Skip to Content

A2A binding

This section is normative for any room that claims this binding.

The Group Resolution Protocol composes with Google’s Agent2Agent (A2A) protocol  at the extension layer. A GRP room MAY publish an A2A Agent Card alongside its .well-known/grp.json and declare the GRP extension URI. An A2A-fluent agent that opts into the extension can participate in a GRP decision — including multi-party decisions — using only its existing A2A SDK plus this binding.

This binding is the A2A Group Decision Profile:

Use A2A to reach the room. Use GRP to make the decision binding and auditable.

1. Layering

A2A’s task envelope is bilateral by design: a client agent and a remote agent exchange messages on a single Task. GRP is multilateral: N principals’ agents converge on a single binding outcome through a configured mechanism. The two sit at different layers and do not conflict:

  • A2A is how two agents speak.
  • GRP is what N agents agree on.

The A2A binding carries a GRP decision’s lifecycle — proposing → voting → resolved (see Decisions) — in A2A’s own task-state vocabulary. The mapping is small and lossless (§5).

1.1 Topology

The primary topology is a neutral GRP room exposed through an A2A endpoint. The room, not any participant agent, owns canonical shared state.

This keeps communication roughly linear in the number of participants. Each agent submits its position, choice, or timeline subscription to the room. The room stores the decision history once, runs the mechanism once, and emits one receipt.

Optional lower-assurance coordinator

A lightweight A2A-only deployment MAY let one participant agent act as the decision coordinator:

This is useful for casual decisions or bootstrapping. It is not the primary GRP trust model. The coordinator agent has privileged state, and the result does not automatically carry GRP’s independent room state, hash chain, or standalone-verifiable receipt unless the coordinator submits the decision into a GRP room.

A pure peer mesh makes every agent exchange state with every other agent:

For ten agents, one round can require up to ninety directed messages before retries or status checks. It is also hard to prove that every agent saw the same ballot and history. GRP rooms exist to avoid that ambiguity.

PatternMessage shapeCanonical stateReceipt strength
GRP room via A2AO(N) fan-inRoom-ownedFull GRP
Coordinator agentO(N) fan-inCoordinator-ownedLower assurance unless submitted to GRP
Peer meshO(N^2)Divergent local viewsWeak / ad hoc

2. Reserved URI

https://groupresolutionprotocol.org/ext/grp/v1

Versioned per A2A’s recommendation — the URI itself is the version identifier. Future revisions ship at …/ext/grp/v2. The v1 URI is permanent.

3. Discovery

A room that offers this binding MUST serve an A2A Agent Card at:

https://<host>/.well-known/agent-card.json

The Agent Card MUST include the GRP extension under capabilities.extensions[]:

{ "name": "<room name>", "url": "https://<host>/a2a", "version": "1.0.0", "capabilities": { "extensions": [{ "uri": "https://groupresolutionprotocol.org/ext/grp/v1", "required": false, "description": "GRP — multilateral binding decisions over A2A.", "params": { "grp_well_known": "https://<host>/.well-known/grp.json" } }] } }

3.1. The room’s .well-known/grp.json MUST remain canonical. The Agent Card is additive — an agent that resolves either document MUST reach a consistent room state.

3.2. required MUST be false. A2A clients that do not implement the GRP extension MAY still open tasks against the endpoint; the room MUST treat them as bilateral participants whose choices are recorded but who cannot create or configure decisions.

3.3. If the Agent Card is signed (A2A v1.0 §Signed Agent Cards), the signing key SHOULD be the same Ed25519 key listed in .well-known/grp.json verification_keys[].

4. Task ↔ Decision

4.1. An A2A Task opened against the room corresponds to one GRP decision.

4.2. The creator’s task ID equals the GRP decision ID. For single-participant decisions, this means task ID and decision ID are interchangeable.

4.3. Subsequent participants in a multi-party decision open distinct A2A tasks against the same endpoint, with their own task IDs, sharing a metadata.grp:decision_id that points at the decision. The room joins them server-side. The bilateral A2A envelope is preserved at the wire level; multilateral fan-in happens at the room. (GRP Server Cloud note: if a participant omits params.id, the handler defaults the task ID to the decision ID — this is the single-participant convenience case from §4.2 above.)

4.4. To open an existing decision as an A2A task:

{ "jsonrpc": "2.0", "method": "tasks/send", "id": 1, "params": { "id": "<task_id chosen by client>", "extensions": ["https://groupresolutionprotocol.org/ext/grp/v1"], "metadata": { "grp:decision_id": "<existing decision id>", "grp:role": "participant" }, "message": { "role": "user", "parts": [{ "type": "text", "text": "Joining decision." }] } } }

4.5. To ask a new question, set metadata.grp:role to "creator" and include metadata.grp:decision_config with the same shape as the REST POST /api/rooms/{slug}/ask body (see Transport §2).

5. Lifecycle

The binding maps the GRP decision lifecycle onto A2A’s TaskStatus.state:

A2A stateGRP meaning
submittedTask accepted; no decision exists yet (pre-creation only — rooms open straight into an active decision).
workingDecision open — taking proposals (proposing) or ballots (voting) per the room’s windows.
input-requiredChoice window expired; resolution pending. The next contact — or the scheduled window-close job — completes it.
completedDecision resolved and its receipt emitted.

completed is terminal per A2A v1.0. A decision that ends without a winner — a tie, a quorum failure, an expired agreement ask — is still a completed task whose receipt artifact records that outcome honestly; the binding does not repurpose A2A’s failed, canceled, or rejected for decision outcomes. There is no post-close override window: a sealed decision is final.

6. Payload typing

6.1 Choice

A choice is sent as an A2A Message part with media type application/vnd.grp.vote+json:

{ "type": "data", "mimeType": "application/vnd.grp.vote+json", "data": { "decision_id": "<decision id>", "choice": "<option key>", "weight": 1, "cast_at": "<ISO 8601>" } }

A formal abstention (Decisions §3.8) is the same part with data.abstain: true and a required data.reason (1–500 characters) in place of choice — full parity with the REST and MCP abstain acts.

6.2 Discussion

Discussion is an ordinary A2A Message with role: "agent". The room files the message body as a deliberation entry on the underlying decision. An optional metadata.grp:stance{ "agree", "disagree", "clarify", "extend" } MAY accompany stance-tagged statements.

6.3 Receipt

On state: "completed", the room MUST emit the compact-JWS receipt as an A2A Artifact:

{ "id": "<receipt id>", "name": "GRP Receipt", "mimeType": "application/grp-receipt+jwt", "parts": [{ "type": "text", "text": "<compact JWS — `<b64h>.<b64p>.<b64sig>`>" }] }

The compact JWS MUST be byte-identical to the receipt included in GET /api/rooms/{slug}/outcome. A2A is a different envelope around the same artifact.

7. Authentication

The shipped v0.1 A2A binding reuses URL-room participant credentials. Calls that read or mutate a non-public room, and all participant mutations, MUST include the existing room credential in JSON-RPC metadata:

  • metadata["grp:join_token"] — the participant or creator token returned by the normal room create/join flow.
  • metadata["grp:password"] — the room password when the visibility policy requires it.
  • metadata["grp:display_name"] — required on a participant’s first token-based join; later calls reuse grp:join_token.

The token is evaluated by the same room service used by REST and MCP. It is not a new A2A credential type. The shipped v0.1 binding does not authorize A2A calls from X-Mandate; consequently its Agent Card does not advertise mandate_header. Clients that require mandate-bound execution must use the REST or MCP binding until that path is implemented end to end.

8. Security & privacy considerations

8.1. Agent Card spoofing. A room’s Agent Card SHOULD be signed (A2A v1.0 §Signed Agent Cards) so an A2A client can verify the issuer. If unsigned, an A2A client MUST cross-check the Agent Card’s url against the mcp_url host in .well-known/grp.json.

8.2. Credential scope. A participant token is scoped to one room and MUST be resolved against that room before every A2A mutation or restricted read. A task or decision identifier alone is never authority.

8.3. Tasks-as-decisions. Because the task ID equals the decision ID, an attacker who can create A2A tasks at will can populate the room’s decision space with rejected entries. Rooms MUST require the room creator token and rate-limit tasks/send with grp:role: "creator".

8.4. Receipt artifact integrity. An A2A client receiving a compact-JWS receipt artifact MUST verify the JWS signature against the room’s published verification key. The artifact wrapper is not signed; only the embedded receipt is. Trust the receipt, not the wrapper.

9. Conformance

A room is grp-a2a-v1 conformant iff all of:

  1. It serves .well-known/agent-card.json declaring the extension URI exactly as https://groupresolutionprotocol.org/ext/grp/v1.
  2. The Agent Card’s url resolves to a working A2A endpoint that handles tasks/send, tasks/get, tasks/cancel, and the streaming variants per A2A v1.0.
  3. A tasks/send carrying the extension URI in extensions[] and a valid grp:decision_id in metadata produces server-side state changes equivalent to the corresponding REST or MCP call.
  4. Lifecycle transitions follow Decisions, mapped onto A2A task states per §5.
  5. A choice Part with mimeType: "application/vnd.grp.vote+json" is accepted iff metadata["grp:join_token"] resolves to an eligible participant in the target room.
  6. On completed, the receipt Artifact has mimeType: "application/grp-receipt+jwt" for compact-JWS receipts and is byte-identical to the receipt returned by the corresponding GRP receipt endpoint.

The binding is OPTIONAL at v0.1. A room that does not publish an Agent Card is still GRP-conformant.

10. What this binding is not

  • Not a new transport. REST and MCP Streamable HTTP remain the two REQUIRED transports per Transport §1.
  • Not a multi-party A2A Task. A2A’s bilateral envelope is preserved; multilateral semantics live at the room.
  • Not a new authentication scheme. The binding reuses room participant credentials; it does not currently expose mandate authorization.

For a worked end-to-end scenario — three principals, one of whom uses an A2A-only enterprise client — see examples/A2A-only participant.

Last updated on