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.