2
2 Comments

We connected A2A delegation to MCP tools—and tested whether stale evidence reaches execution

An AI agent reads a customer record and decides to issue a refund.

Before it acts, the work is delegated to another agent. That agent eventually calls a payment tool through MCP.

But the customer record changed in the meantime.

The reasoning may have been valid when it was produced. The tool call may also be technically correct. Yet the action is now based on evidence that is no longer current.

That gap becomes harder to see when work crosses agent boundaries.

A2A gives agents a standard way to delegate work. MCP gives agents a standard way to discover and call tools. Neither automatically establishes that the evidence behind a delegated decision is still current when a consequential tool executes.

The path can look like this:

Agent A reads evidence
        ↓
Agent A forms a decision
        ↓
Agent A delegates through A2A
        ↓
Agent B or Agent C receives the task
        ↓
An MCP tool is about to execute

The evidence can change anywhere between the first and final steps.

FreshCtx 0.14.0 introduces a bounded A2A-to-MCP protection path. A signed, expiring and recipient-bound evidence receipt travels with the delegated work. The receiving agent validates it before execution reaches MCP’s native tools/call boundary.

Immediately before the tool executes, FreshCtx revalidates the declared evidence:

  • CURRENT: the evidence has not changed, so the tool executes.
  • STALE_REASONING: required evidence changed, so the tool is blocked.
  • UNVERIFIABLE: the evidence cannot be checked reliably, so the tool is blocked.

Missing, expired, modified and wrong-recipient receipts are also rejected before the protected action runs.

The receipt can preserve the observation linked to the decision, its intended recipient, expiry information, and parent/root correlation across multiple delegations. It deliberately excludes prompts, credentials, source contents, tool arguments and business payloads.

The repository includes an executable three-agent demonstration:

Originating agent
        ↓ A2A
Delegated agent
        ↓ A2A
Executing agent
        ↓ MCP tools/call
Consequential tool

The demonstration verifies three outcomes:

Evidence unchanged       → MCP tool executes once
Evidence changed         → tool does not execute
Evidence cannot be read  → tool does not execute

FreshCtx now applies the same pre-action invariant across MCP, A2A, Agno, LangGraph, OpenAI Agents SDK, Google ADK and ElevenLabs Python tools.

Each platform has a different interception mechanism, but the rule remains:

Observe → Reason → Revalidate → Act

The scope is intentionally precise. CURRENT does not mean the agent selected the correct source, interpreted it correctly, or was authorized to act. It means the declared evidence remained unchanged.

I maintain FreshCtx and would value one specific implementation review from teams operating A2A or MCP workflows:

Is the receiving A2A executor the right enforcement boundary in your architecture, or is there a delegated execution path that could bypass it?

Install:

python -m pip install "freshctx[a2a-mcp]==0.14.0"

GitHub: https://github.com/Hyperwise-LLC/freshctx

PyPI: https://pypi.org/project/freshctx/0.14.0/

on September 6, 2026
  1. 1

    The fail-closed UNVERIFIABLE branch is the right default, but it gives you a new DoS surface: if the evidence store is briefly unreachable, legitimate delegated work gets blocked too. Do you add bounded retries or a circuit breaker before the receipt is rejected? Also curious whether the signed receipt binds the MCP tool arguments, or only the evidence — if it's evidence-only, a valid receipt could be replayed with different tool args.

  2. 1

    The stale-evidence problem is the right framing for A2A + MCP: delegation inherits conclusions, not freshness. A signed, recipient-bound receipt that is revalidated at tools/call is basically the agent-world analog of a TLS session ticket with a short lifetime — cheap to carry, fail-closed on doubt. Curious how FreshCtx handles receipt revocation when the underlying record changes multiple times within one delegation chain — do parent/root correlations re-anchor the whole chain or just the leaf?