microsoft / microsoft/agent-host-protocol

Verified client identities (self-sovereign clientId via did:key)

Open
#259 0 comments 0 reactions 1 assignee View on GitHub

@connor4312 is already working on this.

Since Jun 23, 2026.

enhancement under-discussion
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:key used as its clientId (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:key is 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.
  • Proof is a server-issued challenge carried in a new error, symmetric for initialize and reconnect:
    1. Client sends initialize / reconnect with a did:key clientId.
    2. If the host enforces identity and no valid proof is attached, it replies with ClientIdentityChallengeRequired (-32012) and data: { nonce } (opaque, base64url).
    3. Client signs "AHP-client-identity-v1" ‖ nonce and retries the same command with an added identityProof.
    4. Host verifies the signature against the key in the clientId, then proceeds.
  • 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-formatted clientId presented 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 clientId strings.
  • 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: add ClientIdentityChallengeRequired: -32012 to AhpErrorCodes and a ClientIdentityChallengeData { nonce: string } detail type.
  • types/common/commands.ts: add optional identityProof to InitializeParams and ReconnectParams.
  • Docs: new proposal under docs/proposals/, plus a Lifecycle handshake update once accepted.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.