Output Format

Example Output

Service (Cognitive Services / AI Foundry account)

{
  "type": "service",
  "timestamp": "2026-07-15T15:48:55-04:00",
  "urn": "urn:ai:service:azure:my-foundry-account/<resource-group>/<subscription-id>",
  "url": "https://portal.azure.com/#resource/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.CognitiveServices/accounts/my-foundry-account/overview",
  "extra": {
    "arm_id": "/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.CognitiveServices/accounts/my-foundry-account",
    "resource_endpoint": "https://my-foundry-account.cognitiveservices.azure.com/",
    "kind": "AIServices",
    "location": "eastus",
    "provider": "azure",
    "public_network_access": "Enabled",
    "network_default_action": "Allow",
    "diagnostic_logging_enabled": false,
    "encryption_key_urn": "urn:pubkey:sha256:<fingerprint>",
    "managed_identity_type": "SystemAssigned",
    "managed_identity_principal_id": "<account-managed-identity-object-id>",
    "created_by": "owner@example.com",
    "created_by_type": "User",
    "created_at": "2026-06-16T19:39:26Z",
    "last_modified_by": "owner@example.com",
    "last_modified_by_type": "User",
    "last_modified_at": "2026-06-16T19:39:26Z",
    "tags": {"cost-center": "ai-platform"},
    "role_assignments": [
      {
        "role_definition_id": "/subscriptions/<subscription-id>/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe",
        "role_name": "Storage Blob Data Contributor",
        "role_type": "BuiltInRole",
        "scope": "/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.Storage/storageAccounts/mystorage",
        "scope_type": "resource"
      }
    ],
    "resource_group": "<resource-group>",
    "subscription_id": "<subscription-id>",
    "subscription_name": "Production East"
  }
}

Ownership fields (created_by, created_by_type, created_at, last_modified_by, last_modified_by_type, last_modified_at, tags) come straight from ARM systemData/tags and are emitted on service and project records whenever present. role_assignments lists the Azure RBAC roles held by the resource's own identity (the account/project system-assigned managed identity, or the agent's Entra Agent Identity instance_principal_id) within the scanned subscription — i.e. what that identity is allowed to touch, not who can administer the resource. The query is made at subscription scope, so it returns assignments made directly on the subscription or any resource group/resource inside it, plus those inherited from the subscription's management-group ancestry and the tenant root (scope_type tells them apart). It does not enumerate roles the same identity holds in other subscriptions; treat role_assignments as subscription-local RBAC, not a tenant-wide entitlement inventory. If reading role assignments fails with 401/403 for any principal, the field is omitted for every record of that account rather than emitted partially. Only role/scope metadata is emitted; it is omitted entirely when the scanner cannot read role assignments (see Required Permissions) and when the identity simply holds none — an Entra Agent Identity has no Azure RBAC assignments unless someone grants them, so an agent record without role_assignments is not by itself a permissions problem; check the service/project records in the same scan, whose managed identities are more likely to hold assignments.

Secret (account key slot)

{
  "type": "secret",
  "urn": "urn:secret:name:azure/<subscription-id>/<resource-group>/my-foundry-account/key1:current",
  "extra": {
    "account": "my-foundry-account",
    "key_slot": "key1",
    "origin": "azure_generated",
    "subscription_name": "Production East"
  }
}

Key reference (customer-managed encryption key)

A CMK reference is classified by the key type read from Key Vault: an RSA/EC key is emitted as a pubkey (with the reconstructed public key PEM), a symmetric (OCT) key as a symkey, and an unknown or unreadable key as a secret. The deprecated generic key type is never emitted. The example below shows the common RSA case:

{
  "type": "pubkey",
  "urn": "urn:pubkey:sha256:<fingerprint>",
  "url": "https://my-vault.vault.azure.net/keys/cmk-key/abc123",
  "pubkey_pem": "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n",
  "extra": {
    "account": "my-foundry-account",
    "key_vault_uri": "https://my-vault.vault.azure.net",
    "key_name": "cmk-key",
    "key_version": "abc123",
    "key_type": "RSA",
    "purpose": "encryption_at_rest",
    "subscription_name": "Production East"
  }
}

Model (deployment)

{
  "type": "model",
  "urn": "urn:ai:model:azure:gpt-4o/my-foundry-account/<resource-group>/<subscription-id>",
  "url": "https://portal.azure.com/#resource/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.CognitiveServices/accounts/my-foundry-account/deployments/gpt-4o",
  "extra": {
    "arm_id": "/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.CognitiveServices/accounts/my-foundry-account/deployments/gpt-4o",
    "deployment_name": "gpt-4o",
    "model_type": "gpt-4o",
    "model_version": "2024-11-20",
    "model_format": "OpenAI",
    "rai_policy_name": "strict-production-policy",
    "provisioning_state": "Succeeded",
    "model_capabilities": {
      "inference": "true",
      "fine_tune": "true"
    },
    "resource_endpoint": "https://my-foundry-account.cognitiveservices.azure.com/",
    "sku_name": "GlobalStandard",
    "sku_capacity": 100,
    "model_requests_total": 0,
    "usage_region": "eastus",
    "usage_interval": "PT1H",
    "usage_namespace": "Microsoft.CognitiveServices/accounts",
    "usage_period_start": "2026-08-23T15:49:53-04:00",
    "usage_period_end": "2026-08-24T15:49:53-04:00",
    "subscription_name": "Production East",
    "guardrail_policy_assignments": [
      {
        "assignment_id": "/subscriptions/<subscription-id>/providers/Microsoft.Authorization/policyAssignments/require-content-safety",
        "definition_id": "/providers/Microsoft.Authorization/policyDefinitions/1234abcd-5678-...",
        "scope": "/subscriptions/<subscription-id>",
        "enforcement_mode": "Default",
        "compliance_state": "NonCompliant",
        "evaluated_at": "2026-08-31T12:00:00Z",
        "exemption": {
          "category": "Waiver",
          "expires_on": "2027-01-01T00:00:00Z"
        }
      }
    ]
  }
}

guardrail_policy_assignments lists the Azure Policy assignments applicable to this deployment (including ones inherited from subscription/resource-group scope), each enriched with its latest Policy Insights compliance evaluation when one exists — compliance_state/evaluated_at are omitted from an entry if Policy Insights hasn't evaluated it yet. exemption is present only when the assignment has a matching Azure Policy exemption (fetched via a raw HTTP call — no SDK client exists for this endpoint in the current Azure SDK for Go). This is a distinct governance mechanism from the RAI content-filter policy above: RAI describes what content-safety behavior is enforced; guardrail_policy_assignments describes what Azure Policy requires and whether the deployment currently complies.

Responsible AI policy and blocklist

Policies and blocklists use the generic ai_asset envelope because the shared AI taxonomy has no dedicated guardrail type. extra.asset_type identifies the concrete resource.

{
  "type": "ai_asset",
  "urn": "urn:ai:ai_asset:azure:rai-policy/strict-production-policy/my-foundry-account/<resource-group>/<subscription-id>",
  "url": "https://portal.azure.com/#resource/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.CognitiveServices/accounts/my-foundry-account/raiPolicies/strict-production-policy",
  "extra": {
    "asset_type": "rai_policy",
    "account": "my-foundry-account",
    "policy_name": "strict-production-policy",
    "base_policy_name": "Microsoft.DefaultV2",
    "policy_type": "UserManaged",
    "mode": "Blocking",
    "content_filters": [
      {
        "name": "Hate",
        "source": "Prompt",
        "enabled": true,
        "blocking": true,
        "severity_threshold": "Low"
      }
    ],
    "custom_blocklists": [
      {
        "blocklist_name": "prohibited-terms",
        "source": "Prompt",
        "blocking": true
      }
    ],
    "created_at": "2026-08-01T10:00:00Z",
    "modified_at": "2026-08-15T09:30:00Z"
  }
}
{
  "type": "ai_asset",
  "urn": "urn:ai:ai_asset:azure:rai-blocklist/prohibited-terms/my-foundry-account/<resource-group>/<subscription-id>",
  "extra": {
    "asset_type": "rai_blocklist",
    "account": "my-foundry-account",
    "blocklist_name": "prohibited-terms",
    "description": "Organization prohibited terms",
    "created_at": "2026-07-20T08:00:00Z",
    "modified_at": "2026-07-20T08:00:00Z"
  }
}

URN paths follow a consistent leaf-first convention across all AI asset types:urn:ai:{assetType}:azure:{leafName}/.../{accountName}/{resourceGroup}/{subscriptionId} — the most specific resource name comes first, subscription ID comes last.

Note on model_capabilities key casing: keys are normalized to snake_case (Azure's own casing is inconsistent, e.g. fineTune); values are passed through verbatim.

Project (Foundry project / AML workspace)

{
  "type": "project",
  "urn": "urn:ai:project:azure:my-project/my-foundry-account/<resource-group>/<subscription-id>",
  "url": "https://ai.azure.com/build/overview?wsid=/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.MachineLearningServices/workspaces/my-project",
  "extra": {
    "account": "my-foundry-account",
    "arm_id": "/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.CognitiveServices/accounts/my-foundry-account/projects/my-project",
    "kind": "AIServices",
    "location": "eastus",
    "is_default": true,
    "provisioning_state": "Succeeded",
    "endpoints": {
      "AI Foundry API": "https://my-foundry-account.services.ai.azure.com/api/projects/my-project"
    },
    "managed_identity_type": "SystemAssigned",
    "managed_identity_principal_id": "<project-managed-identity-object-id>",
    "agent_identity_id": "<project-agent-identity-id>",
    "agent_identity_blueprint_id": "<agent-identity-blueprint-app-id>",
    "agent_identity_blueprint_object_id": "<agent-identity-blueprint-object-id>",
    "created_by": "owner@example.com",
    "created_by_type": "User",
    "created_at": "2026-06-16T19:39:36.9944721Z",
    "last_modified_by": "owner@example.com",
    "last_modified_by_type": "User",
    "last_modified_at": "2026-06-16T19:39:36.9944721Z",
    "provider": "azure",
    "resource_group": "<resource-group>",
    "subscription_id": "<subscription-id>",
    "subscription_name": "Production East"
  }
}

The ARM-level project fields (arm_id, endpoints, managed_identity_*, agent_identity_*, ownership, tags, role_assignments) are read from Microsoft.CognitiveServices/accounts/{account}/projects (api-version 2025-06-01) and are present only for Foundry (AIServices) projects; hub-based/AML-workspace projects carry just the base fields. agent_identity_blueprint_id is the project-level Entra Agent Identity blueprint that every native agent's blueprint_client_id in this project should match — a native agent whose blueprint does not match its project's is worth flagging downstream.

Agent (Foundry data-plane agent)

An agent carries the richest metadata of any record — its Foundry/Entra identity, lifecycle state, version status, endpoint auth schemes, and the model deployment it's bound to. No key material or credentials are ever emitted.

Quick note on the 6 ID-shaped fields surfaced for agents — 2 catalog identifiers (which Foundry object this is; no security meaning) and 4 Entra identities (who it authenticates as):

  • agent_id — the human-assigned catalog ID (a slug, e.g. my-agent); also the literal path segment in the agent's own URL (/agents/<agent_id>). Not a security identity.
  • agent_guid — internal Foundry reference; not an Entra identity, not used for auth.
  • blueprint_principal_id / blueprint_client_id — Entra SP / app ID for the agent's blueprint/template. Shared by all agents of that type, so not unique to one agent. Used to prove/manage the template, not for live tool calls.
  • instance_principal_id / instance_client_id — Entra SP / app ID for this specific agent instance. This is the identity presented at runtime when the agent calls a tool/MCP server, and is the "Entra Agent ID" shown in the Foundry portal.
  • blueprint_principal_display_name / instance_principal_display_name — optional Entra workload-principal labels returned by Foundry. These mutable labels improve readability but do not identify a human owner and must not replace the principal IDs for correlation.
{
  "type": "agent",
  "urn": "urn:ai:agent:azure:<agent-guid>/my-project/my-foundry-account/<resource-group>/<subscription-id>",
  "url": "https://my-foundry-account.services.ai.azure.com/api/projects/my-project/agents/my-agent?api-version=v1",
  "extra": {
    "account": "my-foundry-account",
    "project": "my-project",
    "project_urn": "urn:ai:project:azure:my-project/my-foundry-account/<resource-group>/<subscription-id>",
    "agent_id": "my-agent",
    "agent_name": "my-agent",
    "agent_guid": "<agent-guid>",
    "blueprint_principal_id": "<blueprint-principal-id>",
    "blueprint_client_id": "<blueprint-client-id>",
    "blueprint_principal_display_name": "<blueprint-principal-display-name>",
    "instance_principal_id": "<instance-principal-id>",
    "instance_client_id": "<instance-client-id>",
    "instance_principal_display_name": "<instance-principal-display-name>",
    "auth_schemes": ["Entra"],
    "state": "enabled",
    "is_draft": false,
    "version_number": "1",
    "version_status": "active",
    "created_date": "2026-08-19T18:57:46-04:00",
    "model_deployment_name": "gpt-4o",
    "model_urn": "urn:ai:model:azure:gpt-4o/my-foundry-account/<resource-group>/<subscription-id>",
    "protocols": ["responses"],
    "origin_kind": "foundry_native",
    "discovered_via": ["agents_api"],
    "identity_type": "entra_agent_identity",
    "tools": ["web_search", "mcp", "connected_agent", "a2a"],
    "permitted_operations": [
      {"server_label": "github", "require_approval_configured": false}
    ],
    "tool_connection_urns": [
      "urn:ai:mcp_server:azure:github/my-project/my-foundry-account/<resource-group>/<subscription-id>",
      "urn:ai:tool:azure:news-scanner/my-project/my-foundry-account/<resource-group>/<subscription-id>"
    ],
    "connected_agent_urns": [
      "urn:ai:agent:azure:<other-agent-guid>/my-project/my-foundry-account/<resource-group>/<subscription-id>",
      "urn:ai:agent:azure:<news-agent-guid>/my-project/my-foundry-account/<resource-group>/<subscription-id>"
    ],
    "resource_endpoint": "https://my-foundry-account.cognitiveservices.azure.com/",
    "provider": "azure",
    "subscription_name": "Production East"
  }
}

tools lists the tool types declared on the agent. Foundry models a peer agent as just another tool the caller may invoke, so agent→agent edges come from two tool types, both resolved into the same field: connected_agent tools (classic Agents API/SDK shape, target referenced by agent id/name in the same project) and a2a tools (new-portal Agent2Agent tool, target referenced through a project connection). Either way the target agent record's URN lands in connected_agent_urns; tools carrying a project_connection_id (MCP servers, remote tools, and the A2A connection itself) additionally become tool_connection_urns (URNs of tool/mcp_serverrecords). References that don't match a discovered asset are kept raw in unresolved_tool_connection_urns / unresolved_connected_agent_ids rather than fabricated — for an a2a tool the unresolved entry is the connection name.

Also visible through APIM (apim_registrations). When a native agent has additionally been registered as an asset in an APIM gateway of the same subscription, the registration is folded into the native record rather than emitted twice: discovered_via becomes ["agents_api", "apim_api"] and apim_registrations lists each registration — gateway, resource_group, subscription_id, api_name, registration_protocol (a2a/mcp/http), and the sanitized gateway_endpoint and agent_card_url. The raw backend URL is not carried over. Absent when the agent is not registered anywhere.

Human-in-the-loop (permitted_operations). One entry per mcp tool (keyed by server_label, or type when unlabeled) carrying the tool's require_approval policy and, when set, allowed_tools / allowed_tools_read_only. When an mcp tool omits require_approval, the entry carries require_approval_configured: false and no require_approval value: the plugin reports only what the agent definition states and does not infer the platform default. Consumers that want to reason about the effective runtime policy apply Foundry's documented default themselves; the flag lets them tell "explicitly configured" from "left unset".

How an a2a edge is resolved ("follow the address"): the tool points at a RemoteA2A project connection (emitted as a tool record with protocols: ["a2a"], auth_type: AgenticIdentityToken; the caller's project_connection_id is the connection's full ARM id). The connection's target URL is then matched, without any network call, against (1) native Foundry agent endpoints (https://<account>.services.ai.azure.com/api/projects/<project>/agents/<id>/...), (2) the gateway endpoint of the APIM MCP API Foundry creates when the peer is a Foundry agent — that mcp_server record also carries target_agent_urn — and (3) the gateway endpoint / backend of any APIM-registered agent record (HTTP or A2A registration). A target that matches none of these — e.g. an external endpoint typed in via "Connect via endpoint" — stays in unresolved_connected_agent_ids with the connection's url available on the tool record; the plugin never probes it to find out whether an agent really answers there, that judgement is left downstream.

Tool / MCP server (project connection)

A tool and an mcp_server share the same shape — an mcp_server is a tool connection further identified as a Model Context Protocol server. The auth_type is the non-secret credential type of the connection (see the enum reference below); credential values are never fetched or emitted.

{
  "type": "mcp_server",
  "urn": "urn:ai:mcp_server:azure:GitHub/my-project/my-foundry-account/<resource-group>/<subscription-id>",
  "url": "https://api.githubcopilot.com/mcp",
  "extra": {
    "account": "my-foundry-account",
    "project": "my-project",
    "project_urn": "urn:ai:project:azure:my-project/my-foundry-account/<resource-group>/<subscription-id>",
    "connection_id": "/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.CognitiveServices/accounts/my-foundry-account/projects/my-project/connections/GitHub",
    "connection_type": "RemoteTool",
    "auth_type": "CustomKeys",
    "resource_endpoint": "https://my-foundry-account.cognitiveservices.azure.com/",
    "provider": "azure",
    "subscription_name": "Production East"
  }
}

AI asset (infrastructure-dependency connection)

An ai_asset is a project connection that is part of the AI footprint but isn't a callable tool — for example an Application Insights or Container Registry connection. Its actual nature is in extra.connection_type.

{
  "type": "ai_asset",
  "urn": "urn:ai:ai_asset:azure:my-appinsights-conn/my-project/my-foundry-account/<resource-group>/<subscription-id>",
  "url": "https://portal.azure.com/#resource/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/microsoft.insights/components/my-foundry-account-appinsights",
  "extra": {
    "account": "my-foundry-account",
    "project": "my-project",
    "project_urn": "urn:ai:project:azure:my-project/my-foundry-account/<resource-group>/<subscription-id>",
    "connection_id": "/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.CognitiveServices/accounts/my-foundry-account/projects/my-project/connections/my-appinsights-conn",
    "connection_type": "AppInsights",
    "auth_type": "ApiKey",
    "resource_endpoint": "https://my-foundry-account.cognitiveservices.azure.com/",
    "provider": "azure",
    "subscription_name": "Production East"
  }
}

Index (AI Search index)

An index is emitted once per search index — either from a standalone AI Search service (shown below, with search_service/field_count/vector_search_enabled) or from a Foundry project's connected indexes (account/project instead of search_service, no field/vector metadata). No document content is ever read — only index-level metadata.

{
  "type": "index",
  "urn": "urn:ai:index:azure:my-index/my-search-service/<resource-group>/<subscription-id>",
  "url": "https://my-search-service.search.windows.net/indexes/my-index",
  "extra": {
    "provider": "azure",
    "search_service": "my-search-service",
    "resource_group": "<resource-group>",
    "subscription_id": "<subscription-id>",
    "field_count": 12,
    "vector_search_enabled": true,
    "subscription_name": "Production East"
  }
}

Gateway (API Management AI gateway) and Endpoint

{
  "type": "gateway",
  "urn": "urn:ai:gateway:azure:my-apim/<resource-group>/<subscription-id>",
  "url": "https://portal.azure.com/#resource/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.ApiManagement/service/my-apim/overview",
  "extra": {
    "arm_id": "/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.ApiManagement/service/my-apim",
    "gateway_url": "https://my-apim.azure-api.net",
    "location": "eastus",
    "sku_name": "Premiumv2",
    "provisioning_state": "Succeeded",
    "public_network_access": "Enabled",
    "managed_identity_type": "SystemAssigned",
    "policy_summary": {
      "rate_limit_present": true,
      "rate_limit_calls": 100,
      "rate_limit_renewal_period_seconds": 60,
      "jwt_validation_present": true
    },
    "subscription_name": "Production East"
  }
}
{
  "type": "endpoint",
  "urn": "urn:ai:endpoint:azure:foundry-backend/my-apim/<resource-group>/<subscription-id>",
  "url": "https://my-foundry-account.services.ai.azure.com",
  "extra": {
    "gateway": "my-apim",
    "resource_group": "<resource-group>",
    "subscription_id": "<subscription-id>",
    "ai_provider": "azure_foundry",
    "protocol": "http",
    "subscription_name": "Production East"
  }
}

policy_summary is derived from the gateway's service-level (global, "All APIs") policy — the one at Microsoft.ApiManagement/service/{name}/policies/policy; per-API, per-operation and per-product policies are not read, so a rate limit set on a single API alone does not appear here. It contains only presence flags and numeric attributes — rate_limit_*, rate_limit_by_key_*, quota_*, quota_by_key_* (*_present, *_calls, *_renewal_period_seconds), ip_filter_present/ip_filter_action, cors_present, jwt_validation_present, client_certificate_validation_present. The raw policy XML (including any IP ranges, JWT issuers or key names it contains) is never emitted. The field is omitted when the policy can't be read (missing Microsoft.ApiManagement/service/policies/read, logged as a non-fatal 403) or when the global policy defines none of those elements (APIM's default global policy is <inbound/> + <forward-request/>, which yields no summary). Absence of the field therefore means either "not readable" or "nothing to summarise" — see Troubleshooting for how to tell them apart.

Agent registered via Register asset (detected through an APIM gateway)

Emitted only for APIs Azure itself marks isAgent: true (an authoritative flag, not an inference — see "Note on registered-agent detection" above) whose effective backend URL (serviceUrl, else jsonRpcProperties.BackendUrl) doesn't match an agent this same scan already discovered natively — those are merged into the native record instead (see the note above). extra.agent_name comes from the API's own agent.name field, when set. extra.origin_account, extra.origin_project, and extra.origin_agent_id are present only when the URL fits the Foundry project-agent shape — a genuinely external (non-Foundry) registration carries only origin_url.

Every agent record (native or registered) also carries three classification fields so downstream consumers don't have to infer provenance from which optional fields happen to be present:

Field

Values

Meaning

origin_kind

foundry_native

Discovered through the project's /agents data-plane API.


foundry_registered_via_gateway

Registered asset whose Agent URL points at a Foundry project agent that this scan did not see natively (other subscription, deleted, or not readable).


external_registered

Registered asset whose Agent URL is not a Foundry project-agent URL — the customer-declared "external agent" bucket.

discovered_via

list of agents_api, apim_api

Every discovery surface that produced the record itself. A list on purpose so a future surface (e.g. an Entra agent-identity enumeration) can be appended without a schema change. Enrichment calls such as RBAC role_assignments do not add an entry — they decorate a record, they don't discover one.

identity_type

entra_agent_identity

The agent authenticates as an Azure-native Entra Agent Identity (instance_principal_idpresent).


unknown

No identity observable from this scan — always the case for APIM-registered agents, whose runtime identity APIM knows nothing about. A proxy-issued SPIFFE identity is not inferred here; a separate SPIRE/proxy discovery would join on instance_principal_id.

identity_type is not the same thing as auth_schemes: auth_schemes is inbound — how callers must authenticate to the agent (Foundry Entra/BotService…, or APIM oauth2/openid); identity_type is outbound — the principal the agent itself acts as. An external agent can demand oauth2 from callers while its own identity stays unknown.

Registered agents additionally expose the APIM API's own metadata, all read from the same apis list call (no extra request): registration_protocol (APIM's API type — a2a, mcp, http, … — falling back to whichever of a2aProperties/mcpProperties is populated, then http), management_portal_url (customer-supplied, sanitized like the Agent URL), provider_name, api_type, api_path, transport_protocols (https/http/ws — APIM transport, distinct from native agents' protocols), subscription_key_required (false means the gateway accepts calls without an APIM subscription key) and auth_schemes (oauth2/openid, names only — the authorization-server settings themselves are never emitted). Empty values are omitted. The URN's first segment is the APIM API name (emitted as api_name), which is unique per gateway — agent_id is not: for an "A2A Agent" API authored directly in APIM, Azure fills agent.id from the peer's Agent Card (e.g. hello-world-agent), so two such APIs fronting same-named agents would otherwise collide. For Foundry-registered assets api_name and agent_id are identical.

A2A registrations. Registering an asset with protocol A2A (or adding an "A2A Agent" API directly in APIM) produces an API with type: "a2a", an empty serviceUrl, the agent's runtime endpoint in jsonRpcProperties.BackendUrl and the peer's Agent Card location in a2aProperties.agentCardBackendUrl. The plugin uses the JSON-RPC backend as the agent URL / origin_url (so origin_kind and native dedup work the same as for HTTP/REST registrations) and emits the card location as agent_card_url — the agent↔agent relation edge. The card itself is never fetched; both URLs are sanitized like every customer-supplied URL. APIM hides a2a/mcp APIs from older api-versions, so the apis list is read with 2024-10-01-preview.

{
  "type": "agent",
  "urn": "urn:ai:agent:azure:a2atestlocal-g8xt44og/my-apim/<resource-group>/<subscription-id>",
  "url": "https://agent.partner.example.com",
  "extra": {
    "api_name": "a2atestlocal-g8xt44og",
    "agent_id": "a2atestlocal-g8xt44og",
    "agent_name": "A2ATestLocal",
    "identity_type": "unknown",
    "agent_card_url": "https://agent.partner.example.com/.well-known/agent-card.json",
    "api_type": "a2a",
    "registration_protocol": "a2a",
    "origin_kind": "external_registered",
    "origin_url": "https://agent.partner.example.com",
    "discovered_via": ["apim_api"],
    "gateway": "my-apim"
  }
}

MCP server exposed through an APIM gateway

APIM APIs of type: "mcp" (APIM → APIs → MCP Servers) are MCP servers, not agents: Azure sets isAgent: false on them, so they are emitted as mcp_serverrecords rather than agent. The URL is the sanitized backend MCP endpoint (backend URL resolved via backendId + mcpProperties.endpoints.mcp.uriTemplate); gateway_endpoint is the APIM-side URL consumers call. Also emitted: api_name, display_name,api_path, api_type, mcp_uri_template, backend_name, transport_protocols, subscription_key_required, auth_schemes, is_federation_router (only when true) and discovered_via: ["apim_api"]. The server's tool list is never requested, and mcpProperties.federation is not emitted. These records use extra.gateway, not extra.account/extra.project, which distinguishes them from the project-connection mcp_server records described above. When the backend URL is a native Foundry agent's own endpoint (the shape Foundry creates for its Agent2Agent tool), the record also carries target_agent_urn pointing at that agent record.

{
  "type": "mcp_server",
  "urn": "urn:ai:mcp_server:azure:docs-mcp/my-apim/<resource-group>/<subscription-id>",
  "url": "https://mcp.example.com/api/mcp",
  "extra": {
    "api_name": "docs-mcp",
    "display_name": "Docs MCP",
    "api_path": "docs-mcp",
    "api_type": "mcp",
    "gateway": "my-apim",
    "gateway_endpoint": "https://my-apim.azure-api.net/docs-mcp",
    "mcp_uri_template": "/api/mcp",
    "transport_protocols": ["https"],
    "subscription_key_required": false,
    "discovered_via": ["apim_api"]
  }
}
{
  "type": "agent",
  "urn": "urn:ai:agent:azure:cross-proj-test-abc123/my-apim/<resource-group>/<subscription-id>",
  "url": "https://other-foundry-account.services.ai.azure.com/api/projects/other-project/agents/other-agent?api-version=v1",
  "extra": {
    "provider": "azure",
    "gateway": "my-apim",
    "resource_group": "<resource-group>",
    "subscription_id": "<subscription-id>",
    "agent_id": "cross-proj-test-abc123",
    "agent_name": "cross-proj-test",
    "origin_url": "https://other-foundry-account.services.ai.azure.com/api/projects/other-project/agents/other-agent?api-version=v1",
    "origin_account": "other-foundry-account",
    "origin_project": "other-project",
    "origin_agent_id": "other-agent",
    "origin_kind": "foundry_registered_via_gateway",
    "discovered_via": ["apim_api"],
    "registration_protocol": "http",
    "api_path": "cross-proj-test-abc123",
    "transport_protocols": ["https"],
    "subscription_key_required": false,
    "subscription_name": "Production East"
  }
}