In August 2026, Google's Agent2Agent protocol moved into the Agentic AI Foundation, putting it under the same roof as Anthropic's Model Context Protocol for the first time. The foundation has grown from fewer than 40 members at its December 2025 launch to more than 250 in eight months, and the two protocols now form the complementary stack every agent platform is standardizing on: MCP is the vertical edge from an agent down to its tools, A2A is the horizontal edge between agents.
The governance merger is the news. The design question it forces is more interesting: now that your coding agent and your operations agent finally speak the same two protocols, what exactly should cross the wire when one hands a deploy investigation to the other?
The short answer, up front: A2A carries the diagnosis, MCP carries the authority, and no token crosses between agents. A coding agent that spots a failing deploy sends the ops agent a task containing evidence, a suspected cause, and a requested action — but no credentials. The ops agent then acts as itself, through its own narrowly scoped MCP tools, each call authenticated and logged. Here is the whole handoff in four steps:
- The coding agent diagnoses the failed deploy and packages symptoms, log evidence, and a requested action into an A2A task addressed to the ops agent — with its own identity attached and no bearer token inside.
- The ops agent receives the task over A2A, authenticating the sender against the ops agent's declared authentication requirements.
- The ops agent investigates further using its own MCP tools (deploy status, logs), presenting its own credentials — never the coder's.
- The rollback tool executes only when a recorded human or policy approval exists; the approval reference lands in the audit log next to the caller's identity.
Everything below unpacks those four steps into a design you can implement: the failure mode it replaces, the narrow MCP surface, the worked A2A task, and the three invariants — identity, approval boundary, least privilege — mapped onto Kubernetes RBAC.
Why the naive handoff fails
The obvious way to connect two agents is also the worst: give them the same credentials. The coding agent holds a bearer token that can read logs and trigger rollbacks, and when it needs operations help, it pastes that token into the handoff message — or worse, both agents mount the same kubeconfig. The ops agent then rolls back the deploy as the coding agent. It works on the first day, which is exactly why teams ship it.
It fails the first time anyone asks the incident-review question: who authorized this rollback? The audit log shows one identity performing both the diagnosis and the production write, because from the platform's perspective they were one identity. You cannot distinguish "the ops agent investigated and a human approved" from "the coding agent's token leaked into a log and something else used it." Blast radius follows the same blur: a prompt-injection attack against the coding agent — via a malicious issue comment, a poisoned doc page, a crafted stack trace — inherits deploy authority it was never meant to hold, because the token travels with the conversation.
This is the confused-deputy problem wearing an agent costume, and the A2A/MCP split is the industry's answer to it. The two protocols divide the world precisely along the line the naive handoff erases: A2A moves work between agents, MCP moves capability between an agent and a platform. Credentials belong only on the second edge. Once you accept that division, the design almost writes itself.
MCP stays the narrow tool interface
On the MCP edge, the ops agent meets the platform through a small, audited tool surface — not a shell, not a cluster-admin kubeconfig. For deploy operations, three tools cover the realistic workflow:
get_deploy_status— read the rollout state, replica counts, and recent events for a service.read_service_logs— fetch bounded log excerpts for a deploy window, with explicit time and line limits.execute_rollback— roll a service back to a pinned prior revision. This is the only write, and it refuses to run without an approval reference it can verify.
Each tool sits behind OAuth 2.1 authorization following the MCP spec's Protected Resource Metadata model: the client presents a bearer token, the server validates it, and scopes decide which tools the token may invoke. Authorization is optional in the MCP specification, but the spec says HTTP-based servers that implement it should conform to this flow — and for anything that can touch production, "optional" is not a setting you leave off. The ops agent's token carries scopes for exactly these three tools and nothing else: no secret reads, no arbitrary pod exec, no cluster-wide mutation.
Every invocation lands in a structured audit log with the same fields: caller identity, tool name, arguments, and — for the rollback — the approval reference. That log is the artifact the naive handoff destroys. When the postmortem asks who authorized the rollback, the answer is a row: the ops agent's identity, the human or policy approval it cited, and the exact revision it rolled to. The coding agent appears nowhere in that row, because it authorized nothing.
A2A carries the diagnosis, not the authority
The horizontal edge does the opposite job: it moves context, not capability. Before sending anything, the coding agent fetches the ops agent's AgentCard — the signed metadata document at /.well-known/agent.json that advertises the ops agent's skills ("investigate failed deploys", "execute approved rollbacks") and its authentication requirements. The A2A specification requires servers to authenticate every incoming request against those declared requirements, so the ops agent knows which peer it is hearing from before it reads a word of the diagnosis.
The handoff itself is a task object. For a failed deploy, the honest version looks like this:
{
"taskId": "deploy-investigation-4471",
"from": "coding-agent/checkout-service",
"to": "ops-agent/production",
"status": "needs-investigation",
"diagnosis": {
"symptom": "checkout-service rollout stuck: 2/5 pods Ready for 14 minutes",
"evidence": [
"readiness probe failing on pods checkout-7d9f / checkout-7d2b",
"last 200 lines of checkout-7d9f show DB connection timeouts after migration 0042"
],
"suspectedCause": "migration 0042 added a NOT NULL column; old code path still writing NULLs"
},
"requestedAction": "confirm and roll back to revision 118 if the migration hypothesis holds",
"approvalState": "none-yet"
}Read that object for what it contains and what it pointedly does not. It contains everything a competent on-call engineer would want in a handoff: the symptom, the evidence, a falsifiable hypothesis, and a concrete requested action. It does not contain a token, a kubeconfig, a password, or any ambient authority whatsoever. The "approvalState": "none-yet" line is load-bearing: it tells the ops agent that no one has approved anything, so the requested rollback is a proposal to validate, not an order to execute.
This is also where least privilege gets its teeth. The coding agent cannot grant what it does not have: its own MCP scopes cover reading code and CI status, not production writes, so even a compromised coding agent can at most send a convincing-sounding task. The ops agent still has to verify the evidence with its own read tools, and the rollback still needs its own approval. Each layer re-checks rather than trusting the handoff, which is what makes the design survive the injection scenario that kills the shared-token approach.
The three invariants, mapped to Kubernetes RBAC
Strip the design down and three invariants do all the work. Each maps to a concrete Kubernetes mechanism, and each has a specific failure waiting if you skip it:
| Invariant | Mechanism | What breaks without it |
|---|---|---|
| Originating identity is preserved | One ServiceAccount per agent; the MCP server validates tokens via TokenReview and logs the caller on every tool call | Concurrent handoffs become unattributable — two investigations blur into one identity and the audit log can't say which agent did what |
| The approval boundary survives the handoff | execute_rollback verifies a recorded human or policy approval before running; the approval reference is part of the audit row | The handoff itself becomes the authorization — whoever can send the ops agent a task can roll back production, and A2A becomes a remote rollback API with no gate |
| Each agent holds least privilege | The ops agent's Role allows broad reads but production writes only through the approval-gated tool; the coding agent's Role has no production writes at all | A compromised or confused coding agent inherits deploy authority through the shared token, and one prompt injection away from a self-inflicted outage |
A few notes on making the table real. Per-agent ServiceAccounts are the easy part — the discipline is in refusing to share them "temporarily," because temporary sharing has a way of surviving into the incident.
The approval verification belongs in the MCP server, not in the agent's prompt: a rollback tool that checks its own preconditions cannot be talked out of them by a clever task description, while a prompt-level instruction can. And the "broad reads" side of the ops agent's Role deserves a second look in multi-tenant setups, where telemetry for every tenant flows through shared backends and per-tenant scoping — the same tenant-boundary thinking behind the Cortex and Mimir isolation debate — applies to what the agent is allowed to see, not just what it may change.
The payoff compounds in incident review. When a rollback goes wrong, the trail reads like a well-run human on-call: the coder's diagnosis task with its evidence, the ops agent's independent verification reads, the recorded approval, and the rollback row citing all three. The A2A transcript explains why; the MCP audit log proves who and with what permission. Neither protocol could tell the full story alone, which is precisely why having both under one foundation matters — the identity and audit story can now evolve as one design instead of two vendors' integration guides.
Audit your own agent-ops split
If you already run agents against production — or plan to this quarter — check your handoff against this list before your next incident does it for you:
- No credentials in A2A tasks. Grep your agent transcripts for tokens, kubeconfigs, and connection strings crossing the agent-to-agent edge. Any hit is a shared-token handoff wearing a protocol costume.
- AgentCards declare authentication, and servers enforce it. Discovery without authentication is a phone book for attackers; the spec requires authenticating every request, so verify yours does.
- The write tools verify approvals themselves. If your rollback path trusts the agent's claim that "the human approved it," move the check into the tool, where prompts can't reach it.
- One identity per agent, end to end. The ServiceAccount that calls the tool, the name in the audit log, and the principal in the RBAC binding should all agree — for every agent in the chain.
- The audit log answers the postmortem. Pick your last agent-driven production change and try to reconstruct who requested it, who approved it, and what permission executed it from logs alone. If you can't, the trail has a gap exactly where the next incident will look.
Shared governance won't write this design for you — the AAIF merger aligns the specs, but the ServiceAccounts, scopes, and approval gates are still yours to build. What the merger does give you is a stable target: one foundation where the vertical edge and the horizontal edge evolve together, so the handoff you design today doesn't rot into a vendor-specific integration tomorrow. Build the split now — diagnosis over A2A, authority over MCP, approval in the tool — and the next time a deploy fails at 3am, the transcript will show two agents doing exactly what a good on-call team does: one bringing the evidence, the other bringing the judgment, and neither borrowing the other's keys.
Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own, with an MCP surface that treats agents as first-class operators. Star the repo on GitHub or deploy your first app today.



