1 · Terms
2 · Transport
A2A 1.0 HTTP+JSON. Requests SHOULD sendA2A-Version: 1.0 and
Content-Type: application/json. A2A responses MUST use
Content-Type: application/a2a+json.
2.1 Agent Card
One card per Brand, served by the Provider:- The personal agent gets the card URL from the Brand; it never builds it from
a Brand ID. The standard place is
https://{brandDomain}/.well-known/agent-card.json, which serves the card or redirects to the Provider’s URL. Out-of-band sources, such as a link from the Brand or a public registry of Agent Cards, MAY point to the card wherever it is hosted. This spec does not define a registry. - No authentication. An unknown
brandIdgets404with no A2A body. - MUST list a
supportedInterfacesentry withprotocolBinding: "HTTP+JSON"andprotocolVersion: "1.0". Itsurlis the interface URL. Personal agents pick the interface by binding and version, not by position. - MUST declare the personal-agent JWT (§3) as an
httpAuthSecuritySchemewithscheme: "Bearer",bearerFormat: "JWT", listed alone in onesecurityRequirementsentry. - MAY declare delegated authority (§5.1).
name,description,skillsare informational.
2.2 Operations
Relative to the interface URL. Onlymessage:send is required. Other A2A
operations behave as A2A defines.
Any route that isn’t an A2A operation gets
404 or 405 with no A2A body.
Routing happens before authentication; an unknown Brand is 404 even with a
valid token.
3 · Personal agent identity
The bearer token is a JWT the personal agent signs with its own key. The Provider verifies it against the personal agent’s JWKS. No shared secrets.3.1 Registration
How these are exchanged is out of scope. Registration happens once per personal agent and
Provider, not per User or Brand.
audience is one value per Provider and
MUST NOT be derived from a card URL.
Whether a Provider accepts only personal agents it has allowlisted (a trusted-issuer
registry) or any personal agent whose iss serves a JWKS is the Provider’s policy, not
PACT’s. An open Provider still verifies §3.2 in full; jwksUri MAY then be
found through OIDC discovery at {iss}/.well-known/openid-configuration.
3.2 Personal-agent JWT
Every request except the card carriesAuthorization: Bearer <pa-jwt>.
Providers MUST verify the signature via
jwksUri, allow at most 30 s clock
skew, and reject unknown or disabled personal agents. The User is the pair (personal agent, sub);
the personal agent MUST reuse the same sub for the same User.
3.3 What the personal-agent JWT proves
That a known personal agent is calling for someone it callssub. Not that sub owns a
Brand account. Without §5, the agent verifies the User the way it does in a
chat widget (it asks for an order number, email, etc.) and the personal agent relays the
User’s answers. Account credentials never pass through the personal agent.
3.4 Failure
4 · Messages
4.1 Request
- An A2A
SendMessageRequest.configurationandmetadataMAY be ignored. roleMUST beROLE_USER.partsMUST have at least one non-blanktextpart. Other part kinds getCONTENT_TYPE_NOT_SUPPORTED.taskIdMUST be absent; otherwiseTASK_NOT_FOUND.messageIdMUST be unique within the context.
4.2 Context
- The reply is synchronous:
{ "message": Message }withrole: ROLE_AGENTandcontextIdset (or a task, §5.5). - Without
contextId, the message starts a new conversation and the Provider mints an opaquecontextId. - With
contextId, the message continues that conversation. The context MUST belong to this Brand and this(personal agent, sub); otherwiseINVALID_PARAMS, without saying whether it exists for someone else. contextIdis state, not a credential. Ordinary turns create no A2A Task.- A Provider MAY close a conversation (the Brand’s agent ended it, or it
expired). A message to a closed
contextIdgetsUNSUPPORTED_OPERATION; the personal agent starts a new conversation by omittingcontextId.
4.3 Retries
A repeatedmessageId in the same contextId returns the stored reply
without re-running the agent. If there is no stored reply yet, return
INVALID_PARAMS.
5 · Delegated authority
Optional. This is the PACT Delegated profile (§7). Identity (§2–4) works without it; Providers that don’t offer it omit §5.1 from their cards.Lets the Brand’s agent act on the User’s Brand account, using standard OAuth 2.0 device code (RFC 8628). Each Brand defines its own scopes. The User logs in with the Brand, never with the personal agent, and approves some of them. The personal agent needs only a generic device-code client. In OAuth 2.0 terms:
- Request scopes. The personal agent asks the Provider for the scopes it needs, sending its §3 JWT as the client credential (§5.3).
- Login link. The Provider returns a link to the Brand’s own login. The personal agent shows it to the User and never handles the login itself.
- Sign in and approve. The User logs in with the Brand and approves scopes on the Provider’s consent page. The personal agent never sees the login.
- Delegation token. The Provider signs a delegation token listing the approved scopes (§5.4). The personal agent carries it but cannot change it.
- Send and receipt. The personal agent sends the token with each message. The Provider checks it, and the Brand’s agent acts as the User only within those scopes (§5.5). Every reply carries a signed receipt (§5.6).
5.1 Card
A Brand that supports delegation adds anoauth2SecurityScheme with a
deviceCode flow and a second securityRequirements entry naming both
schemes:
- The entry that needs only the personal-agent JWT MUST stay. A personal agent MAY always talk with §3 alone.
oauth2MetadataUrlMUST serve RFC 8414 metadata; itsjwks_uripublishes the keys that sign delegation tokens and receipts.
5.2 Scopes
A scope is{ id, description }. Each Brand defines its own (orders:read,
booking:change, whatever its agent does) and PACT reserves no ids. The
Brand maps its agent’s capabilities to scopes; unmapped capabilities stay
available under §3. Personal agents pick scopes by reading the descriptions and MUST
request only ids on the card. Providers show descriptions to the User
verbatim on consent.
5.3 Getting a token
RFC 8628 with two rules: the OAuth client is the personal agent, authenticated with its §3 JWT (client_id = its issuer URL); the login step is the Brand’s own login.
- An unknown scope id gets OAuth
invalid_scope. A bad personal-agent JWT gets401(§3.4). - The personal agent shows the User
verification_uri_complete. It MUST NOT proxy, frame, or observe the login. - The link opens the Brand’s login. The Brand authenticates the User and
returns the User to the Provider with a single-use assertion bound to the
user_code, sent byPOST, not a credential from another channel. The Provider then shows consent as the logged-in User: the personal agent’s issuer origin, the Brand, and each scope as a checkbox the User MAY uncheck. Login comes first so the grant is bound to a verified account. - Consent MAY be skipped when an unexpired grant for
(User, personal agent)already covers the request.
authorization_pending, slow_down, access_denied, or
expired_token per RFC 8628. Then:
scope is what the User approved, which may be less than requested. The personal agent
MUST read it.
5.4 Delegation token
access_token is a JWT signed by the Provider (ES256/RS256; keys at the
jwks_uri from §5.1).
5.5 Sending with it
Both tokens go on the request. The personal-agent JWT is checked first, unchanged.aud, exp, that client_id equals the personal agent’s iss, and
that the grant is not revoked; (3) run the agent as Brand user sub, limited
to scope. A bad delegation token gets 401 with
WWW-Authenticate: Bearer realm="a2a", error="invalid_token", no A2A body.
contextId rules (§4.2) are unchanged. A context started under §3 MAY
continue under delegation. Once a context has run as one sub, a token for a
different sub gets INVALID_PARAMS.
Step-up. If a turn needs a scope the token lacks, the Provider MUST NOT
fail it. It returns a task in TASK_STATE_AUTH_REQUIRED with the missing ids
and a new link; the conversation stays open:
contextId. The step-up task MAY be ephemeral; tasks/{id} MAY
return TASK_NOT_FOUND for it.
5.6 Receipts
Everymessage:send served under a delegation token MUST include in the
reply’s metadata a receipt signed with the same keys as the token:
jws is the compact JWS of claims. Personal agents SHOULD verify and keep receipts.
6 · Errors
A2A errors use the A2A / AIP-193 envelope.code repeats the HTTP status; the
reason is error.details[0].reason. Clients MUST NOT infer the reason from
the status alone.
INVALID_PARAMS covers: bad JSON or schema, wrong role, blank text, bad
pageSize, an unknown or foreign contextId, a repeated messageId with no
stored reply, and a sub mismatch (§5.5).
Not A2A errors: 401 (§3.4, §5.5); 404/405 for unmatched routes or
unknown Brands (§2.2); 429 with Retry-After when a Provider rate-limits a
personal agent or a (personal agent, sub); and OAuth endpoint errors
(RFC 6749 §5.2, RFC 8628).
On 429, personal agents SHOULD wait Retry-After before retrying.
7 · Conformance
This is PACT 1.0. Breaking changes to either profile bump that number.
7.1 Implementing
Step-by-step guides with a check per step: Build a Provider (ends with runninge2e/ against yourself with E2E_PROVIDER=any) and
Build a personal agent integration.