Overview
TheA2AVerificationInterceptor is the central component of QWED A2A. Every inter-agent message passes through it before reaching the recipient.
The
trace_id parameter is required and must be provided by the caller. This ensures all verdicts and JWT attestations are deterministic and auditable. The HTTP gateway (POST /a2a/intercept) generates this automatically.Verification pipeline
1
Schema Validation
The incoming
AgentMessage is validated by Pydantic:sender_agent_idandreceiver_agent_idmust be 1–256 chars, no control characterspayloadis required (dict)payload_typedefaults toGENERALif not specified- Timestamps are timezone-aware UTC
2
Trust Boundary
The trust boundary evaluates the sender→receiver pair:
- Global blocklist check
- Pair-level block check
- Allowlist check (in strict mode)
- Token-bucket rate limiting
config.trusted_agents are pre-added to the trust boundary allowlist at interceptor construction time. There is no separate bypass step — trusted agents still flow through engine routing and receive a normal verdict.3
Engine Routing
Based on
payload_type, the message is routed to the appropriate verification engine (finance_guard, logic_guard, code_guard). Payload types with no engine (GENERAL, DATA_QUERY) return an unverifiable engine result instead of being silently forwarded.4
Verdict & Attestation
The engine result is wrapped in a
VerificationVerdict. FORWARDED, BLOCKED, and HEURISTIC_PASS verdicts are signed with an ES256 JWT attestation. UNVERIFIABLE verdicts carry no JWT — issuing a signed token for content that was never verified would be a false cryptographic claim.Verification engines
Finance guard
Verifies financial claims using deterministic Decimal arithmetic. Recomputes totals from line items and compares against theclaimed_total.
Empty or malformed payloads return
UNVERIFIABLE, not FORWARDED. If a FINANCIAL_TRANSACTION payload is missing data, line_items, or claimed_total, or contains non-numeric amounts, the finance guard returns status=unverifiable with no JWT attestation. Earlier releases collapsed these cases to a signed FORWARDED verdict, which falsely attested that the math had been checked.Logic guard
Detects logical contradictions — claims where the same proposition is both asserted and negated.Empty or malformed logic payloads return
UNVERIFIABLE. A LOGIC_ASSERTION payload with a missing, non-list, or empty assertions array — or with malformed assertion entries — returns status=unverifiable and no JWT attestation. There is nothing to check, so nothing is attested.Code guard
Scans code payloads using a two-layer approach. AST structural analysis runs first; regex heuristics only run when the AST layer finds nothing. Layer 1 — AST structural analysis (primary). The code is parsed into an abstract syntax tree and inspected for direct dangerous constructs:
Layer 2 — Regex heuristic scan (secondary). Catches obfuscation patterns that survive AST parsing:
If either layer finds a threat, the verdict is
BLOCKED (the reason notes which layer triggered). If both layers are clean, the verdict is HEURISTIC_PASS — a signed attestation that no known dangerous constructs were found, not a deterministic guarantee that the code is safe to execute.
Passthrough (unverifiable)
Messages withpayload_type of GENERAL or DATA_QUERY have no verification engine. The interceptor returns an UNVERIFIABLE verdict with engine="passthrough", no JWT attestation, and reason "No verification engine available for this payload type". The message is not silently forwarded — callers must decide whether to route unverified content downstream based on their own policy.
Verdict statuses
Every call tointercept() returns a VerificationVerdict with one of five statuses. Only statuses backed by a real verification decision carry a signed JWT attestation.
Configuration reference
TheInterceptorConfig controls which engines are active:
Error handling
Whenblock_on_error=True (default), any exception in a verification engine results in a BLOCKED verdict. When False, the message is FORWARDED despite the error — useful for observability-only deployments.
block_on_error=True (default)
block_on_error=True (default)
Engine exception →
BLOCKED verdict with error reason. Safe default for production.block_on_error=False (observability mode)
block_on_error=False (observability mode)
Engine exception →
FORWARDED verdict. The error is logged but doesn’t block communication. Use for shadow deployments.