AI代理交互协议

A2A和MCP协议提供AI代理之间的标准化交互方式,支持不同框架间的无缝通信和工具调用。

  • by smakubi
  • Python
  • 本地部署
  • 更新于

使用说明

A2A+MCP协议演示

两个开放协议成为可互操作AI代理系统标准的最小、可运行的示例:

  • A2A(代理2代理) --代理人如何相互交谈
  • MCP(模型上下文协议) --代理如何与工具对话

三种不同的框架(Google ADK、LangGraph、BeeAI)都通过A2A进行通信——这就是重点。


两个协议

A2A——代理人对代理人

A2A是一个开放的HTTP协议,允许AI代理使用 不同的框架 无需自定义集成代码即可相互发现和调用。由Google Cloud于2025年4月推出,捐赠给Linux基金会。

A2A代理只是一个HTTP服务器。任何其他说A2A的代理都可以呼叫它。

三个核心概念:

概念 它是什么 你在哪里看到它
代理卡 JSON文档位于 GET /.well-known/agent.json --代理的名称、URL、版本和技能。客户如何 发现 代理人。 a2a_policy_agent.py → LlmAgent(name=..., description=...)
AgentSkill 的 AgentCard中声明的功能。路由器和协调器通过阅读技能来决定呼叫哪个代理。 a2a_provider_agent.py → AgentSkill(...)
代理执行器 传入A2A请求和业务逻辑之间的桥梁。要么实施 execute() 手动或让像ADK这样的框架通过 to_a2a(). a2a_provider_agent.py → 由...处理 langgraph-a2a-server

MCP——代理到工具

MCP是一个开放协议,标准化了LLM代理如何连接到外部工具和数据源。MCP服务器公开任何MCP客户端都可以调用的类型化函数,而不管框架如何。

三个核心概念:

概念 它是什么 你在哪里看到它
MCP服务器 显示一个或多个工具。框架无关。 mcpserver.py
MCP客户端 发现并调用MCP工具的代理端适配器。 a2a_provider_agent.py → MultiServerMCPClient
工具 一个带有docstring的类型化Python函数。LLM读取它并决定何时调用它 mcpserver.py → list_doctors()

它们如何相互补充

A2A=代理人与代理人交谈。MCP=代理与工具对话。

代理可以同时是 A2A服务器 (接受任务)和 MCP客户端 (调用工具来实现它们)。提供商代理正是这样做的。


完整架构

                    ┌─────────────────────────────────────────────────┐
                    │  Option A: client.py (GPT-4o router)            │
                    │  Option B: a2a_orchestrator_client.py (BeeAI)   │
                    └────────────────┬────────────────────────────────┘
                                     │ A2A
                                     │
                    ┌────────────────▼────────────────────────────────┐
                    │         a2a_orchestrator.py  :9996              │
                    │         BeeAI RequirementAgent                  │
                    │                                                 │
                    │  Fetches AgentCards at startup → creates        │
                    │  HandoffTools → routes via LLM reasoning        │
                    └──────────────┬──────────────┬───────────────────┘
                                   │ A2A          │ A2A
                   ┌───────────────▼──┐      ┌───▼──────────────────────┐
                   │ Policy Agent     │      │ Provider Agent           │
                   │ :9999            │      │ :9997                    │
                   │ Google ADK       │      │ LangGraph + MCP          │
                   │                  │      │                          │
                   │ LlmAgent         │      │ ReAct agent loop         │
                   │ + to_a2a()       │      │       │ MCP (stdio)      │
                   │      │           │      │       ▼                  │
                   │      │ LiteLLM   │      │ mcpserver.py             │
                   │      ▼           │      │       │                  │
                   │ Gemini + PDF     │      │       ▼                  │
                   └──────────────────┘      │ doctors.json            │
                                             └──────────────────────────┘

特工Deep Dives

策略代理——谷歌ADK

文件夹: policy_agent.py + a2a_policy_agent.py | 端口: 9999

回答有关保险计划覆盖范围的问题。

User question (via A2A)
    │
    ▼
Google ADK LlmAgent receives request
    │
    ├── Decides to call answer_policy_question() tool
    │
    ▼
policy_agent.py → LiteLLM → Gemini API + PDF (base64)
    │
    ▼
to_a2a() sends response back over A2A

按键图案-- to_a2a() 与手动A2A SDK相比:

A2A SDK手册 谷歌ADK
定义 AgentCard 您自己 生成自 LlmAgent(name=..., description=...)
实施 AgentExecutor.execute() ADK内部处理
电线 DefaultRequestHandler + A2AStarletteApplication to_a2a(agent) 做这一切
约80行 约20行

权衡:ADK隐藏了协议细节。手动方法更具教育性。


提供者代理--LangGraph+MCP

文件夹: a2a_provider_agent.py + mcpserver.py | 端口: 9997

按地点查找医疗保健提供者,并告诉你他们接受什么保险。

User question (via A2A)
    │
    ▼
LangGraph ReAct agent loop
    ├── LLM thinks: "I need to search for doctors"
    ├── Calls list_doctors() via MCP ──► mcpserver.py subprocess (stdio)
    │                                        └── filters doctors.json
    ├── LLM receives results
    └── LLM formats readable answer
    │
    ▼
A2A response (result in task.artifacts)

关键模式: 一个代理中有三个协议:

  1. A2A --外层,接受任务并提供响应(langgraph-a2a-server)
  2. LangGraph --中间层,运行ReAct推理循环
  3. 主控程序 --内层,将LangGraph连接到 list_doctors 通过stdio工具

mcpserver.py 作为子进程自动启动 MultiServerMCPClient --切勿手动启动。


BeeAI编排器

文件: a2a_orchestrator.py | 端口: 9996

协调两个子代理来回答跨越两个领域的复杂问题。

User question (via A2A)
    │
    ▼
BeeAI RequirementAgent
    │
    ├── ThinkTool: reasons about what's needed
    │
    ├── HandoffTool → Policy Agent (A2A :9999)
    │   "What does the plan cover for mental health?"
    │
    ├── ThinkTool: reasons about next step
    │
    ├── HandoffTool → Provider Agent (A2A :9997)
    │   "Find psychiatrists in Boston, MA"
    │
    └── Synthesizes both answers into one response
    │
    ▼
A2A response

关键图案——BeeAI的优雅:

  • 在启动时, check_agent_exists() 获取每个子代理的代理卡
  • HandoffTool 将每个A2A代理包装为可调用工具——描述直接来自AgentCard
  • ConditionalRequirement 防止无限循环(每个代理每个请求调用一次max)
  • 零硬编码路由——LLM根据AgentCard描述决定调用哪些工具

client.py——原始A2A SDK+GPT-4o路由器

文件: client.py

直接调用两个子代理的交互式客户端(绕过编排器)。使用GPT-4o读取AgentCard并智能路由。

Startup: fetch AgentCards from both agents → show discovery output

Loop:
    User types question
        → GPT-4o reads AgentCards, reasons about which agent fits
        → Routes to chosen agent via A2A
        → Prints response

使用此功能: 演示A2A发现,并展示任何LLM如何纯粹从AgentCard元数据充当路由器。


项目结构

a2a/
│
├── policy_agent.py               # Plain Python class — no A2A, no framework
│                                 # Reads PDF at startup, answers via Gemini/LiteLLM
│
├── a2a_policy_agent.py           # Google ADK: LlmAgent + to_a2a() (port 9999)
│
├── a2a_provider_agent.py         # LangGraph + MCP as A2A server (port 9997)
│
├── mcpserver.py                  # MCP server — exposes list_doctors() tool (stdio)
│
├── a2a_orchestrator.py           # BeeAI RequirementAgent orchestrator (port 9996)
│                                 # Reads AgentCards, coordinates sub-agents
│
├── a2a_orchestrator_client.py    # Interactive client for the BeeAI orchestrator
│                                 # Keeps conversation memory across follow-ups
│
├── client.py                     # Interactive client with GPT-4o router
│                                 # Calls sub-agents directly (no orchestrator)
│
├── helpers.py                    # setup_env() — loads .env, suppresses warnings
│
├── data/
│   ├── 2026AnthemgHIPSBC.pdf    # Insurance policy PDF (Policy Agent)
│   └── doctors.json              # Doctor dataset (MCP server)
│
├── example.env                   # Environment variable template
└── pyproject.toml                # Project dependencies

设置

1.API密钥

密钥 使用人 获取
GEMINI_API_KEY 策略代理、提供者代理、编排器 谷歌AI工作室
OPENAI_API_KEY 路由器在 client.py (GPT-4o) OpenAI平台

2.配置环境

cp example.env .env
# Edit .env and fill in both API keys

3.安装依赖项

uv sync

4.VS代码解释器

Cmd+Shift+P → Python:选择解释器 → 选择 .venv 在这个文件夹中。


跑步

选项A——两个代理+GPT-4o路由器(3个终端)

# Terminal 1
uv run a2a_policy_agent.py       # Google ADK, port 9999

# Terminal 2
uv run a2a_provider_agent.py     # LangGraph + MCP, port 9997

# Terminal 3
uv run client.py                 # GPT-4o router, interactive

选项B——全栈BeeAI编排器(4个终端)

# Terminal 1
uv run a2a_policy_agent.py       # Google ADK, port 9999

# Terminal 2
uv run a2a_provider_agent.py     # LangGraph + MCP, port 9997

# Terminal 3 — start AFTER 1 & 2 are running
uv run a2a_orchestrator.py       # BeeAI orchestrator, port 9996

# Terminal 4
uv run a2a_orchestrator_client.py  # Interactive, with memory

重要提示: 仅在子代理运行后启动编排器(终端3)——它调用 check_agent_exists() 在启动时获取两个AgentCard。


要尝试的示例问题

问题 最佳客户
“我的计划包括心理健康吗?” client.py → 策略代理
“我的免赔额是多少?” client.py → 策略代理
“在波士顿找心理医生” client.py → 提供商代理
“阿曼达·福斯特医生接受什么保险?” client.py → 提供商代理
“我在波士顿。我有什么心理健康保险,并在我附近找一位精神病医生?” a2a_orchestrator_client.py (同时调用两者)

关键依赖

包 角色
a2a-sdk A2A协议-- AgentCard, AgentExecutor, ClientFactory
google-adk 谷歌代理开发工具包-- LlmAgent, to_a2a()
mcp MCP协议-- FastMCP 服务器工具包
langchain-mcp-adapters MultiServerMCPClient --LangGraph↔ MCP电桥
langgraph 在提供者代理中重新执行代理循环
langgraph-a2a-server 将LangGraph图包装为A2A HTTP服务器
beeai-framework RequirementAgent, HandoffTool, A2AServer
litellm 统一LLM API-Gemini+OpenAI,带有一个接口
langchain-litellm LiteLLM的LangChain适配器

延伸阅读