@openpactprotocol/client does steps 3–5. It is not on
npm yet; copy packages/client/src/ from this repository.
Covers the PACT Identity profile only. Delegated authority is in spec §5.
Values you need
1 · Publish a signing key
Generate an ES256 key with akid. Serve the public JWK as a JWKS at
{PA_ISSUER}/.well-known/jwks.json. PA_ISSUER is your platform’s URL and
becomes the iss claim. In this repository, pnpm gen-keys generates a key
pair in this format.
An example JWKS with one public key:
d field; keep it
secret and use it to sign tokens (step 3).
Done when curl $PA_ISSUER/.well-known/jwks.json returns { "keys": [ … ] }.
2 · Get the Provider’s audience and register if required
Get the Provider’s audience from its documentation or onboarding process and copy it intoaud (step 3). Do not derive it from the Agent Card URL.
Registration depends on the Provider’s policy. If required, send your issuer
and JWKS URL once per Provider, not per User or Brand. Open Providers may accept
agents without prior registration and discover their keys instead. Both verify
personal-agent JWTs in full (spec §3.1).
The reference Provider requires registration and offers a
self-service endpoint.
Done when you have the Provider’s audience and have completed any required
registration.
3 · Sign a personal-agent JWT
One per request, valid ≤ 300 s (spec §3.2): headerkid; iss = PA_ISSUER; sub = your stable, opaque id for the User;
aud = the Provider’s audience; iat, exp.
jwtVerify(token, yourJwks, { issuer: PA_ISSUER, audience }) succeeds.
4 · Fetch the Brand’s Agent Card
No token. The interface URL is theurl of the supportedInterfaces
entry with protocolBinding: "HTTP+JSON" and protocolVersion: "1.0". A
trimmed card (full example in spec §2.1):
interfaceUrl returns https://provider.example.com/a2a/01J… here. Step 5
sends to {interfaceUrl}/message:send.
404 means the Brand is unknown
to that Provider.
5 · Send messages
POST {interfaceUrl}/message:send with Authorization: Bearer <token> and
A2A-Version: 1.0 (spec §4). The reply carries a
contextId; send it with every later message for the same User and Brand.
Use a fresh messageId per message; resending one is a safe retry.
role: "ROLE_AGENT" and a contextId, and a
second message with that contextId continues the conversation.
6 · Handle errors
The reason is
error.details[0].reason (spec §6).
A2AClient throws A2AError for envelopes and A2AHttpError for the rest.
Test locally
Start the reference stack; it already trusts the demo key frompnpm gen-keys.
contextId.
Delegated authority is optional: the User logs in with the Brand and approves
scopes, so the Brand’s agent can act on their account. Brands advertise it on
their card; spec §5 defines it. Nothing above
changes.