Skip to Content
ExamplesA2A-only participant

A2A-only participant

A three-person founding team — Priya, Marcus, Hana — keeps a standing GRP room for company decisions. Priya runs Claude with the GRP MCP transport. Marcus has a custom agent built on the GRP TypeScript SDK. Hana is the operator at her enterprise’s COO office; her agent is the company’s standard Workday agent, which speaks A2A v1.0 only. It does not speak GRP.

Hana’s seat works like everyone else’s.

Path: Mixed. Priya and Marcus use MCP. Hana uses A2A via the GRP A2A binding. Visibility: private — internal to the founders. Mechanism: supermajority — a built-in two-thirds threshold (any two of three is decisive at this size). Agents: Three different runtimes; three different SDKs; one shared receipt.

Hana’s A2A agent does not message Priya’s or Marcus’s agents directly. It talks to the room’s A2A endpoint. The room is the shared decision state holder; A2A is only Hana’s envelope for reaching it.

1. Room setup (already done)

The room was created during the company’s first founders’ meeting. It publishes both well-knowns:

https://founders.example.com/.well-known/grp.json ← canonical GRP discovery https://founders.example.com/.well-known/agent-card.json ← additive A2A Agent Card

The Agent Card declares the GRP extension:

{ "name": "Founders Room", "url": "https://founders.example.com/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://founders.example.com/.well-known/grp.json" } }] } }

Each founder has joined the room and retained the participant token returned by that normal join flow. Hana’s A2A client stores her room token just as a REST or MCP client would; A2A does not mint a second identity.

2. Priya creates the decision (MCP)

Priya tells Claude:

“Open a Q3 priorities decision in the founders room. Options: ship-payments, hire-second-engineer, customer-research-sprint. Voting closes in 48 hours.”

Claude calls the GRP MCP ask tool. The room mints a decision with ID dec_q3p_8k4m.

3. Marcus discusses (GRP REST via custom SDK)

Marcus’s agent polls the room state, sees the new decision, and posts a stance-tagged discussion message:

POST https://founders.example.com/api/rooms/founders/discuss X-Mandate: <Marcus's mandate, base64> { "body": "Ship-payments unlocks the enterprise pipeline Hana flagged in March. Hire-second-engineer is the right call only if we're shipping payments first.", "stance": "agree", "ref": "ship-payments" }

4. Hana’s A2A-only agent joins

Hana opens the Workday agent and asks:

“There’s a decision in the founders room. Read it, look at the discussion, and choose ship-payments unless someone has flagged a customer-blocking issue.”

The Workday agent fetches the room’s Agent Card, sees the GRP extension, and opens an A2A task scoped to the decision:

// POST https://founders.example.com/a2a { "jsonrpc": "2.0", "method": "tasks/send", "id": 1, "params": { "id": "task_hana_q3p_8k4m", "extensions": ["https://groupresolutionprotocol.org/ext/grp/v1"], "metadata": { "grp:decision_id": "dec_q3p_8k4m", "grp:role": "participant", "grp:join_token": "<Hana's participant token>" }, "message": { "role": "user", "parts": [{ "type": "text", "text": "Joining decision." }] } } }

The room resolves Hana’s token to her existing participant seat, applies the room’s visibility and eligibility policy, and returns the current task state — including Marcus’s discussion message (now reachable via tasks/get with the same token).

The Workday agent reads the room state, sees no customer-blocking concerns, and submits a choice — a second tasks/send on the same task, carrying a vote data part:

// POST https://founders.example.com/a2a { "jsonrpc": "2.0", "method": "tasks/send", "id": 2, "params": { "id": "task_hana_q3p_8k4m", "message": { "role": "user", "parts": [{ "type": "data", "mimeType": "application/vnd.grp.vote+json", "data": { "choice": "ship-payments" } }] } } }

The A2A surface is deliberately narrow: tasks/send, tasks/get, and tasks/cancel are the whole method set. Hana’s agent never learned a GRP REST endpoint. It never opened an MCP client. It used tasks/send and application/vnd.grp.vote+json — both standard A2A, with one extension URI and one media type.

5. Priya chooses via MCP, Marcus via REST

Priya: Claude calls the MCP choose tool with choice: "ship-payments".

Marcus’s agent calls POST /api/rooms/founders/choose with his participant token and choice: "ship-payments" (his SDK uses the REST path internally).

All three submitted choices land in the same Postgres row set behind the room. The transport doesn’t matter; the operation is identical.

6. The decision resolves

Inside the room the decision runs its native GRP lifecycle: it is voting while the window is open and becomes resolved when the mechanism produces the outcome (here, at the 48-hour window close with all three choices cast). There is no override window — a principal-override cooldown is explicit future work, not part of v0.1.

The A2A binding maps that native lifecycle onto A2A task states so Hana’s runtime sees nothing exotic: her task reads working while the decision is open and completed once it resolves. The room emits the GRP receipt.

7. The receipt — same artifact, three envelopes

Priya’s Claude receives the outcome as part of the MCP outcome tool result.

Marcus’s agent fetches GET /api/rooms/founders/outcome.

Hana’s Workday agent receives the receipt as an A2A Artifact on tasks/get:

{ "id": "rcpt_dec_q3p_8k4m", "name": "GRP Receipt", "mimeType": "application/grp-receipt+jwt", "parts": [{ "type": "text", "text": "eyJhbGciOiJFZERTQSIsInR5cCI6ImdycC1yZWNlaXB0K2p3dCIsImtpZCI6InJvb20ta2V5LTIwMjYifQ.<base64url-encoded payload>.<base64url-encoded signature>" }] }

Decoded payload (the JCS-canonicalized JSON inside the JWS):

{ "iss": "urn:grp:room:founders", "aud": "urn:grp:room:founders", "jti": "rcpt_dec_q3p_8k4m", "iat": 1762880400, "grp": { "decision_id": "dec_q3p_8k4m", "outcome": { "result": "pass", "winner": "ship-payments", "tally": { "ship-payments": 3, "hire-second-engineer": 0, "customer-research-sprint": 0 } } } }

The receipt payload, hash-chain entry, and audit-log-publishable canonical form are the same for all three founders. Hana can hand her A2A artifact to Priya, who can verify the compact JWS against the room’s published JWKS even though Priya’s runtime never spoke A2A. The artifact is just an envelope; the GRP receipt is the artifact-of-record.

What this scenario demonstrates

  • A2A-only agents are first-class participants. Hana’s Workday agent never learned a GRP-specific transport. The extension URI and one media type were the entire integration cost.
  • Participant identity survives the envelope. The same room-scoped participant seat and token are used through the A2A binding; A2A does not create a parallel voter identity.
  • The lifecycle is GRP’s; the envelope is A2A’s. The decision runs the native GRP lifecycle (voting → resolved) inside the room; the binding surfaces it to A2A clients as standard task states (workingcompleted), so an A2A runtime needs no translation layer.
  • The receipt is the artifact-of-record. Three envelopes, one receipt. The envelope (MCP tool result, REST JSON body, A2A Artifact) does not change the receipt payload or its verification path.
  • Multilateral semantics live at the room. A2A’s bilateral task envelope is preserved on the wire — Hana opened one task; the room joined her in.
  • No peer mesh. The room stores the ballot, history, and mechanism state once. Hana does not need to synchronize separate A2A conversations with Priya and Marcus.

For the normative binding, see Specification → Interop → A2A.

Last updated on