# Agents Across Frameworks: A2A

> 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.

---

LLMS index: [llms.txt](/llms.txt)

---

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/2026/06/15/integrating-x402-payments-for-agents/) 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.
