Files
micro--go-micro/internal/website/blog/26.md
T
wehub-resource-sync e071084ebe
govulncheck / govulncheck (push) Has been cancelled
Lint / golangci-lint (push) Has been cancelled
Run Tests / Unit Tests (push) Has been cancelled
Run Tests / Etcd Integration Tests (push) Has been cancelled
Harness (E2E) / Harnesses (mock LLM) (push) Has been cancelled
Harness (E2E) / Provider harnesses (live LLM conformance) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:40:33 +08:00

54 lines
3.5 KiB
Markdown

---
layout: blog
title: "Agents Across Frameworks: A2A"
permalink: /blog/26
description: "Go Micro agents already call each other over RPC. Now they speak the Agent2Agent protocol too — reachable by, and able to reach, agents built on any framework. Cards are generated from the registry, the same way the MCP gateway derives tools."
---
# Agents Across Frameworks: A2A
*June 18, 2026 • Asim Aslam*
Inside a Go Micro system, agents already talk to each other. An agent is a service with an `Agent.Chat` endpoint, so `delegate` just calls another agent over RPC. That works as long as everyone is on Go Micro. The moment an agent is built on a different framework, the conversation stops: it can't call yours, and yours can't call it.
[A2A](https://a2a-protocol.org) — the open Agent2Agent protocol — is the standard that closes that gap, and Go Micro now speaks it.
## A2A is to agents what MCP is to tools
This lines up with something Go Micro already does. The MCP gateway exposes your *services as tools* to any MCP-speaking agent. The A2A gateway exposes your *agents as agents* to any A2A-speaking client. Two interop standards, two front doors — and now both are covered.
The design is the same in both cases: **discovery is generated from the registry.** MCP derives a tool from each service endpoint. A2A derives an **Agent Card** — the JSON descriptor other agents read to find and call yours — from each agent's registry metadata. There is nothing to publish and no code to add. Register an agent, and it has a card:
```bash
micro a2a serve --address :4000
micro a2a list
```
An incoming A2A task is translated to the agent's existing `Agent.Chat` RPC — the same call `delegate` and flows already use. The agent's loop, memory, guardrails, and tool wrappers all apply unchanged. The gateway is a protocol adapter, not a second agent runtime.
## Both directions
Exposing your agents is half of it. The other half is calling agents that aren't yours. The `a2a.Client` does that, by URL, and it's wired into the two places work gets handed off:
```go
// As a workflow step — the cross-framework counterpart to Dispatch:
flow.Step{Name: "research", Run: flow.A2A("https://other.example.com/agents/research")}
```
```go
// From inside an agent, delegate to a URL and it goes over A2A:
// "delegate this to https://other.example.com/agents/research"
```
When `delegate`'s target is an `http(s)` URL instead of a local agent name, the subtask is sent over A2A. The model doesn't learn a new tool; it just delegates to a URL.
## Scope
This is the synchronous JSON-RPC binding: `message/send` runs the agent and returns a completed task, `tasks/get` retrieves one, and Agent Cards are served for discovery. Streaming (`message/stream`), multi-turn `input-required`, and push notifications are advertised as unsupported on the card, so clients negotiate correctly. Those are the follow-ups; the synchronous binding is what makes a Go Micro agent both reachable from, and able to reach, the wider ecosystem today.
## Where it fits
A2A completes the interop set. MCP exposes services as tools, A2A exposes agents as agents, and [x402](/blog/22) handles payment between them — all derived from the registry, none of them a new runtime. An agent stays a service; A2A is one more way to reach it, alongside the `Chat` RPC, `micro chat`, and a flow. Building an agent that the rest of the world can talk to is, again, building a service.
See the [A2A guide](/docs/guides/a2a-protocol) for the full reference.