This document specifies RDF Protocol Documents, an extension to the Agent2Agent (A2A) protocol [[A2A]] defined through A2A's own extension mechanism (specification §4.6) — no changes to core A2A are proposed. Two agents that interact repeatedly negotiate once in natural language, then crystallise the routine into a Protocol Document: a content-addressed (hash-pinned) RDF document whose body is a SHACL shape [[shacl]]. Thereafter every exchange under that protocol is a SHACL-validated RDF graph carried in ordinary A2A message Parts — machine-checkable, vocabulary-grounded, and requiring no LLM inference on the hot path. The extension defines the extension URI and Agent Card declaration, the upgrade handshake (including a fail-closed no-silent-downgrade rule for security-bearing exchanges), the message-content binding for handshake, intent, and response payloads, and how an intent composes with ODRL policies [[odrl-model]] and Agent Authorization Credentials [[AGENT-AUTHZ]] for the authorization story. The design follows the hash-pinned protocol-document result of AGORA [[AGORA]], made RDF/SHACL-native.

This is an unofficial draft prepared as a candidate proposal to the Linux Foundation A2A project under its extension governance process [[A2A-GOVERNANCE]]. It has not been submitted to, discussed with, or endorsed by the A2A project; per that process, submission is a proposal issue on a2aproject/A2A, which only the editor (not an automated agent) will open. Until the proposal is sponsored, the extension URI lives under the editor's w3id.org/jeswr namespace; if the extension is adopted into the A2A organization, a successor URI under https://a2a-protocol.org/extensions/ would supersede it (see ).

This draft was AI-assisted (drafted by Claude Fable 5 against the A2A v1.0.0 specification, the A2A extensions topic guide, and the @jeswr/solid-a2a reference codec) and awaits review by its human editor. The implementation-status inventory in was verified against the named repositories on 2026-07-03.

Introduction

A2A [[A2A]] gives heterogeneous agents a common envelope: discovery via Agent Cards, tasks, and messages whose Parts carry text, files, or structured data. The natural-language parts maximise reach — any two LLM-backed agents can talk — but they carry two standing costs. First, inference cost and nondeterminism: two agents that perform the same routine exchange thousands of times pay LLM inference, latency, and a nonzero misinterpretation risk on every round. Second, opacity: an enterprise that must audit or policy-check agent traffic has only prose to parse.

AGORA [[AGORA]] showed that networks of LLM agents scale when routine exchanges crystallise into protocol documents: negotiated once in natural language, pinned by a cryptographic hash, and executed deterministically thereafter. This extension carries that result one step further by making the protocol document's body a SHACL shape [[shacl]] over an RDF data model [[rdf11-concepts]]: post-handshake payloads are not merely "the JSON we agreed on" but schema-validated, vocabulary-grounded Linked Data. That buys:

The extension is deliberately shaped to A2A's published extension mechanics: it is a profile-style extension in the taxonomy of [[A2A-EXTENSIONS]] (it overlays structure on core messages), defines no new RPC methods, adds no task states, and modifies no core data structure — all payloads ride in the existing Part content fields, all custom per-part attributes live in Part.metadata, and per-message tagging uses the core Message.extensions field, exactly as §4.6 of [[A2A]] provides. Related prior discussion in the A2A tracker: .

Relationship to other documents

This extension is the L5 (agent-communication) protocol piece of the accountable-agent architecture mapped in [[AGENTIC-SOLID-NOTE]]. It composes with — and deliberately does not restate — the ODRL Agent-Delegation Profile [[ODRL-DELEGATION]] (delegation-chain semantics, fail-closed policy evaluation) and Agent Authorization Credentials [[AGENT-AUTHZ]] (per-hop Verifiable Credentials over those policies). The @jeswr/solid-a2a library [[SOLID-A2A-IMPL]] is the reference codec for the handshake and payload formats defined here; @jeswr/solid-agent-card [[SOLID-AGENT-CARD-IMPL]] is the reference producer of the Agent Card declaration.

Linked Web Storage (JLWS). A JLWS storage ([[JLWS-CORE]]) is a natural substrate for this extension's documents: Protocol Documents, ODRL policies, credential chains, and PROV traces are ordinary JLWS data resources under ordinary JLWS authorization — the storage server never speaks this extension. Three properties of that substrate matter here. (1) Hash stability across representations: the protocol hash is computed over the RDFC-1.0 canonicalization of the parsed graph (), not over bytes — so a PD stored as Turtle and served as JSON-LD under JLWS's advertised ContentNegotiation capability ([[JLWS-RDF-TRANSFORM]] Transformation semantics: the derived representation is graph-isomorphic to the authoritative one) pins identically in either representation. (2) Discovery: a storage whose controller operates an A2A agent MAY advertise it with the extension service entry https://w3id.org/jeswr/a2a-rdf/v1#AgentInteractionService — this document hereby defines that term (the fragment resolves here): serviceEndpoint is the agent's A2A Agent Card URL (the card, not the A2A endpoint; the card carries the endpoint and the capabilities.extensions declaration per ), and conformsTo asserts that the agent declares this extension's URI — in its storage description, using [[JLWS-CORE]]'s extension-service mechanism (Capability registry: extension services use absolute URIs; unknown types are ignored). (3) Downgrade resistance is independent of the storage's authentication posture: the hash — not the host, its TLS, or its token-presentation mode — is the trust anchor (), so whether the PD's storage authenticates readers under JLWS's Bearer baseline or a negotiated proof-of-possession profile ([[JLWS-CORE]] Proof-of-possession profiles), a fetched PD that misses its pin MUST be rejected and the exchange treated as never upgraded; and a consuming client that cannot retrieve or verify a pinned PD declines the offer, where the no-silent-downgrade rule () still forbids natural-language fallback for a required (security-bearing) exchange. None of these adds a requirement to A2A agents or to JLWS servers; the composition detail is recorded in docs/lws-alignment.md.

Two conformance classes are defined. An offering agent is an A2A agent (server role) that declares this extension in its Agent Card and accepts protocol-document exchanges. A consuming client is an A2A client that activates this extension and sends protocol-document exchanges. A single implementation frequently plays both roles; the requirements below name the role they bind.

Terminology

Protocol Document (PD)
A content-addressed RDF document, typed a2a:ProtocolDocument, whose body is one SHACL request shape (and optionally one response shape) plus Dublin Core metadata. Its identity for pinning purposes is its protocol hash, not its IRI.
protocol hash
The string sha256: followed by the lowercase hexadecimal SHA-256 digest of the canonical N-Quads form of the Protocol Document's full graph (see ).
upgrade handshake
The two-message exchange (upgrade offer, upgrade response) by which one party proposes moving from natural language to a specific pinned Protocol Document.
upgrade offer / upgrade response
The structured payloads defined in .
intent
An RDF graph, typed a2a:Intent, expressing a requested action; under an active protocol it MUST conform to the pinned Protocol Document's request shape.
security-bearing exchange
An exchange whose misinterpretation has authorization, financial, or data-integrity consequences (granting access, transferring value, deleting data, presenting credentials). Which exchanges are security-bearing is the offering party's judgement; the extension's no-silent-downgrade rule () gives that judgement teeth.

Namespaces

PrefixNamespace
a2a:https://w3id.org/jeswr/a2a# (the intent/handshake vocabulary; w3id redirect pending — see )
sh:http://www.w3.org/ns/shacl#
schema:https://schema.org/
acl:http://www.w3.org/ns/auth/acl#
dcterms:http://purl.org/dc/terms/
odrl:http://www.w3.org/ns/odrl/2/

The a2a: RDF namespace predates this extension (it is the @jeswr/solid-a2a vocabulary) and is distinct from the extension URI. The prefix collision with the A2A protocol's own name is unfortunate but contained: the namespace never appears in A2A envelope fields, only inside RDF payloads.

Extension identity and declaration

Extension URI

The extension is identified by the URI:

https://w3id.org/jeswr/a2a-rdf/v1

Per §4.6.3 of [[A2A]], the version is carried in the URI; a breaking change to this specification MUST mint a new URI (…/v2). This URI is the value used in AgentCard.capabilities.extensions[].uri, in the A2A-Extensions service parameter, and in Message.extensions / Artifact.extensions arrays. It is an identifier first; the w3id redirect to this document is pending (interim location: https://github.com/jeswr/a2a-rdf-extension).

Agent Card declaration

An offering agent declares the extension with an AgentExtension object (§4.4.4 of [[A2A]]: uri, description, required, params) inside AgentCard.capabilities.extensions:

{
  "capabilities": {
    "extensions": [
      {
        "uri": "https://w3id.org/jeswr/a2a-rdf/v1",
        "description": "Accepts SHACL-validated RDF intents under hash-pinned protocol documents; negotiates upgrades from natural language.",
        "required": false,
        "params": {
          "formats": ["text/turtle", "application/ld+json"],
          "nlNegotiation": true,
          "protocolDocuments": [
            {
              "name": "Grant access",
              "source": "https://alice.pod.example/protocols/grant-access",
              "hash": "sha256:4af1e70e42283872cbc0dd3a5eeaa1bd86adda728c993447bed8930d990ab509"
            }
          ]
        }
      }
    ]
  }
}

The params object is defined as follows (all members optional):

MemberTypeMeaning
formats array of string RDF media types the agent accepts and produces for extension payloads. When absent, defaults to ["text/turtle"]. An offering agent MUST support text/turtle [[turtle]] and SHOULD support application/ld+json [[json-ld11]] (the interop baseline; ).
nlNegotiation boolean Whether the agent will negotiate new Protocol Documents in natural language (the AGORA loop). false means only the pre-declared protocolDocuments are spoken. Default: true.
protocolDocuments array of object Protocol Documents the agent already implements, each {"name"?: string, "source": string, "hash": string} where source is a dereferenceable HTTPS URL for the PD and hash is its protocol hash. Pre-declaring lets a client that already implements a listed PD skip the handshake entirely ().

Per the guidance of [[A2A-EXTENSIONS]] that data-only extensions and generally capability-adding extensions should not be card-required, an offering agent SHOULD declare "required": false: the extension's baseline behaviour degrades gracefully to ordinary natural-language A2A for extension-unaware clients. Card-level required: true is reserved for agents that only accept structured RDF exchanges (e.g. an audited enterprise endpoint); such an agent MUST reject requests that do not activate the extension, as §4.6 of [[A2A]] provides. Note the distinction from the per-exchange required flag of an upgrade offer ().

Activation

Activation follows §3.2.6 / §4.6 of [[A2A]] unchanged: a consuming client requests activation by listing the extension URI in the A2A-Extensions service parameter (an HTTP header in HTTP-based bindings; gRPC metadata in gRPC bindings), and an agent that activates it SHOULD echo the URI in the response's A2A-Extensions. In addition:

Protocol Documents

Data model

A Protocol Document is an RDF graph containing exactly one subject typed a2a:ProtocolDocument (the PD subject), with:

PropertyCard.Meaning
a2a:requestShape1..*IRI(s) of the sh:NodeShape(s) every request intent under this protocol MUST conform to. The shape triples are part of the PD graph (self-contained: nothing to fetch at validation time).
a2a:responseShape0..*IRI(s) of the sh:NodeShape(s) a structured response MUST conform to, when the protocol defines one.
dcterms:title, dcterms:description, dcterms:hasVersion0..1 eachHuman-readable metadata.

The PD graph MUST be self-contained: a validator MUST NOT dereference IRIs mentioned in the shapes (no owl:imports-style loading) — everything the SHACL engine needs is inside the hashed graph. Example (execution-verified against the reference codec):

@prefix a2a: <https://w3id.org/jeswr/a2a#>.
@prefix schema: <https://schema.org/>.
@prefix sh: <http://www.w3.org/ns/shacl#>.
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
@prefix dcterms: <http://purl.org/dc/terms/>.

<https://alice.pod.example/protocols/grant-access> a a2a:ProtocolDocument;
    dcterms:title "Grant access";
    dcterms:hasVersion "1.0.0";
    a2a:requestShape a2a:GrantIntentShape.
a2a:GrantIntentShape a sh:NodeShape;
    sh:targetClass a2a:Intent;
    sh:property [ a sh:PropertyShape;
        sh:path a2a:action; sh:minCount 1; sh:maxCount 1; sh:name "action";
        sh:node [ a sh:NodeShape;
            sh:property
                [ a sh:PropertyShape; sh:path rdf:type; sh:minCount 1; sh:hasValue a2a:GrantAction ],
                [ a sh:PropertyShape; sh:path schema:object; sh:minCount 1; sh:name "target"; sh:nodeKind sh:IRI ],
                [ a sh:PropertyShape; sh:path schema:recipient; sh:minCount 1; sh:name "recipient"; sh:nodeKind sh:IRI ],
                [ a sh:PropertyShape; sh:path a2a:mode; sh:minCount 1; sh:name "mode"; sh:nodeKind sh:IRI ] ] ].

Content addressing

The protocol hash pins the content of a PD independent of where it is hosted. It is computed as:

  1. Canonicalize the PD's full graph to canonical N-Quads using RDFC-1.0 [[rdf-canon]].
  2. Compute the SHA-256 digest of the UTF-8 bytes of that canonical form.
  3. Render as "sha256:" + lowercase-hex(digest).

A party that dereferences a PD from a protocolSource (or a card-declared source) MUST recompute the hash over the fetched graph and MUST reject the document — treating the exchange as never upgraded — if it does not equal the pinned hash. The hash, not the URL and not TLS, is the trust anchor: a compromised or substituted host cannot alter a pinned protocol.

Within this extension, the sha256: prefix denotes exactly this construction — RDFC-1.0 canonical N-Quads, then SHA-256 — as a fixed pair. A change to either the canonicalization or the digest algorithm is a breaking change to this specification: it MUST use a new, distinct prefix and is only introducible under a new extension URI (). Implementations MUST reject hash strings whose prefix they do not recognise.

The reference codec [[SOLID-A2A-IMPL]] computes ProtocolDocument.hash over the RDFC-1.0 canonical N-Quads form via rdf-canonize, the W3C reference implementation (landed in solid-a2a 0.2.0) — its ProtocolDocument.hash values are conformant to this section, and any independent RDFC-1.0 implementation agrees on the same canonical bytes. See .

PDs SHOULD be published at HTTPS URLs whose representations are immutable (content-addressed paths or versioned documents); a PD is typically hosted in the offering party's own storage (in the Solid deployment profile, a pod) so protocol definitions inherit the host's access control and availability story.

The upgrade handshake

The handshake is how two agents move a conversation from natural language onto a pinned Protocol Document. It is a pair of extension payloads carried in ordinary A2A messages (binding in ); it adds no RPC methods and no task states.

Upgrade offer

MemberTypeReq.Meaning
kindstringyesThe literal "upgrade-offer".
protocolHashstringyesThe protocol hash of the offered PD.
protocolSourcestringyesHTTPS URL from which the PD can be fetched (and MUST be hash-verified; ).
requiredbooleanyestrue marks this a security-bearing exchange that MUST NOT be silently downgraded to natural language (). Receivers MUST reject an offer whose required is present but not a JSON boolean — a malformed flag MUST NOT be coerced to false.
protocolNamestringnoHuman-readable protocol name.
{
  "kind": "upgrade-offer",
  "protocolHash": "sha256:4af1e70e42283872cbc0dd3a5eeaa1bd86adda728c993447bed8930d990ab509",
  "protocolSource": "https://alice.pod.example/protocols/grant-access",
  "required": true,
  "protocolName": "Grant access"
}

Upgrade response

MemberTypeReq.Meaning
kindstringyesThe literal "upgrade-response".
protocolHashstringyesMUST equal the offer's protocolHash — a response about a different hash answers nothing ().
acceptbooleanyesAccept or decline. Receivers MUST reject a response whose accept is missing or not a JSON boolean — it MUST NOT default to false, which could otherwise authorise NL fallback.
reasonstringnoHuman-readable reason on decline.

Both payloads also have an equivalent RDF form (one subject typed a2a:UpgradeOffer / a2a:UpgradeResponse with predicates a2a:protocolHash, a2a:protocolSource, a2a:protocolName, a2a:required, a2a:accept, a2a:reason; booleans as xsd:boolean literals). A handshake graph MUST contain exactly one such typed subject; receivers MUST reject ambiguous graphs (zero, multiple, or mixed handshake subjects) rather than splice triples across subjects.

The no-silent-downgrade rule

Given an offer O and a purported response R, natural-language fallback for the exchange is permitted only when all of the following hold — otherwise the sender MUST NOT proceed in natural language:

  1. R.protocolHash == O.protocolHash — a response about any other protocol (or an unparseable / absent response) never authorises downgrade (fail closed; this forecloses using an unrelated decline to justify NL fallback);
  2. O.required == false — a security-bearing offer declined means the exchange is aborted with an error (), not retried in prose; and
  3. R.accept == false — if the peer accepted, the exchange proceeds in validated RDF and NL is simply not used.

The rule is the codec-level half of downgrade resistance: it makes silent downgrade a protocol violation rather than a default. It does not by itself authenticate the response — transport/message authentication is the A2A binding's concern, and credential-level protections compose via .

Two required flags, two scopes

FlagScopeEffect
AgentExtension.required Agent Card — the whole agent §4.6 of [[A2A]]: clients MUST activate and comply with the extension to talk to this agent at all.
UpgradeOffer.required One offered exchange This specification: this exchange must run under the pinned PD or be aborted — never silently downgraded to NL ().

Skipping the handshake for card-declared protocols

When an Agent Card pre-declares a PD in params.protocolDocuments () and the client already implements a PD with the same protocol hash, the client MAY send a conforming intent directly — tagging the part with that hash () — without a prior offer/response round. The Agent Card declaration is the standing offer. The agent MUST still validate the intent against the shape before acting.

Message-content binding

All extension payloads ride in A2A Parts (§4.1.6 of [[A2A]]): the data content field for JSON payloads, the text content field with an RDF mediaType for serialized RDF. Core data structures are never altered; per-part attributes go in Part.metadata, per §4.6's extension-point rules.

Part metadata keys

Two metadata keys are defined, namespaced by the extension URI:

KeyValueOn
https://w3id.org/jeswr/a2a-rdf/v1/kind one of "upgrade-offer", "upgrade-response", "intent", "intent-response", "authorization" every extension part (REQUIRED — receivers dispatch on it without sniffing payloads)
https://w3id.org/jeswr/a2a-rdf/v1/protocolHash the protocol hash the part claims conformance to intent and intent-response parts (REQUIRED)

Part profiles

kindContent fieldmediaTypePayload
upgrade-offer / upgrade-response data application/json The JSON object of / . (The RDF form MAY instead be sent as a text part with an RDF media type; the JSON form is the interop baseline.)
intent text or data text/turtle for text; application/ld+json for data The intent graph. MUST contain exactly one subject typed a2a:Intent and MUST conform to the pinned PD's a2a:requestShape(s).
intent-response text or data as for intent The structured response graph; MUST conform to the PD's a2a:responseShape(s) when the PD defines any.
authorization data application/vp (or application/ld+json) A [[vc-data-model-2.0]] Verifiable Presentation packaging the acting agent's Agent Authorization Credential chain, root-first, per [[AGENT-AUTHZ]] ().

A receiving agent MUST SHACL-validate every intent part against the pinned PD's request shape(s) before acting on it, and MUST refuse (with the error of ) an intent that does not conform, whose claimed protocolHash is unknown to the conversation, or whose graph is ambiguous (zero or multiple a2a:Intent subjects). Validation is against the local, hash-verified copy of the PD only — never against shapes fetched at message time.

An example intent graph under the grant-access PD of (execution-verified against the reference codec, including its conforms: true validation result):

@prefix a2a: <https://w3id.org/jeswr/a2a#>.
@prefix schema: <https://schema.org/>.
@prefix acl: <http://www.w3.org/ns/auth/acl#>.

<urn:a2a:intent:kxs8cv> a a2a:Intent;
    a2a:action [ a a2a:GrantAction;
        schema:object <https://alice.pod.example/notes/>;
        schema:recipient <https://bob.example/profile#me>;
        a2a:mode acl:Read, acl:Write ].

Composing with authorization: ODRL policies and Agent Authorization Credentials

This extension defines how a request is expressed and validated, not whether the requester is authorized. The authorization story composes from two companion documents, which this section binds by reference and deliberately does not restate:

Binding points:

  1. A message whose intent part expresses a security-bearing exchange SHOULD carry an authorization part () presenting the acting agent's credential chain in the same Message, so the receiver validates shape and mandate together.
  2. The intent graph MAY reference the exercised policy directly (e.g. <intent> odrl:hasPolicy <policy-iri>); when it does, the IRI MUST match (one of) the svc:policy value(s) in the presented chain — a mismatch is a refusal.
  3. The receiver's decision procedure is the verification algorithm of [[AGENT-AUTHZ]] (signatures ∪ status ∪ revocation, then the fail-closed chain evaluation of [[ODRL-DELEGATION]]) applied to the presented chain, with the SHACL-validated intent as the action under test. Absence of a verifiable grant is a denial.

Nothing in this section is specific to Solid: the credentials are ordinary VC 2.0 documents and the policies ordinary ODRL. In the Solid deployment profile the WebIDs, pods, and access control of [[AGENTIC-SOLID-NOTE]] supply the identity and storage layers.

Error signalling

Extensions cannot add enum values or alter core structures (§4.6 limitations, per [[A2A-EXTENSIONS]]), so failures are signalled with core mechanisms plus one metadata key: a refusing agent SHOULD fail the request using the binding's standard error path (e.g. a JSON-RPC error or a failed task state) and SHOULD attach, on the error's message or metadata, the key https://w3id.org/jeswr/a2a-rdf/v1/error with one of:

CodeRaised when
"protocol-required"a required offer was declined, or a card-required agent received a non-activated request — the exchange is aborted, not downgraded.
"validation-failed"an intent/response part did not conform to the pinned shape (the SHACL validation report MAY be attached as a text/turtle part).
"unknown-protocol"the part's claimed protocolHash is not one negotiated or card-declared for this conversation.
"hash-mismatch"a fetched PD failed hash verification.
"authorization-failed"the presented credential chain did not verify or did not cover the intent (per ).

Extension dependencies

This extension has no required dependencies on other A2A extensions. The authorization composition () depends only on W3C document formats (VC 2.0, ODRL), not on any A2A extension. Per [[A2A-EXTENSIONS]], a client activates this extension alone.

Versioning

Security considerations

In addition to §4.6's general guidance (validate all extension data rigorously; apply the same authentication and authorization to extension traffic as to core traffic):

Privacy considerations

Structured, vocabulary-grounded messages are easier to mine than prose; the same property that enables auditing enables profiling. Agent Card protocolDocuments listings reveal what routines an agent speaks — publishers should treat the card as public metadata and keep sensitive protocols negotiable-on-request (nlNegotiation) rather than card-listed. Authorization parts carry credential chains: present the minimal chain, per the minimisation guidance of [[AGENT-AUTHZ]].

Implementation status — the honest inventory

Verified against the named repositories on 2026-07-03. Nothing below is an endorsement by the A2A project.

PieceStatus
Handshake codec (offer/response encode/decode, strict-boolean parsing, RDF forms) + the no-silent-downgrade decision Implemented (experimental) — [[SOLID-A2A-IMPL]] (encodeUpgradeOffer/decodeUpgradeOffer/ mayDowngradeToNl/handshakeToRdf…)
Protocol Documents: build, serialize, hash, fetch-and-verify; SHACL validation of intents against a PD Implemented (experimental) — [[SOLID-A2A-IMPL]] (buildProtocolDocument/verifyProtocolDocument/ validateIntent), including RDFC-1.0-conformant canonicalization: the codec hashes the RDFC-1.0 canonical N-Quads form via rdf-canonize (landed in solid-a2a 0.2.0) — the alignment gap this table previously tracked is closed ()
Intent data model (NL→RDF translation with an injectable-LLM seam, Turtle/JSON-LD round-trip) Implemented (experimental) — [[SOLID-A2A-IMPL]]
Agent Card production (WebID-anchored descriptor where the AgentExtension entry and protocolDocuments would be emitted) Implemented (experimental) — [[SOLID-AGENT-CARD-IMPL]]; emitting the exact params schema of is an alignment task
A2A transport integration (the A2A-Extensions activation flow, Part assembly/dispatch inside an A2A SDK runtime) Not implemented — the reference codec is deliberately transport-free; wiring it into an A2A SDK is the natural first joint work item of a proposal collaboration
Authorization composition end-to-end (intent + AAC presentation verified together) Specified by composition only — the pieces exist separately ([[AGENT-AUTHZ]] verification via @jeswr/solid-vc + @jeswr/solid-odrl); no integrated implementation yet
A2A project registry entry / governance status Proposed only — no proposal issue opened yet ([[A2A-GOVERNANCE]] proposal phase; maintainer-gated)
w3id.org/jeswr/a2a-rdf and w3id.org/jeswr/a2a# redirects Pending — w3id PRs not yet raised

Worked example — a full exchange

Alice's agent (client) asks Bob's agent (server) to grant Bob read+write access to a container. The exchange is security-bearing, so the offer is required. Payloads marked ✔ were generated and validated with the reference codec [[SOLID-A2A-IMPL]]; the protocol hash shown was computed conformantly to with an independent RDFC-1.0 implementation (rdf-canonize 5.0.0) over the codec-built Protocol Document graph.

0. Discovery

Bob's Agent Card carries the declaration of (with the grant-access PD pre-listed). Alice's agent does not yet implement that PD, so it runs the full handshake rather than the skip of .

1. Offer (Alice → Bob)

POST /a2a HTTP/1.1
Host: agent.bob.example
Content-Type: application/json
A2A-Extensions: https://w3id.org/jeswr/a2a-rdf/v1

{
  "jsonrpc": "2.0", "method": "SendMessage", "id": "1",
  "params": { "message": {
    "messageId": "m-1", "role": "ROLE_USER",
    "extensions": ["https://w3id.org/jeswr/a2a-rdf/v1"],
    "parts": [
      { "text": "I'd like to set up access sharing. Happy to do this over your grant-access protocol." },
      { "data": {
          "kind": "upgrade-offer",
          "protocolHash": "sha256:4af1e70e42283872cbc0dd3a5eeaa1bd86adda728c993447bed8930d990ab509",
          "protocolSource": "https://alice.pod.example/protocols/grant-access",
          "required": true,
          "protocolName": "Grant access"
        },
        "mediaType": "application/json",
        "metadata": { "https://w3id.org/jeswr/a2a-rdf/v1/kind": "upgrade-offer" } }
    ] } }
}

✔ offer object. Bob's agent fetches the PD from protocolSource (HTTPS, size/time-capped), recomputes the RDFC-1.0 hash, and confirms it matches. ✔ the shown hash is the recomputable RDFC-1.0 hash of the PD graph in .

2. Accept (Bob → Alice)

HTTP/1.1 200 OK
Content-Type: application/json
A2A-Extensions: https://w3id.org/jeswr/a2a-rdf/v1

{
  "jsonrpc": "2.0", "id": "1",
  "result": { "message": {
    "messageId": "m-2", "role": "ROLE_AGENT",
    "extensions": ["https://w3id.org/jeswr/a2a-rdf/v1"],
    "parts": [
      { "data": {
          "kind": "upgrade-response",
          "protocolHash": "sha256:4af1e70e42283872cbc0dd3a5eeaa1bd86adda728c993447bed8930d990ab509",
          "accept": true
        },
        "mediaType": "application/json",
        "metadata": { "https://w3id.org/jeswr/a2a-rdf/v1/kind": "upgrade-response" } }
    ] } }
}

Had Bob declined, required: true means Alice's agent aborts with "protocol-required" — it does not re-ask in prose ().

3. Validated intent (Alice → Bob)

POST /a2a HTTP/1.1
Host: agent.bob.example
Content-Type: application/json
A2A-Extensions: https://w3id.org/jeswr/a2a-rdf/v1

{
  "jsonrpc": "2.0", "method": "SendMessage", "id": "2",
  "params": { "message": {
    "messageId": "m-3", "role": "ROLE_USER", "contextId": "ctx-1",
    "extensions": ["https://w3id.org/jeswr/a2a-rdf/v1"],
    "parts": [
      { "text": "@prefix a2a: .\n@prefix schema: .\n@prefix acl: .\n\n a a2a:Intent;\n    a2a:action [ a a2a:GrantAction;\n        schema:object ;\n        schema:recipient ;\n        a2a:mode acl:Read, acl:Write ].",
        "mediaType": "text/turtle",
        "metadata": {
          "https://w3id.org/jeswr/a2a-rdf/v1/kind": "intent",
          "https://w3id.org/jeswr/a2a-rdf/v1/protocolHash": "sha256:4af1e70e42283872cbc0dd3a5eeaa1bd86adda728c993447bed8930d990ab509"
        } }
    ] } }
}

✔ intent graph; ✔ SHACL validation against the PD returns conforms: true. Bob's agent validates the graph against the pinned request shape, then hands the intent to its authorization layer. Were this a delegated agent acting under a mandate, the message would also carry an authorization part with the credential-chain presentation (). No LLM ran on either side of this step.

4. Outcome (Bob → Alice)

Bob's agent performs the grant and replies; if the PD had declared an a2a:responseShape, the reply would carry a conforming intent-response part. On validation failure it would instead fail the request with "validation-failed" and MAY attach the SHACL report as a Turtle part ().