Query Details

Agent Multi Project Activity

Query

id: 17283940-7777-4f13-9207-0123456789d1
name: Agent - Same agent active across multiple projects
description: |
  Hunts a single Foundry / Agent Service agent (gen_ai.agent.name) whose
  spans appear under two or more distinct project IDs
  (microsoft.foundry.project.id) in the same window. An agent identity
  crossing project boundaries is the tenancy-boundary / lateral-reach
  shape - a shared or cloned agent reaching data planes it should not, or
  an identity reused across environments. Low noise: most agents live in
  exactly one project, so multi-project agents stand out cleanly.

  Reads gen_ai.agent.name and microsoft.foundry.project.id from the
  AppDependencies span property bag (Properties).
query: |
  let lookback = 1d;
  AppDependencies
  | where TimeGenerated > ago(lookback)
  | where isnotempty(Properties["gen_ai.agent.name"])
  | where isnotempty(Properties["microsoft.foundry.project.id"])
  | extend
      Agent     = tostring(Properties["gen_ai.agent.name"]),
      ProjectId = tostring(Properties["microsoft.foundry.project.id"]),
      Model     = tostring(Properties["gen_ai.request.model"]),
      ConvId    = tostring(Properties["gen_ai.conversation.id"])
  | summarize
      Projects        = make_set(ProjectId, 20),
      DistinctProjects = dcount(ProjectId),
      Conversations   = dcount(ConvId),
      Calls           = count(),
      Models          = make_set(Model, 10),
      FirstSeen       = min(TimeGenerated),
      LastSeen        = max(TimeGenerated)
      by Agent
  | where DistinctProjects >= 2
  | project
      LastSeen, Agent, DistinctProjects, Projects, Conversations,
      Calls, Models, FirstSeen
  | order by DistinctProjects desc, Calls desc
tactics:
  - LateralMovement
  - Discovery
techniques:
  - T1078
  - T1580
tags:
  - Sentinel-As-Code
  - Custom
  - Foundry
  - AI

Explanation

This query is designed to identify agents (specifically, Foundry/Agent Service agents) that are active across multiple projects within a specified time window (the past day). The goal is to detect agents that might be improperly shared or cloned across different projects, which could indicate a security risk such as unauthorized access or data exposure.

Here's a simplified breakdown of what the query does:

  1. Time Frame: It looks at data from the last day (lookback = 1d).

  2. Data Source: It examines the AppDependencies table, focusing on specific properties related to agents and projects.

  3. Filtering: It filters out records where the agent name and project ID are not empty.

  4. Data Extraction: It extracts and converts relevant properties into strings, such as agent name, project ID, model, and conversation ID.

  5. Aggregation: It summarizes the data by agent, calculating:

    • The set of project IDs the agent is associated with.
    • The number of distinct projects the agent is involved in.
    • The number of unique conversations and total calls.
    • The set of models used.
    • The first and last time the agent was seen.
  6. Condition: It filters for agents that are associated with two or more distinct projects.

  7. Output: It projects relevant information such as the last seen time, agent name, number of distinct projects, list of projects, number of conversations, total calls, models used, and first seen time.

  8. Sorting: It orders the results by the number of distinct projects and then by the number of calls, both in descending order.

The query is tagged with tactics and techniques related to lateral movement and discovery, indicating its use in identifying potential security threats.

Details

David Alonso profile picture

David Alonso

Released: June 8, 2026

Tables

AppDependencies

Keywords

AgentFoundryProjectPropertiesAppDependenciesTimeGeneratedModelConversation

Operators

letagowhereisnotemptyextendtostringsummarizemake_setdcountcountminmaxbyprojectorder bydesc

Actions