Agent Identity Registry
The Agent Identity Registry provides a persistent identity layer for AI agents. Each registered agent receives a Decentralized Identifier (DID) bound to its organization, with rotatable key material and capability attestations. This is the foundation for agent-to-agent trust and enables cryptographic authentication in MCP tool calls and multi-agent workflows.
Overview
Unlike ephemeral session tokens, agent identities are persistent and organization-bound. An agent's capabilities are still ephemeral — task-scoped, time-bound, and issued dynamically through mandates — but the identity itself persists across sessions and mandate lifecycles.
| Concept | Description |
|---|---|
| Agent DID | A persistent decentralized identifier in the format did:web:agents.mandaitor.io:{agent_id} |
| Key Material | A key pair for signing: one the agent holds (public_key_jwk, EC on P-256 or P-384), or one Mandaitor holds in KMS (key_algorithm, ES256 unless named). Supports rotation with 30-day grace period for old keys |
| Mandate Binding | Agents can be bound to one or more mandates, establishing their authorized scope |
| Lifecycle | Agents follow the same lifecycle as mandates: ACTIVE → SUSPENDED → REVOKED |
Registering an Agent
Registering an agent, rotating its key, binding it to mandates and changing its lifecycle need tenant:write: a tenant administrator, on the dashboard's Agent Registry page or through the API from their own session. An API key is refused with 403. Reading agents and their DID documents needs no more than access to the tenant.
An agent that will ask Mandaitor to act, through the MCP server or the execution API, registers the public half of a key only it holds:
// adminClient: a tenant administrator's session. API keys cannot register agents.
const agent = await adminClient.post("/agents", {
name: "procurement-agent",
description: "Releases purchase requisitions at plant 1000",
// EC on P-256 (ES256) or P-384 (ES384). The private key stays with the agent.
public_key_jwk: { kty: "EC", crv: "P-256", x: "f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU", y: "x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0" },
});
console.log(agent.agent_id); // "agt_01HXYZ..."
console.log(agent.did); // "did:web:agents.mandaitor.io:agt_01HXYZ..."
Getting Started shows how to make such a key. Without public_key_jwk, Mandaitor mints a key it holds in KMS (key_algorithm, ES256 unless named). The agent cannot sign with that key, so it can never open a session for the MCP server or the execution API.
Its environment
An agent that requests executions acts in one environment, such as qas or prd: lower case, starting with a letter, at most 32 characters. Name it at registration with environment; an agent given none is in default. It never changes, and the agent's sessions carry it. The agent's executions use the tools enabled in its environment, which run only on that environment's connectors, so an agent registered for a test system never reaches production. An agent that must act in two environments is registered twice. See Environments.
Resolving a DID Document
Each agent's DID resolves to a standard DID Document containing its public key material:
GET /agents/{id}/did
Content-Type: application/did+json
The response follows the W3C DID Core specification and includes verification methods that can be used by external systems to verify signatures produced by the agent.
Key Rotation
Agent keys should be rotated periodically. During rotation, the old key remains valid for 30 days to allow in-flight operations to complete:
const rotated = await adminClient.post(`/agents/${agentId}/rotate`, {
reason: "Scheduled quarterly rotation",
});
// "Key rotated successfully. Old key scheduled for deletion in 30 days."
An agent that holds its own key sends the new public key, as public_key_jwk. Without one, Mandaitor mints a key it holds, and the agent can no longer sign the client assertion an MCP session needs. Either way, only the new key authenticates the agent from then on; sessions it already holds last until they expire. In the dashboard, the Agent Registry asks such an agent for its new public key.
Binding Agents to Mandates
An agent must be bound to at least one mandate before the MCP Authorization Server issues it a session. Binding lets the agent present a mandate its principal delegated to it — the mandate's delegate.subject_id must be the agent's DID or agent id:
await adminClient.post(`/agents/${agentId}/bind`, {
mandate_id: "mdt_abc123",
});
Binding a mandate delegated to anyone else is refused with 409 and code MANDATE_DELEGATE_MISMATCH. A binding grants no authority of its own: the authority is the mandate's, and only the delegate the principal named may use it.
A single agent can be bound to multiple mandates simultaneously. A binding does not decide what the agent may do: an execution is decided on every active mandate naming the agent, bound or not. To take a mandate's authority away, suspend or revoke the mandate. Bindings can also be removed without revoking the agent, which is useful when a project ends or a mandate is superseded.
| Operation | Endpoint | Purpose |
|---|---|---|
| List agents | GET /agents | Returns registered agents for the tenant. |
| Get agent | GET /agents/{id} | Retrieves one agent including lifecycle status and binding metadata. |
| Bind mandate | POST /agents/{id}/bind | Adds a binding to a mandate delegated to this agent; 409 for any other mandate. |
| Unbind mandate | DELETE /agents/{id}/bind/{mandateId} | Removes one mandate binding while keeping the agent active. Sessions the agent already holds stop listing that mandate at once. |
await adminClient.delete(`/agents/${agentId}/bind/${mandateId}`);
Agent Lifecycle
Agents support the same lifecycle transitions as mandates:
| Action | Endpoint | Effect |
|---|---|---|
| Suspend | POST /agents/{id}/suspend | Temporarily disables the agent. Every MCP session it holds ends at once, and it cannot obtain a token while suspended. |
| Reactivate | POST /agents/{id}/reactivate | Re-enables a suspended agent. It requests a new token: sessions from before the suspension stay ended. |
| Revoke | POST /agents/{id}/revoke | Permanently disables the agent. Its keys are revoked and every MCP session it holds ends. Cannot be undone. |
Revoking an agent is permanent. Its keys are revoked and drop out of its DID document, its MCP sessions end, and it can never obtain a token again. Its mandate bindings are not removed, and the mandates themselves stay active until you revoke them. This action cannot be reversed.