当AI学会分工合作:用MCP和A2A协议搭一套多智能体系统,跑了跑真实业务流程

当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 Google
发布时间 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系统来处理电商订单:

  1. 订单分析Agent:解析用户订单,提取关键信息(SKU、数量、收货地址等)
  2. 库存查询Agent:通过MCP工具查询库存,判断是否有货
  3. 订单执行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教程是一个很好的实战起点。

三个值得思考的问题:

  1. 当Agent数量从3个扩展到30个,当前的图模型编排方式是否还能hold住?是否需要引入层级化的Agent管理?
  2. MCP和A2A目前都没有内置的计费和审计机制,企业级部署中怎么追踪每个Agent的资源消耗和操作记录?
  3. 当多个Agent产生矛盾的结果(比如两个分析Agent给出相反的建议),冲突解决的策略应该由Agent自己决定还是由人工介入?

参考链接:

相关推荐
HIT_Weston10 小时前
45、【Agent】【OpenCode】本地代理分析(请求&接收回调)
人工智能·agent·opencode
逻辑君10 小时前
认知神经科学研究报告【20260010】
人工智能·深度学习·神经网络·机器学习
星河耀银海10 小时前
远控体验分享:安全与实用性参考
人工智能·安全·微服务
企业架构师老王11 小时前
2026企业架构演进:科普Agent(龙虾)如何从“极客玩具”走向实在Agent规模化落地?
人工智能·ai·架构
GreenTea11 小时前
一文搞懂Harness Engineering与Meta-Harness
前端·人工智能·后端
鬼先生_sir11 小时前
Spring AI Alibaba 1.1.2.2 完整知识点库
人工智能·ai·agent·源码解析·springai
深念Y11 小时前
豆包AI能力集成方案:基于会话管理的API网关设计
人工智能
龙文浩_11 小时前
Attention Mechanism: From Theory to Code
人工智能·深度学习·神经网络·学习·自然语言处理
ulimate_11 小时前
八卡算力、三个Baseline算法(WALLOSS、pi0、DreamZero)
人工智能