microsoft / microsoft/agent-host-protocol
Verified client identities (self-sovereign clientId via did:key)
@connor4312 is already working on this.
Since Jun 23, 2026.
- Dominant language
- TypeScript
- Stars
- 344
- Forks
- 122
- Avg merge
- 14h 12m
- Merged PRs (30d)
- 22
Description
Summary
Add an opt-in, transport-agnostic mechanism for clients to prove a stable, self-sovereign identity to an agent host. Today clientId is an unauthenticated string, so any peer that learns another client's clientId can impersonate it — most notably to hijack reconnect and replay another client's session deltas.
This proposal gives clients a cryptographic identity that proves continuity ("the same client is connecting again"). Authorization is out of scope — a host (or a proxy in front of it) decides whether a given identity is allowed by its own means.
Mechanism
- A client's identity is a
did:keyused as itsclientId(e.g.did:key:z6Mk...). The public key is embedded in the identifier, so no separate key field is needed.- Baseline: Ed25519 (MUST). P-256 allowed (Secure Enclave / TPM / WebAuthn hardware keys).
did:keyis self-describing, leaving room for post-quantum schemes later. - The
did:key:prefix is the unambiguous marker for "identity-bearing clientId." - The resulting client ID's are 56 characters or 57 characters for Ed25519 and P-256 respectively.
- Baseline: Ed25519 (MUST). P-256 allowed (Secure Enclave / TPM / WebAuthn hardware keys).
- Proof is a server-issued challenge carried in a new error, symmetric for
initializeandreconnect:- Client sends
initialize/reconnectwith adid:keyclientId. - If the host enforces identity and no valid proof is attached, it replies with
ClientIdentityChallengeRequired(-32012) anddata: { nonce }(opaque, base64url). - Client signs
"AHP-client-identity-v1" ‖ nonceand retries the same command with an addedidentityProof. - Host verifies the signature against the key in the
clientId, then proceeds.
- Client sends
- The signed payload is always wrapped by the fixed spec prefix
"AHP-client-identity-v1". The host controls the nonce body; the prefix guarantees the signature can only ever be an AHP identity proof (no blind-signing oracle).
Host requirements
- The nonce MUST be single-use and bound to the connection (e.g. by embedding a connection id), so a captured
(nonce, signature)pair can't be replayed on another connection. - The nonce MAY be a stateless authenticated token (
random ‖ HMAC_serverKey(random ‖ clientId ‖ connId ‖ expiry)), avoiding server-side challenge storage. - A host that enforces identity MUST reject a
did:key-formattedclientIdpresented without a valid proof.
Compatibility
Non-breaking and opt-in:
- Hosts unaware of the scheme ignore the extra field and accept the connection.
- Clients not adopting identities keep using plain
clientIdstrings. - The security guarantee holds only where the host enforces it.
Transport security (non-normative)
AHP does not specify a transport. Where the transport already authenticates the client (mutual TLS, OS peer credentials on a local socket), a host MAY treat that as satisfying identity and skip the challenge. A TLS-terminating host MAY also channel-bind by folding a TLS exporter value into the opaque nonce — mTLS-grade binding with no transport language in the spec.
Proposed surface
types/common/errors.ts: addClientIdentityChallengeRequired: -32012toAhpErrorCodesand aClientIdentityChallengeData { nonce: string }detail type.types/common/commands.ts: add optionalidentityProoftoInitializeParamsandReconnectParams.- Docs: new proposal under
docs/proposals/, plus a Lifecycle handshake update once accepted.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.