# Agent identity and DIDs

> How the Agent Gateway derives a deterministic Decentralised Identifier for each agent, from request payload fields, API keys, mTLS certificates, JWT claims, or a static DID configured on the surface.
Agent Gateway assigns every distinct agent a deterministic W3C [Decentralised Identifier (DID)](https://www.w3.org/TR/did-core/). The DID persists across requests and anchors every trace, metric, and policy decision to a verifiable cryptographic root of trust.

The extraction type is configured on the Identity element in the surface builder. The gateway can extract identity from request payload fields, derive it from a stored API key or mTLS certificate, read it from a validated JWT claim, or use a fixed DID. Once derived, the gateway reuses the same DID for subsequent requests from the same agent, with no manual enrolment flow.

## What agent identity is

Agent identity in Agent Gateway is a stable cryptographic identifier derived once and reused across all requests from the same agent. The same identity inputs always produce the same DID, so the gateway recognises the same agent consistently across requests and sessions.

Each agent identity is a did:webvh identifier anchored to the gateway’s domain:

```text
did:webvh:z6MkScAii9T4RDvTegERUhf4esTGNQTzCgP3kfXpjBfgUA:gateway.example.com:surface:9fd06096-0188-4979-aa99-8171cde7090a
```

The format is did:webvh:{SCID}:{domain}:surface:{uuid}:

- {SCID}: the self-certifying identifier derived from the agent’s initial key material.

- {domain}: the gateway’s public domain.

- surface: a fixed segment that scopes agent identities within the gateway.

- {uuid}: the unique identifier of the surface that issued the identity.

did:webvh is domain-hosted and maintains a verifiable key-rotation log anchored to the gateway’s domain. Key rotations are recorded without changing the DID itself, so changes can be audited over time. Agent identities are versioned: you can rotate cryptographic keys while the DID that downstream systems and policies rely on remains unchanged.

## Identity extraction types

The Identity element’s Identity Extraction Type selector determines how the gateway resolves a DID for a request.

| Extraction type | Identity source | DID stability |
| From Payload (identity metadata) | Fields in the request payload marked with x-identity: true. | Unique per distinct combination of field values. |
| From mTLS certificate | Stored client certificate. The DID is keyed on the stored cert record, not the certificate’s key material. | Stable through cert renewal. Uploading a new certificate to the same stored record preserves the DID. Re-pointing to a different stored cert produces a new DID. |
| From API Key | Stored API key. | Stable through key secret rotation. The DID is keyed on the stored key ID, not the secret value. |
| From JWT Claims | Validated JWT claim (default: oid). Optional Namespace Claims such as iss or tid isolate identities across tenants. The same oid value from different tenants produces distinct DIDs. | Stable while the primary claim value and all configured Namespace Claim values are unchanged across tokens. |
| Static DID | Fixed DID configured on the surface. | Same DID for all requests. |

## Agent identity using payload extraction

This corresponds to the From Payload (identity metadata) extraction type in the Identity element configuration.

Every agent that talks through Agent Gateway can be given a verifiable cryptographic identity without a registration round-trip. With this extraction type, the gateway reads the identity descriptor already present in protocol metadata, derives a stable fingerprint from configured fields, and issues or reuses the corresponding DID for that exact agent configuration.

How the descriptor is carried depends on protocol:

- A2A, AP2, and UCP: identity is provided as a protocol extension. The agent declares https://fabric.affinidi.io/extensions/agent-identity/v1 in the extensions array and includes the matching descriptor under the same key in metadata.

- MCP: identity is carried in JSON-RPC metadata under _meta.agentIdentity, keeping identity context separate from tool parameters across HTTP, SSE, and stdio transports.

From there, the gateway extracts values from configured identity fields, canonicalises and hashes them, and looks up an existing identity mapping. If found, it reuses the same DID. If not, it mints a new identity and issues one for that descriptor. The gateway then replaces the raw identity descriptor in the forwarded request with a signed Verifiable Presentation, so the downstream target receives verifiable identity rather than raw descriptor fields.

Other identity binding options are available for transport and caller-credential based flows, including mTLS, API key, and JWT/OIDC bearer token strategies. These options do not require payload identity descriptors and are configured through source authentication modes.

For payload extraction examples, see [Secure a surface](/products/affinidi-trust-fabric/agent-gateway/get-started/secure-a-surface.md) and [A2A surface starter](/products/affinidi-trust-fabric/agent-gateway/how-to-guides/setup/a2a-surface-starter.md).

## How payload extraction derives identity

This section applies to the From Payload (identity metadata) extraction type. Other extraction types derive the DID from stored credentials, JWT claims, or a static value. No payload parsing is involved.

For this extraction type, derivation happens at request time using protocol metadata and payload fields already present in the request. No separate registration step is required.

  Request payload
  →
  Extract x-identity fields
  →
  Sort & canonicalise
  →
  SHA-256 hash
  →
  Lookup in identity store
  →
  Return or mint DID

### Identity schema

Identity derivation relies on a JSON schema that describes the structure of the agent’s request payload. Fields that should contribute to the DID are marked with "x-identity": true. Only those fields are included in the hash computation. All other fields in the payload are available for policy evaluation and payload capture but do not affect the DID.

The example below shows a schema where the agent’s LLM provider, model, cloud provider, region, and environment are all marked as identity fields:

```json
{
  "type": "object",
  "properties": {
    "agentIdentity": {
      "type": "object",
      "properties": {
        "llmInfo": {
          "type": "object",
          "properties": {
            "provider": { "type": "string", "x-identity": true },
            "model":    { "type": "string", "x-identity": true }
          }
        },
        "provisioningInfo": {
          "type": "object",
          "properties": {
            "cloudProvider": { "type": "string", "x-identity": true },
            "region":        { "type": "string", "x-identity": true },
            "environment":   { "type": "string", "x-identity": true }
          }
        }
      }
    }
  }
}
```

### Extraction, hashing, and DID assignment

Extract identity fields

Extract the values of all x-identity fields from the request payload.

Sort and canonicalise

Sort the extracted key-value pairs alphabetically by field path. Build a canonical string in the form field.path1=value1|field.path2=value2|….

For example, an agent running GPT-4 in AWS production produces:

```text
agentIdentity.llmInfo.model=gpt-4|agentIdentity.llmInfo.provider=openai|agentIdentity.provisioningInfo.cloudProvider=aws|agentIdentity.provisioningInfo.environment=production|agentIdentity.provisioningInfo.region=us-east-1
```

The same field values always produce the same canonical string. Changing any value changes the string and produces a different DID.

Compute SHA-256 hash

Hash the canonical string with SHA-256 to produce a fixed-length fingerprint used as the identity key.

Look up or mint a DID

Look up the hash in the identity store.

- If a matching record exists: return the existing DID and increment the usage count.

- If no record exists: generate an Ed25519 key pair, assign a new did:webvh:{SCID}:{domain}:surface:{uuid} identifier, and store the record.

## Enabling agent identity

Add an Identity element to the surface builder canvas and place it on the edge where identity evidence is available:

| Placement | Identity captured |
| Caller → access point | Calling agent (Inbound caller identity). |
| Managed agent → access point | Protected agent (Protected (Managed) Agent identity). |
| Managed agent → external target | Upstream agent called by the managed agent (External (upstream) Agent identity). |

Each Identity element is configured independently with an extraction type. No prior registration or credential exchange is required.

## Verifiable Credentials

When identity is enabled, the gateway issues a W3C Verifiable Credential for each agent. The credential’s issuer is the gateway’s own DID, and the subject is the agent’s assigned DID. Claims contain the agent’s extracted identity attributes. The credential is signed with EdDSA (Ed25519).

In a multi-gateway scenario, the issuing gateway wraps the VC in a Verifiable Presentation signed with the agent’s Ed25519 key before forwarding:

  VC issued
  →
  Wrap in VP
  →
  Sign VP (agent key)
  →
  Forward to receiving gateway

The receiving gateway verifies both signatures to determine the identity’s trust level:

  Receive VP
  →
  Verify VP signature
  →
  Verify VC signature
  →
  VP holder = VC subject ✓

## Cross-gateway trust

In a multi-gateway architecture, an identity that passes all checks at the receiving gateway is stored as verified. It appears on the Identities tab with a REMOTE badge alongside a VERIFIED badge.

## Where identity fits in the gateway

Identity resolution runs inline with every request, within the same pipeline as policy evaluation and trust-registry checks.

  Inbound request
  →
  Resolve agent DID
  →
  Issue VC
  →
  Trust-registry check
  →
  Forward to target

## Supported DID methods

| Method | Format | Usage |
| did:webvh (gateway) | did:webvh:{SCID}:{domain} | The gateway’s own primary identity, with a verifiable key-rotation log. |
| did:web (gateway) | did:web:{domain} | Parallel document served alongside the did:webvh log. Includes alsoKnownAs referencing the gateway’s did:webvh. |
| did:webvh (agent) | did:webvh:{SCID}:{domain}:surface:{uuid} | Agent identities issued by the gateway. |
| did:web (connection point) | did:web:{domain}:connection-points:{uuid} | Gateway-to-gateway connection identities. |

## Gateway DID document

The gateway serves two documents for its own identity:

- /.well-known/did.jsonl: the verifiable did:webvh log. This append-only file records every key rotation event, allowing resolvers to verify the full key history anchored to the gateway’s domain.

- /.well-known/did.json: a parallel did:web document for resolvers that use standard did:web resolution. This document includes an alsoKnownAs field referencing the gateway’s did:webvh DID.

Both endpoints share the same key material and service endpoints. Resolvers that support did:webvh use the log for auditability. Resolvers that only support did:web use the JSON document directly.

Each document includes:

- Ed25519 verification methods for message signing and authentication.

- X25519 key agreement keys for establishing encrypted DIDComm channels.

- A DIDComm service endpoint identifying where DIDComm messages should be delivered.

For the gateway’s DID document to be resolvable by remote parties, the gateway must be accessible at a public HTTPS URL. The gateway’s domain is configured in gateway.json, and the generated DID document points to that domain.

## Related

- [Surface reference](/products/affinidi-trust-fabric/agent-gateway/reference/surfaces/surface-reference.md): The AgentSurface is the top-level configuration and runtime entity in the Agent Gateway.

- [Surfaces](/products/affinidi-trust-fabric/agent-gateway/concepts/surfaces.md): How the identity extraction type is configured per surface.
