当AI学会分工合作:用MCP和A2A协议搭一套多智能体系统,跑了跑真实业务流程
大家好,我是摘星,今天我们来聊聊一个让AI从"只会聊天"变成"真能干活"的关键转折------多智能体协作,以及让这件事成为可能的两个协议:MCP和A2A。
去年这时候,大多数人还在纠结怎么写好Prompt让模型输出更准确。今年风向完全变了------Google、Meta、阿里、华为密集推出多智能体系统的商业解决方案,Gartner把企业级AI智能体列为2026年十大战略技术趋势之一,麦肯锡预测协作式智能体工作流将迎来广泛应用。背后推着这波变革的,是两套看起来不起眼但实际决定了整个生态走向的开放协议:Anthropic推出的MCP解决Agent与工具之间的连接问题,Google推出的A2A解决Agent与Agent之间的通信问题。今天这篇文章,我会把这两个协议的技术原理拆开讲清楚,然后用LangGraph框架从零搭一套三智能体协作系统,跑通一个真实的业务流程------包括代码、架构图、踩坑记录。不管你是在评估要不要上多智能体架构,还是已经动手在做了,这篇文章都能给你一些参考。
一、为什么说2026年是多智能体的真正起点
先说一个数据:Google趋势报告显示,全球已有超过一半的先行企业将AI智能体投入了生产环境。这个数字在2024年还不到15%。一年翻三倍多,说明什么?说明Agent不是概念了,是真的有人在用。
这个转变的核心逻辑其实不复杂。之前的AI应用模式是"一个模型干所有事"------你给它一个任务,它生成一个回答。但真实世界的业务流程不是这样的。一个订单处理流程可能涉及:查库存、核对价格、生成发货单、通知物流、更新CRM。每个环节需要不同的工具、不同的数据源、不同的判断逻辑。让一个大模型一口气做完这些,幻觉率高得吓人,出错了你都不知道错在哪一步。
多智能体系统的思路是:把这些环节拆开,每个环节交给一个专门的Agent,每个Agent只负责自己最擅长的那一件事。它们之间通过协议通信、通过工具协作、通过规则编排。这样做的好处是------每个Agent的职责清晰,出了问题容易定位;每个Agent可以用最适合的模型和工具;整个流程可以监控、可以回滚、可以审计。
2026年之所以成为转折点,几个关键条件刚好凑齐了:
模型能力到位了。 Google在4月初刚发布的Gemma 4系列,从2B到31B四个规格,原生支持多模态输入,专门强化了多步规划和复杂逻辑推理能力------这两个能力恰恰是Agent工作流最需要的。Gemma 4的31B Dense模型在AIME 2026数学竞赛中表现优异,Arena AI排行榜上位列全球开源模型第三名。这意味着你不需要万卡集群,开源模型就够用了。
协议标准到位了。 MCP在2024年底由Anthropic发布,经过一年多的生态建设,已经有了成熟的Python/TypeScript SDK、几十个社区维护的Server。A2A在2025年4月由Google推出,获得了50多家技术伙伴支持,把"Agent之间怎么说话"这件事标准化了。
框架成熟了。 LangGraph、AutoGen、CrewAI三大框架经过两年的迭代,各自找到了明确的应用定位。根据Langfuse的统计,LangGraph月搜索量达到27,100,CrewAI 14,800,AutoGen紧随其后。框架选型不再是"哪个好"的问题,而是"哪个适合我的场景"。
二、MCP:让AI学会使用工具
MCP的全称是Model Context Protocol,由Anthropic在2024年11月发布。它要解决的问题用一个句子概括:AI模型怎么安全、高效地调用外部工具和数据源。
你可能会说,Function Calling不是早就有了吗?确实,GPT系列从2023年就支持Function Calling了。但Function Calling有个根本问题------每个模型的函数调用格式不一样,每个平台的工具定义方式不一样,每换一个模型你就得重写一遍工具接入代码。这就像每个手机品牌用不同的充电接口一样,对开发者来说是纯粹的浪费。
MCP的做法是定义一套统一的标准协议。不管你底层用的是Claude、GPT、Gemini还是开源模型,工具的接入方式都一样。
MCP的三层架构
MCP的架构可以用三个角色来理解:
Host(宿主应用)
如 Claude Desktop / IDE
MCP Client 1
MCP Client 2
MCP Client 3
MCP Server A
数据库查询工具
MCP Server B
文件系统工具
MCP Server C
API调用工具
Host(宿主应用):你运行AI应用的主程序,比如Claude Desktop、VS Code中的AI插件。它负责管理所有的Client实例。
MCP Client:Host内部的子进程,每个Client与一个Server保持一对一的连接。Client负责协议握手、能力协商、消息路由。
MCP Server:提供具体能力的服务端程序,暴露三种东西------Tools(可调用的函数)、Resources(可读取的数据)、Prompts(预设的提示模板)。
这个架构的关键设计决策是:每个MCP Server运行在独立的进程中。这意味着Server的崩溃不会影响Host和其他Server,安全性得到了天然保障。
动手写一个MCP Server
我们来写一个简单的MCP Server,提供两个工具:一个是查询产品库存,一个是计算折扣价格。这是电商场景中最基础的两个能力。
python
# server.py - 一个简单的 MCP Server 示例
import asyncio
from mcp.server.models import InitializationOptions
from mcp.server import Server
from mcp.types import Tool, TextContent
# 创建 Server 实例
app = Server("ecommerce-tools")
# 模拟库存数据
INVENTORY = {
"SKU-001": {"name": "机械键盘 Pro", "stock": 128, "price": 699.0},
"SKU-002": {"name": "4K显示器", "stock": 45, "price": 2999.0},
"SKU-003": {"name": "无线鼠标", "stock": 0, "price": 199.0},
}
@app.list_tools()
async def list_tools() -> list[Tool]:
"""声明 Server 提供的工具列表"""
return [
Tool(
name="query_inventory",
description="根据SKU编号查询产品库存和价格信息",
inputSchema={
"type": "object",
"properties": {
"sku": {
"type": "string",
"description": "产品SKU编号,如 SKU-001"
}
},
"required": ["sku"]
}
),
Tool(
name="calculate_discount",
description="根据原价和折扣率计算最终价格",
inputSchema={
"type": "object",
"properties": {
"price": {"type": "number", "description": "原价"},
"discount_rate": {"type": "number", "description": "折扣率,0.8表示八折"}
},
"required": ["price", "discount_rate"]
}
)
]
@app.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
"""处理工具调用请求"""
if name == "query_inventory":
sku = arguments["sku"]
product = INVENTORY.get(sku)
if not product:
return [TextContent(type="text", text=f"未找到SKU: {sku}")]
return [TextContent(
type="text",
text=f"产品: {product['name']}, 库存: {product['stock']}件, "
f"单价: ¥{product['price']:.2f}"
)]
elif name == "calculate_discount":
final_price = arguments["price"] * arguments["discount_rate"]
return [TextContent(
type="text",
text=f"原价: ¥{arguments['price']:.2f}, "
f"折扣率: {arguments['discount_rate']}, "
f"折后价: ¥{final_price:.2f}"
)]
else:
return [TextContent(type="text", text=f"未知工具: {name}")]
async def main():
from mcp.server.stdio import stdio_server
async with stdio_server() as (read_stream, write_stream):
await app.run(
read_stream, write_stream,
InitializationOptions(
server_name="ecommerce-tools", server_version="1.0.0"
)
)
if __name__ == "__main__":
asyncio.run(main())
这段代码的核心逻辑是:通过@app.list_tools()声明工具列表和参数Schema,通过@app.call_tool()处理具体的工具调用。MCP协议要求所有工具必须有明确的inputSchema(JSON Schema格式),这样Client在做参数校验和类型提示的时候就有据可依。通信层用的是stdio(标准输入输出),MCP也支持SSE(Server-Sent Events)用于远程连接场景。注意每个工具的description要写清楚------这个描述会被发送给LLM,模型根据描述来决定什么时候调用哪个工具,写得不准确会导致模型选错工具。
三、A2A:让AI学会和其他AI对话
MCP解决的是"AI怎么用工具"的问题。但如果你有多个AI Agent需要协作------比如一个负责分析用户需求,一个负责查数据,一个负责生成报告------它们之间怎么通信?这就是A2A要解决的问题。
A2A的全称是Agent2Agent Protocol,由Google在2025年4月发布。如果打个比方,MCP是"Agent的USB接口"(标准化的工具连接),A2A就是"Agent的HTTP协议"(标准化的Agent间通信)。
Agent Card:AI的"名片"
A2A协议中最核心的概念是Agent Card。每个Agent在网络上都需要发布一个JSON格式的"名片",说明自己是谁、能做什么、怎么联系。
json
{
"name": "inventory-agent",
"description": "库存管理智能体,负责查询库存、预警缺货、建议补货方案",
"url": "https://agents.example.com/inventory",
"version": "1.2.0",
"capabilities": {
"streaming": true,
"pushNotifications": true
},
"skills": [
{
"id": "check-stock",
"name": "库存查询",
"description": "根据SKU或产品名称查询实时库存数量和仓库位置",
"inputSchema": {
"type": "object",
"properties": {
"sku": {"type": "string"},
"warehouse": {"type": "string", "enum": ["北京", "上海", "广州"]}
}
}
},
{
"id": "restock-alert",
"name": "补货预警",
"description": "扫描库存低于安全阈值的SKU,生成补货建议清单",
"inputSchema": {
"type": "object",
"properties": {
"threshold": {"type": "integer", "description": "安全库存阈值"}
}
}
}
],
"authentication": {
"type": "bearer",
"description": "需要Bearer Token认证"
}
}
这个JSON看起来简单,但它解决了一个很关键的问题:Agent之间的发现和互操作。想象一下,你的系统里有五个Agent,分别来自不同的开发团队,有的用LangGraph实现,有的用AutoGen实现,有的用Google ADK实现。以前它们之间根本没法对话,现在只要每家都发布一个标准的Agent Card,任何Agent都能读懂另一家能做什么、怎么调用。
A2A的通信流程是:Agent A要找Agent B协作时,先去拉取Agent B的Agent Card(通常托管在固定URL如/.well-known/agent.json),根据Card中的skills描述决定是否匹配需求,匹配成功后通过A2A协议发送Task请求。整个过程基于HTTP,支持流式传输。
MCP vs A2A:不是竞争,是互补
很多人第一次接触这两个协议时会问:它们是不是在竞争?答案是明确的:不是。它们解决的是完全不同层面的问题。
| 维度 | MCP | A2A |
|---|---|---|
| 解决的问题 | Agent如何连接外部工具和数据 | Agent之间如何发现彼此并协作 |
| 通信方向 | 单向(Agent → Tool) | 双向(Agent ↔ Agent) |
| 发起方 | Anthropic | |
| 发布时间 | 2024年11月 | 2025年4月 |
| 核心概念 | Tools、Resources、Prompts | Agent Card、Task、Message |
| 传输协议 | stdio / SSE | HTTP |
| 类比 | USB接口(标准化外设连接) | HTTP协议(标准化网络通信) |
一个完整的多智能体系统通常同时使用这两个协议:MCP让每个Agent能够使用数据库、API、文件系统等外部工具;A2A让多个Agent之间能够分工协作。两者的关系更像是"横向"和"纵向"------MCP是纵向的(Agent向下连接工具),A2A是横向的(Agent之间横向协作)。
四、三大框架怎么选
协议是基础设施,框架是你真正写业务逻辑的地方。2026年主流的多智能体框架有三个,各自的定位很不一样。
| 框架 | 开发者 | 核心理念 | 月搜索量 | 最佳场景 |
|---|---|---|---|---|
| LangGraph | LangChain团队 | 把Agent工作流建模为有向图 | 27,100 | 需要精细控制流程的生产系统 |
| AutoGen | 微软 | Agent之间通过对话协作解决问题 | ~10,000 | 需要Agent讨论、辩论、反复迭代的场景 |
| CrewAI | CrewAI Inc | 以角色分配的方式组织Agent团队 | 14,800 | 快速搭建角色明确的Agent团队 |
LangGraph的思路最"工程化"------它把多智能体工作流建模成一个有向图,每个节点是一个Agent或者一个处理步骤,边定义了执行顺序和条件分支。这种模型对复杂业务流程的描述能力很强,也方便调试和监控。你可以在图上加条件边(conditional edge),让流程根据上一步的输出动态选择下一步走哪个分支。
AutoGen的特点是"对话驱动"。它把多Agent协作看作一群专家在讨论问题,每个Agent有自己的人设和专业知识,它们通过多轮对话来达成共识或者分工。适合那些需要"集体决策"的场景,比如多个分析Agent对同一份数据给出不同角度的解读,最后综合出一个结论。
CrewAI走的是"角色扮演"路线。你给每个Agent设定一个角色(Role)、一个目标(Goal)和一个背景故事(Backstory),然后给整个团队一个任务。CrewAI会自动分配子任务、协调执行顺序。上手最快,但在流程控制精度上不如LangGraph。
如果你要做生产级的多智能体系统,我的建议是:LangGraph。它的图模型天然适合描述复杂业务流程,有完善的checkpoint机制(流程可以暂停、恢复、回滚),而且跟LangChain生态无缝集成。下面我就用LangGraph来搭我们的示例系统。
五、实战:三智能体协作处理电商订单
现在进入实战环节。我们要搭一个三Agent系统来处理电商订单:
- 订单分析Agent:解析用户订单,提取关键信息(SKU、数量、收货地址等)
- 库存查询Agent:通过MCP工具查询库存,判断是否有货
- 订单执行Agent:根据分析结果和库存情况,执行下单、生成发货单或通知缺货
整体架构
MCP工具层
结构化订单数据
库存状态
缺货
发货单/缺货通知
用户订单请求
订单分析Agent
GPT-4o
库存查询Agent
Gemma 4 + MCP
订单执行Agent
Claude
输出结果
数据库MCP Server
通知MCP Server
第一步:定义Agent节点
我们用LangGraph的StateGraph来定义工作流。首先定义一个共享状态类,三个Agent通过这个状态传递信息。
python
# workflow.py - LangGraph 多智能体工作流
from typing import TypedDict, Annotated, Literal
from langgraph.graph import StateGraph, END
from langgraph.graph.message import add_messages
import json
# 定义共享状态------三个 Agent 通过这个状态传递信息
class OrderState(TypedDict):
messages: Annotated[list, add_messages] # 对话历史
raw_order: str # 原始订单文本
parsed_order: dict # 解析后的结构化订单
stock_status: dict # 库存查询结果
result: str # 最终处理结果
retry_count: int # 重试次数
def order_analyst(state: OrderState) -> dict:
"""订单分析 Agent:解析自然语言订单,提取结构化信息"""
from openai import OpenAI
client = OpenAI()
prompt = f"""你是一个订单分析专家。请从以下用户消息中提取订单信息,
返回JSON格式,包含字段:sku, quantity, address, customer_name。
如果信息不完整,在missing_fields中列出缺失项。
用户消息:{state['raw_order']}"""
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": prompt}],
response_format={"type": "json_object"}
)
parsed = json.loads(response.choices[0].message.content)
return {"parsed_order": parsed}
这里定义了一个OrderState作为三个Agent之间的共享数据结构。order_analyst函数是第一个Agent节点,它调用GPT-4o将用户的自然语言订单解析为结构化JSON。add_messages是LangGraph提供的reducer函数,用于自动合并多个Agent产生的消息------这对于保持对话上下文的连贯性至关重要。
第二步:库存查询和条件路由
库存查询Agent通过MCP工具获取实时数据。路由函数根据库存状态决定下一步走哪个分支。
python
def inventory_checker(state: OrderState) -> dict:
"""库存查询 Agent:通过 MCP 工具查询库存"""
import aiohttp
order = state["parsed_order"]
sku = order.get("sku", "")
# 调用库存 MCP Server 的 query_inventory 工具
# 实际生产中通过 MCP SDK 的 Client 连接,这里简化为 HTTP 调用
async with aiohttp.ClientSession() as session:
payload = {
"tool": "query_inventory",
"arguments": {"sku": sku}
}
async with session.post(
"http://localhost:8080/mcp/call",
json=payload
) as resp:
result = await resp.json()
return {"stock_status": result}
def route_by_stock(state: OrderState) -> Literal["execute", "notify_shortage"]:
"""根据库存状态路由:有货执行下单,无货发送缺货通知"""
stock_info = state.get("stock_status", {})
available = stock_info.get("stock", 0)
needed = state["parsed_order"].get("quantity", 1)
if available >= needed:
return "execute"
else:
return "notify_shortage"
def order_executor(state: OrderState) -> dict:
"""订单执行 Agent:生成发货单或缺货通知"""
import anthropic
client = anthropic.Anthropic()
prompt = f"""根据以下信息生成处理结果:
订单:{json.dumps(state['parsed_order'], ensure_ascii=False)}
库存:{json.dumps(state['stock_status'], ensure_ascii=False)}
请生成标准的发货确认单或补货通知。"""
message = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
messages=[{"role": "user", "content": prompt}]
)
return {"result": message.content[0].text}
inventory_checker通过MCP Server查询库存数据。route_by_stock是LangGraph中的条件边(conditional edge)------它根据库存状态动态决定下一步走"下单执行"还是"缺货通知"分支。这种条件路由是LangGraph最强大的特性之一,让你能用图模型描述复杂的业务逻辑分支。order_executor根据前两个Agent的结果生成最终的处理单据,这里用Claude来完成文本生成。
第三步:组装工作流图
有了节点和路由函数,现在把它们组装成一张完整的工作流图。
python
def build_workflow() -> StateGraph:
"""组装三智能体工作流"""
graph = StateGraph(OrderState)
# 添加节点
graph.add_node("analyze", order_analyst)
graph.add_node("check_stock", inventory_checker)
graph.add_node("execute", order_executor)
graph.add_node("notify_shortage", order_executor) # 复用执行节点
# 定义边(执行顺序)
graph.set_entry_point("analyze")
graph.add_edge("analyze", "check_stock")
graph.add_conditional_edges(
"check_stock", # 从库存检查节点出发
route_by_stock, # 根据库存状态路由
{
"execute": "execute", # 有货 → 下单
"notify_shortage": "notify_shortage" # 无货 → 通知
}
)
graph.add_edge("execute", END)
graph.add_edge("notify_shortage", END)
return graph.compile()
# 运行工作流
if __name__ == "__main__":
workflow = build_workflow()
result = workflow.invoke({
"raw_order": "我要买两把机械键盘Pro,送到北京海淀区中关村大街1号,收件人张三",
"retry_count": 0
})
print(result["result"])
这段代码是整个系统的核心编排层。StateGraph是LangGraph的工作流引擎,add_node定义节点,add_edge定义固定边,add_conditional_edges定义条件边。set_entry_point指定入口节点。compile()把所有这些编译成一个可执行的工作流。调用invoke()时传入初始状态,LangGraph会自动按照图的结构执行每个节点,通过状态对象传递中间结果。这种"声明式"的工作流定义方式比"命令式"的if-else嵌套清晰得多,特别是在流程越来越复杂的时候。
完整的执行流程
把上面的代码跑起来,整个流程是这样的:
订单执行Agent MCP Server 库存查询Agent 订单分析Agent LangGraph 工作流 用户 订单执行Agent MCP Server 库存查询Agent 订单分析Agent LangGraph 工作流 用户 alt [库存充足] [库存不足] 提交订单文本 解析订单 {sku: "SKU-001", qty: 2, address: "北京..."} 查询库存 MCP调用 query_inventory {stock: 128, price: 699.0} 库存充足 执行下单 发货确认单 订单已确认 生成缺货通知 补货提醒 缺货通知
这个时序图展示了完整的交互流程。注意几个关键设计:每个Agent只处理自己负责的那一步;Agent之间不直接通信,而是通过LangGraph的状态对象间接传递数据;MCP工具调用是独立的,可以随时替换底层实现而不影响Agent逻辑。
六、用A2A让不同框架的Agent互相发现
上面的例子中,三个Agent都在同一个LangGraph工作流内运行。但真实的企业场景更可能是这样的:库存查询Agent是仓储团队用Google ADK开发的,订单执行Agent是客服团队用AutoGen开发的。它们部署在不同的服务器上,用不同的框架实现。这时候就需要A2A协议来打通。
发布Agent Card
让你的Agent对外可见,第一步是发布Agent Card。这是A2A协议规定的标准做法------在Agent的HTTP服务根路径下托管/.well-known/agent.json文件。
python
# a2a_agent_server.py - 将库存Agent发布为A2A兼容服务
from fastapi import FastAPI
from fastapi.responses import JSONResponse
import httpx
app = FastAPI()
AGENT_CARD = {
"name": "inventory-agent",
"description": "库存管理智能体,支持查询、预警、补货建议",
"url": "https://inventory.example.com",
"version": "1.2.0",
"capabilities": {"streaming": True, "pushNotifications": True},
"skills": [
{
"id": "check-stock",
"name": "库存查询",
"description": "根据SKU查询实时库存",
"inputSchema": {
"type": "object",
"properties": {
"sku": {"type": "string"},
"warehouse": {"type": "string"}
}
}
},
{
"id": "restock-alert",
"name": "补货预警",
"description": "扫描低于安全阈值的SKU",
"inputSchema": {
"type": "object",
"properties": {"threshold": {"type": "integer"}}
}
}
],
"authentication": {"type": "bearer"}
}
@app.get("/.well-known/agent.json")
async def get_agent_card():
"""A2A 标准端点:返回 Agent Card"""
return JSONResponse(content=AGENT_CARD)
@app.post("/tasks/send")
async def handle_task(task_request: dict):
"""A2A 标准端点:处理来自其他 Agent 的任务请求"""
skill_id = task_request.get("skill", "")
params = task_request.get("parameters", {})
if skill_id == "check-stock":
# 调用内部的 MCP 工具查询库存
sku = params.get("sku", "")
stock_info = await query_stock_via_mcp(sku)
return {"status": "completed", "result": stock_info}
elif skill_id == "restock-alert":
threshold = params.get("threshold", 50)
alerts = await generate_restock_alerts(threshold)
return {"status": "completed", "result": alerts}
else:
return {"status": "error", "message": f"未知技能: {skill_id}"}
async def query_stock_via_mcp(sku: str) -> dict:
"""内部调用 MCP Server 查库存"""
async with httpx.AsyncClient() as client:
resp = await client.post(
"http://localhost:8080/mcp/call",
json={"tool": "query_inventory", "arguments": {"sku": sku}}
)
return resp.json()
async def generate_restock_alerts(threshold: int) -> dict:
"""扫描低于阈值的SKU"""
# 实际实现中查询数据库
return {"low_stock_items": [], "threshold": threshold}
这段代码用FastAPI搭建了一个A2A兼容的Agent服务。核心是两个端点:/.well-known/agent.json返回Agent Card供其他Agent发现能力;/tasks/send接收其他Agent发来的任务请求。注意一个设计细节:内部仍然通过MCP协议调用工具------这就是MCP和A2A的互补关系。A2A负责Agent间的发现和通信,MCP负责Agent与工具的连接。
从另一个Agent发起A2A调用
现在来看另一端------订单执行Agent怎么找到库存Agent并调用它。
python
# a2a_client.py - 通过 A2A 协议发现并调用远程 Agent
import httpx
async def discover_agent(agent_url: str) -> dict:
"""发现远程 Agent,获取其 Agent Card"""
async with httpx.AsyncClient() as client:
resp = await client.get(
f"{agent_url}/.well-known/agent.json",
timeout=10.0
)
return resp.json()
async def send_task_to_agent(
agent_url: str,
skill_id: str,
parameters: dict
) -> dict:
"""向远程 Agent 发送任务请求"""
async with httpx.AsyncClient() as client:
resp = await client.post(
f"{agent_url}/tasks/send",
json={
"skill": skill_id,
"parameters": parameters
},
headers={"Authorization": "Bearer <your-token>"},
timeout=30.0
)
return resp.json()
# 使用示例
async def main():
# 第一步:发现库存Agent
agent_card = await discover_agent("https://inventory.example.com")
print(f"发现Agent: {agent_card['name']}")
print(f"可用技能: {[s['name'] for s in agent_card['skills']]}")
# 第二步:调用库存查询技能
result = await send_task_to_agent(
"https://inventory.example.com",
"check-stock",
{"sku": "SKU-001", "warehouse": "北京"}
)
print(f"查询结果: {result}")
整个调用流程分为两步:先通过/.well-known/agent.json获取远程Agent的能力描述,然后根据skills中的inputSchema构造参数,通过/tasks/send端点发起任务。这种"先发现、后调用"的模式和微服务架构中的服务发现很像,但A2A更侧重于描述Agent的"能力"而不是"接口"------Agent Card中的skills描述是给LLM看的,模型根据自然语言描述来决定什么时候调用哪个skill。
七、踩过的几个坑
纸上得来终觉浅。真正动手搭多智能体系统的时候,有几个问题会反复出现,提前说一下。
第一,状态管理比你想的复杂。 三个Agent通过共享状态传递信息,听起来很优雅。但实际业务中,状态结构会越来越复杂------有的字段是必需的,有的是可选的;有的字段在某个分支才有意义;中间结果太多会让上下文窗口溢出。我的建议是:状态类要勤重构,定期清理不再需要的中间字段。LangGraph支持checkpoint机制,每一步的状态都会被持久化,这对调试很有帮助,但也意味着状态设计要谨慎。
第二,MCP工具的描述质量直接决定Agent的决策准确率。 这个坑我踩得很深。一开始我的query_inventory工具的description只写了一句"查询库存",结果模型经常在不该调用的时候调用它,或者传错参数。后来把description改成"根据SKU编号查询指定产品的实时库存数量、仓库位置和预计到货时间,适用于下单前确认是否有货的场景",准确率从60%提到了95%以上。花时间写好工具描述,这件事的投资回报率极高。
第三,多Agent的错误处理要分层。 单个Agent内部的错误(比如LLM调用超时)和Agent间协作的错误(比如下游Agent返回了非预期格式)处理方式完全不同。前者可以通过重试解决,后者需要回退到上一个checkpoint重新路由。LangGraph的interrupt机制在这方面做得不错,允许你在任意节点暂停执行、修改状态、然后继续。
第四,Agent数量不是越多越好。 我见过有人给每个小功能都建一个Agent,结果一个订单流程有七八个Agent在跑,延迟高得离谱,调试也困难。三个Agent是大多数业务流程的甜区------再多了就要考虑合并职责。
第五,成本控制。 每个Agent都要调LLM,三个Agent一次流程就是三次API调用。如果用GPT-4o或Claude,单个订单处理成本可能在0.05-0.15美元。对于高并发场景,考虑把简单任务(比如库存查询的NLU解析)换成本地部署的小模型(比如Gemma 4的E4B版本,可以在树莓派上跑),把贵的模型留给真正需要推理的环节。
八、接下来往哪走
多智能体系统在2026年还处于"早期大众化"阶段------技术栈基本成形,协议标准已经确定,但工程实践和最佳实践还在快速演化。
如果你准备开始做,我的建议分三步走:
第一步:单Agent + MCP。 先让一个Agent通过MCP连接一两个工具,跑通一个简单场景。理解MCP的Host/Client/Server架构,搞清楚工具定义和调用流程。Anthropic官方的MCP Python SDK(GitHub)和快速入门教程是最好的起点。
第二步:LangGraph多Agent工作流。 在单Agent基础上引入LangGraph,把流程拆成两三个Agent节点,用条件边控制路由。感受一下声明式工作流和命令式代码的区别。LangGraph官方文档有丰富的示例。
第三步:接入A2A实现跨框架协作。 当你的Agent需要和其他团队、其他框架的Agent协作时,引入A2A协议。Google的A2A Codelab教程是一个很好的实战起点。
三个值得思考的问题:
- 当Agent数量从3个扩展到30个,当前的图模型编排方式是否还能hold住?是否需要引入层级化的Agent管理?
- MCP和A2A目前都没有内置的计费和审计机制,企业级部署中怎么追踪每个Agent的资源消耗和操作记录?
- 当多个Agent产生矛盾的结果(比如两个分析Agent给出相反的建议),冲突解决的策略应该由Agent自己决定还是由人工介入?
参考链接:
- Anthropic MCP 官方文档:https://modelcontextprotocol.io
- MCP Python SDK:https://github.com/modelcontextprotocol/python-sdk
- Google A2A 协议官方公告:https://developers.googleblog.com/en/a2a-a-new-era-of-agent-interoperability/
- A2A 协议规范:https://a2a-protocol.org/latest/specification/
- A2A 开源仓库:https://github.com/a2aproject/A2A
- Google Gemma 4 模型文档:https://ai.google.dev/gemma/docs/core?hl=zh-cn
- LangGraph 官方文档:https://langchain-ai.github.io/langgraph/
- Gartner 2026年十大战略技术趋势:https://www.gartner.com/en/articles/top-technology-trends-2026
- Google A2A Codelab 实战教程:https://codelabs.developers.google.com/intro-a2a-purchasing-concierge?hl=zh-cn