Guides
The agent inventory
Find agents in Microsoft Entra and Agent 365, Google Workspace, n8n and Zapier, read only, beside the keys discovery finds at OpenAI, Anthropic and OpenRouter. One row per agent, with owners, verb-level permissions, consent type and lifecycle, the findings that matter, and one click to put each under rules.
Discovery finds the keys your people hold at the model vendors. The inventory goes wider: the agents registered in Microsoft Entra, the apps your staff have let into Microsoft 365 and Google Workspace, and the n8n workflows and Zaps that call a model. Every source is read only. Immiscible never changes anything at Microsoft, Google, n8n or Zapier.
An inventory is what exists; a registry is what you approved. Immiscible keeps both: the inventory lists every agent it found, and your agents under Agents are the registry. The rows marked discovered, not yet governed are the gap between the two, and each has a Govern button.
#Sources
| Source | How it connects | What it reads | What it cannot see |
|---|---|---|---|
| Microsoft Entra and Agent 365 | An administrator signs in and grants consent for the tenant (OAuth) | Entra Agent ID agent identities; every delegated permission grant (oauth2PermissionGrants), with its consent type and scopes; Agent 365’s agent catalogue; last sign-in per app | Sponsors (Microsoft offers them only to an app with write permission); the catalogue without an Agent 365 licence; last sign-in without Entra ID P1 or P2 |
| Google Workspace | An administrator signs in (OAuth) | Every active person’s OAuth tokens: which app, which scopes, whether the app is registered with Google | Service accounts with domain-wide delegation; tokens of suspended people |
| n8n | Your n8n address and an API key | Workflows with at least one AI node, the systems their nodes reach, their credentials (names, never secrets), the last run | n8n’s own users; projects on plans without them |
| Zapier | The person signs in to Zapier (OAuth, zap:all) | That person’s Zaps that have an AI step (ChatGPT, Anthropic, AI by Zapier and the like) | Zapier Agents, Zapier MCP servers, and anyone else’s Zaps. Zapier’s API lists only the Zaps the connecting person owns |
| OpenAI, Anthropic, OpenRouter | Discovery’s admin key | Each key and service account, as one row each | See Discovery |
Zapier issues OAuth credentials only to an integration published in its App Directory, so the Zapier source works only once the operator of your deployment has that approval and has set ZAPIER_CLIENT_ID and ZAPIER_CLIENT_SECRET. Until then the console says so. Instinct publishes no API, so it is not a source; see agents without an API.
Microsoft, Google, n8n and Zapier do not endorse or partner with Immiscible. These are their published APIs, used as documented.
#One row per agent
Each agent is one row, joined across sources by a join key: the Entra service principal’s id, a Google OAuth client id, an n8n workflow, a Zap, or a vendor key. An Entra agent identity and the grants made to it are one row; so are an Agent 365 package and the app behind it. Discovered via lists every source that saw it.
| Field | Where it comes from |
|---|---|
| Business owner, technical owner | The one person who granted a Google token, or a vendor key’s creator; otherwise you name them |
| Purpose | Agent 365’s description or an A2A Agent Card; otherwise yours |
| Connected systems | The resource a grant is for, the apps an n8n workflow or a Zap reaches |
| Permissions | At verb level: read or export; create, update or delete; send or share; approve. Read from the scope names, with each scope listed under its verb |
| Consent type | AllPrincipals (an administrator consented for everyone in the tenant), Principal (one person), an API key, or a person’s OAuth sign-in |
| Credentials | Grant ids, token client ids, n8n credential names, key hints. Never a secret |
| Lifecycle | unreviewed, experimental, pilot, approved, production, deprecated, decommissioned. Every row starts unreviewed |
| Last authenticated | Entra sign-in activity, an n8n run, a Zap’s last successful run, a key’s last use |
| Risk class | high: approves, or writes under tenant-wide consent, or an unregistered client that writes; medium: writes or sends, or reads under tenant-wide consent; low: reads; unknown: no source said |
A permission is a dated claim, not a guarantee. Each row keeps what every source said and when (observedAt). A grant can change a minute after a sync, and an MCP server can offer different tools to each request, so treat the permissions as what to check, re-derived on every sync.
#Findings
| Finding | When |
|---|---|
| Tenant-wide grant | A grant with consent type AllPrincipals. Shown first |
| Anonymous client that writes | A Google token from an app not registered with Google, holding a scope that writes or sends. Shown first |
| New scope | A known agent gains a scope since the last sync |
| New tenant-wide grant | A known agent gains an AllPrincipals grant |
| 90 days idle | No authentication for 90 days; resolved when it authenticates again |
| Production with no business owner | An agent in production with nobody named. Moving an agent into production needs a business owner |
| Present after decommission | You decommissioned it, but its source still reports it |
Every finding, sync and change is a record in the workspace’s evidence ledger.
#Govern, ignore, decommission
- Govern registers the agent under Agents, acting for its business owner (or you), and shows a governed key once. A key found at a model vendor goes through discovery’s own path, so both stay in step.
- Ignore keeps a row out of the way.
- Decommission records how: we deleted the credential (a governed agent is stopped), or the grant was revoked at the provider. Immiscible cannot revoke a grant at Microsoft, Google, n8n or Zapier, so the second is your statement; the next sync checks it.
#Exports and Agent Cards
GET /api/w/:wid/inventory/export.cdx.jsongives the inventory as a CycloneDX 1.7 (ECMA-424) bill of materials: each agent a component, its fields asimmiscible:properties, its systems as services.- If an agent publishes an A2A Agent Card, give its address and the card’s description, skills and auth schemes are kept as one more dated claim on the row.
#What this maps to
In our own words, for the person filling in a control framework:
| Control | How the inventory meets it |
|---|---|
| NIST SP 800-53 CM-8, system component inventory | One row per agent, no double counting across sources, reviewed on every sync |
| CM-8(2), automated maintenance | Scheduled syncs (every 12 hours by default) |
| CM-8(3), automated detection of unauthorised components | Discovered, not yet governed; findings in the console and the evidence ledger |
| CM-8(4), accountability information | Business and technical owners; production needs a business owner |
| NIST AI RMF GOVERN 1.6, an inventory of AI systems | The inventory and its CycloneDX export |
#For the operator
| Source | Set up once |
|---|---|
| Microsoft | The sign-in app (MICROSOFT_CLIENT_ID, MICROSOFT_CLIENT_SECRET), with the redirect URI PUBLIC_URL/connect/inventory/microsoft/callback and these application permissions added: AgentIdentity.Read.All, Directory.Read.All, and optionally CopilotPackages.Read.All and AuditLog.Read.All |
| Google Workspace | The directory app (GOOGLE_DIRECTORY_CLIENT_ID) or the sign-in client, with the redirect URI PUBLIC_URL/connect/inventory/google_workspace/callback and the Admin SDK API enabled |
| Zapier | ZAPIER_CLIENT_ID and ZAPIER_CLIENT_SECRET, from an integration Zapier has published, with the redirect URI PUBLIC_URL/connect/inventory/zapier/callback |
| n8n | Nothing: each workspace pastes its own key |