Skip to content

A2A bridge validation receipts

The local A2A bridge is a local-first HTTP+JSON edge for Synapse. Whether it is "production-grade" in the broad sense is not a single conformance pass/fail — it is a set of receipts that survive across the bridge boundary. This page turns the community A2A validation track into that set: the structured artifacts an independent tester records, so anyone can reason about what was actually exercised rather than trusting a claim.

This framing was contributed by Armorer Labs in the A2A validation discussion; it is adopted here as the project's validation template. Two rules run through it:

  • Separate protocol compatibility from operational safety. A bridge can be A2A-shaped and still be unsafe to expose behind a reverse proxy without explicit auth, logging, and egress boundaries. A receipt records both, never one as the other.
  • The interesting case is not the happy-path SDK call. It is restart + bounded replay + a real webhook receiver + a client that assumes durable event history. A crisp trace of that case is what lets people decide whether the bridge is an adapter, a local task runtime, or something that needs a stronger event log behind it.

The receipts

Run synapse a2a-conformance before recording a receipt. It prints the current local matrix against the A2A 1.0.0 operation model; receipt work should update the matching row instead of replacing the matrix with prose.

The repository test suite now includes local real-receiver coverage: push delivery posts to an HTTPS receiver trusted by a test CA and follows a real 307 proxy redirect without dropping the POST body. The delivery client also rejects a public-looking webhook URL when DNS resolves it back to a local receiver before send. A validation receipt is still needed for any public receiver behind production TLS or reverse-proxy infrastructure.

The A2A deployment threat model records the local exposed-bridge review for bearer auth, TLS/proxy placement, state-file permissions, webhook egress, retention, logging, and receipt evidence. A production receipt should still prove the chosen deployment follows that model.

Each receipt is a small, self-contained record. Capture it as JSON, a gist, or a discussion reply — the shape matters more than the medium.

1. Discovery receipt

  • Agent Card returned, the capability-manifest version it was projected from, the endpoint URL, the auth mode, and the client/SDK name and version.

2. Task-lifecycle receipt

  • The submitted payload, the assigned task id, every state transition observed, cancel and timeout behaviour, and the final observed result.

3. Webhook receipt

  • The destination class (public, private, local-network), the bridge's validation decision, how auth headers were handled, the delivery attempts, the retry/backoff observed, and the operator-visible failure mode.

4. Proxy / TLS receipt

  • The public origin, the forwarded headers, where auth was terminated, and whether the protected and public routes stayed separated across the boundary.

5. Replay / subscription receipt

  • Which event window is replayable, what is lost on restart, and how a client detects the gap. This is the receipt the durable-history-assuming client depends on.

6. Threat-model receipt

  • The SSRF / local-network checks exercised, token handling, log redaction, and what a compromised client can still ask the bridge to do.

Local independent HTTP client (in-tree)

Against a running bridge (or the test harness), the repository ships an independent stdlib client that does not import the request-handler path:

synapse a2a-serve --endpoint-url http://127.0.0.1:8877 --host 127.0.0.1 --port 8877 &
synapse a2a-interop-trace --host 127.0.0.1 --port 8877 --output /tmp/a2a-interop.json

The receipt schema is synapse.a2a_interop_trace.v1 (discovery + task lifecycle). It is the deterministic second client stack for the independent matrix row.

Official SDK and TCK receipt (2026-07-10)

The official Python SDK a2a-sdk==1.1.0 discovered the live Agent Card, selected RestTransport, and completed send, get, list, and cancel. The official A2A TCK at commit 5996b79, pinned to specification commit 173695755607e884aa9acf8ce4feed90e32727a1, then ran the HTTP+JSON MUST profile:

Result Count
Passed 55
Failed 5
Skipped 175
Deselected 30

The run closed wire timestamp, explicit version negotiation, AIP-193 error shape, HTTP media-type, unknown-task, continuation, and direct A2A 1.0 inline push-config defects found by the initial diagnostic. The five remaining failures are response-content scenarios: four require exact structured artifacts and one requires a direct Message response. The bridge instead returns a working Task and waits for a SYNAPSE identity; its current plain-chat correlation path cannot express every artifact variant.

The TCK loopback webhook is rejected by the production SSRF guard. Separate repository tests exercise authenticated HTTPS delivery, a real 307 redirect, and DNS-rebinding refusal under an explicit local-test policy. SYNAPSE also has no outbound A2A client/adapter yet, so an independent server pass remains a recorded product gap.

This upgrades the matrix with real official-SDK and official-TCK evidence, but it is partial validation, not A2A certification or full conformance.

How to contribute one

Run the bridge (synapse a2a-card, synapse a2a-serve — see the README's A2A section), exercise a dimension above against your own client/SDK and, where relevant, a real webhook receiver and a reverse-proxy/TLS boundary, and post the receipt to the validation discussion. The restart-plus-replay-plus-real-webhook case is the most valuable one to trace.

Validated dimensions land back in the deployment guide and the A2A section of the README; gaps a receipt exposes become tracked work. Synapse claims no external A2A conformance from screenshots — only from receipts that others can reproduce.