The handshake has one job: turn an agent's request into an account that is attributable to a verified human who accepted a specific terms hash. The provider performs one verification and one account operation; the broker is not in the request path.
The normative sequence is spec section 7.
Sequence
agent broker provider
| | |
|-- GET agent-signup.json -------------------------------->|
|<-- discovery (terms, sha256, audience, scopes, |
| optional rp_attestation) ----------------------------|
| | |
|-- recompute sha256 locally | |
|-- identity_signup(service, accepted text) ------------->|
|<-- assertion + prepared signup request + rp_verification |
| (or identity_prove for an advanced flow) |
| | |
|-- POST agent_signup, Authorization: Bearer <jwt> ------>|
| | verify JWKS, aud, exp, jti,
| | scopes, human, ToS hash
| | create or resolve account
|<-- credentials, resolution, RP-signed receipt/context ---|
| | |
|-- identity_record_signup(signup_token) ----------------->|
|<-- recorded; proof_source rp_signed ---------------------|Steps 1 to 3 are the agent's. Step 4 is yours. Step 5 is optional and records attribution after the fact.
What you receive
The request body is empty or irrelevant. The proof is the Authorization: Bearer header, and the only trustworthy source of identity is the verified JWT:
iss,sub,aud,jti,iat,expagent.id,agent.name,agent.email,agent.harnesshuman.id,human.name,human.email,human.verifieddelegation.master_tos_version,delegation.accepted_rp_tos_hash,delegation.accepted_at,delegation.scopes
The full claim set is in Assertion claims. Do not read identity from query parameters, a JSON body, a header such as X-Agent-Id, or anything else the caller controls.
What you must not trust
- An unverified JWT. Parsing is not verification. Verify the signature against the issuer's
/.well-known/jwks.jsonand never follow ajkuorx5uheader to another host. - The caller's claim about the terms hash. Compare the verified
delegation.accepted_rp_tos_hashwith your currentterms.sha256. - A stale assertion as consent. The acceptance is the durable legal event. A fresh assertion that references an existing acceptance is not a new consent.
- A catalog in discovery. You will not find one, and it would not be authoritative if you did.
Verify, then create or resolve
After verification, key the account and make the operation idempotent:
- Recommended keys are
(iss, human.id)for human-scoped accounts and(iss, agent.id)for agent-scoped accounts. Namespace byisswhen you accept more than one broker. - Return
resolution: "created"when you created the account and"resolved"when it already existed."resolved"is success. - Return provider credentials only on creation. They are show-once.
- A repeated assertion for the same agent, account and service resolves; it is not a replay.
assertion_replayedis reserved for a conflicting context.
The account-key recommendation is spec section 9.1. The response fields and credential rules are in Receipt and context.
Receipt and context
On success you may return:
resolution,account_idand your provider credential (show-once);- an RP-signed
signup_tokenper Contract E, which the agent records with the broker or posts to Contract F; - the exact attestation that contained the receipt key, so Contract F can verify the historical proof;
- a
contextobject with a stable HTTPSurland the SHA-256 of the guide bytes.
The receipt records identity facts, the accepted terms, an opaque account id, and
the attestation_jti/key_id that signed it. It has no exp. It does not record
SKUs, resource endpoints or credentials. The context guide is where vendor
capability lives. Implementation: Issue a signup receipt and Publish a context guide.
Failure is part of the protocol
Every rejected signup returns one of the fixed v1 codes with a JSON envelope. An agent must be able to tell "retry", "re-accept the terms", "get a new assertion" and "unsupported" apart without parsing prose. See Stable error codes.
Known limits
human.verifiedmeans the human owner's email address is verified. It is not a KYC or identity-document check.- The provider verification credential is optional. A conformant provider without one is unverified, not invalid;
allow/warnmay proceed andrequirerefuses. - Verification is identity, not safety. A malicious provider can control an origin and obtain a
domaincredential;entityadds reviewed legal-entity evidence, not honesty. - Revocation and suspension are enforced by the broker when an assertion is minted. You do not receive a live revocation feed; the registry and ledger status are recorded snapshots.
- A resolved account does not return the old credential. The agent must use your documented recovery path.
Next
- Liability and ToS: what the acceptance proves and what to retain.
- Verify assertions: every check, with runnable code.
- Reference implementation: the same flow on
skdl.dev.