#001

AI Agent 架构演进:从单 Agent 到多 Agent 协作

AI Agent架构多 AgentTool Calling

如果你在 2024 年跟人聊 AI Agent,话题多半是「怎么让 LLM 调用工具」。到了 2026 年,话题变成了「怎么让一群 Agent 协同工作」。这中间的演进不是简单的数量叠加,而是一整套架构范式的转变。

单 Agent:一切从 ReAct 开始

最原始的 Agent 不过是一个循环:

# 单 Agent 核心循环(ReAct 模式)
system_prompt = "你是一个能调用工具的助手,每一步先思考再行动。"

messages = [{"role": "system", "content": system_prompt}]
messages.append({"role": "user", "content": "帮我分析这份财报的现金流状况"})

while True:
    response = llm.chat(
        messages=messages,
        tools=[read_file, search_web, run_python, write_file],
    )

    if response.content:
        # 模型选择直接回复 → 循环结束
        print(f"最终回复: {response.content}")
        break

    if response.tool_calls:
        # 模型选择调用工具 → 执行后把结果塞回上下文
        for call in response.tool_calls:
            result = execute(call.function.name, call.function.arguments)
            messages.append({
                "role": "tool",
                "tool_call_id": call.id,
                "content": result,
            })
        continue  # 继续下一轮推理

这个循环看起来简单,但它在相当长的时期内支撑了绝大多数 AI 应用。GPT-4 刚出来的时候,一个 ReAct Agent 配合 5-6 个工具就能解决很多实际问题。

单 Agent 的三重天花板

但当任务变复杂时,三个问题会同时出现:

上下文窗口压力:每轮工具调用的结果都追加到 messages 数组,100 轮对话意味着上下文里塞满了中间结果。这不是 token 成本的问题——即使 128K 窗口能装下,模型在长上下文中对关键信息的注意力也会显著衰退。

工具选择冲突:当你给一个 Agent 30 个工具时,它选择正确工具的概率急剧下降。这跟人一样——工具箱越大,越容易拿错扳手。

单点故障:Agent 说错一句话、选错一个工具、解析错一个返回值,整条链路就断了,没有回退机制。

多 Agent 协作:分工的艺术

多 Agent 系统的核心思想是化整为零——把一个大任务拆成多个小任务,每个小任务交给专门的 Agent。

四种协作模式

┌─────────────────────────────────────────────────────────┐
│  顺序流水线          A → B → C → 输出                    │
│  适合:多步骤线性任务(如:爬取→清洗→分析→报告)          │
│                                                         │
│  层次委托            调度者                               │
│                    ╱    ╲                               │
│                   A      B                              │
│                 ╱  ╲                                     │
│                C    D                                    │
│  适合:复杂任务需要分解(如:大型代码重构)                │
│                                                         │
│  并行独立            A ─┐                                │
│                      B ─┼─ 汇总                          │
│                      C ─┘                                │
│  适合:互不依赖的子任务(如:同时研究三个技术方案)          │
│                                                         │
│  辩论式             A ←→ B ←→ C                          │
│                      ↓                                   │
│                    共识/裁决                              │
│  适合:需要多角度验证的任务(如:代码审查、风险评估)       │
└─────────────────────────────────────────────────────────┘

实践:用 Python 实现层次委托

# 调度者(Orchestrator)的核心逻辑
class Orchestrator:
    def __init__(self, llm):
        self.llm = llm
        self.workers: dict[str, Worker] = {}

    async def decompose_and_dispatch(self, task: str) -> str:
        """分析任务 → 拆分子任务 → 分配给 Worker → 汇总结果"""

        # 第一步:用 LLM 分析任务并生成分解方案
        plan = await self.llm.chat(f"""
        你需要完成以下任务,请先分析并拆分为子任务:

        任务:{task}

        对于每个子任务,说明:
        - 需要什么工具
        - 预期产出是什么
        - 是否依赖其他子任务

        以 JSON 格式返回。
        """)

        sub_tasks = json.loads(plan)

        # 第二步:按依赖关系调度执行
        results = {}
        for sub in topological_sort(sub_tasks):
            # 为每个子任务创建独立的上下文
            worker = Worker(
                llm=self.llm,
                tools=sub["tools"],
                context=f"你负责: {sub['description']}",
            )

            # 注入上游结果作为上下文
            upstream = [results[dep] for dep in sub.get("depends_on", [])]

            result = await worker.run(
                task=sub["description"],
                upstream_results=upstream,
            )
            results[sub["id"]] = result

        # 第三步:汇总所有结果
        summary = await self.llm.chat(f"""
        以下是各子任务的执行结果,请整合为最终输出:

        {json.dumps(results, indent=2)}
        """)

        return summary

并行模式的实际价值

并行独立模式最容易落地,也最值得优先尝试:

# 同时启动多个不相关的 AI 咨询
tasks = [
    "研究 React 19 的 Server Components 对 SSR 性能的影响",
    "研究 Bun 2.0 在生产环境的稳定性",
    "研究 Vercel AI SDK v4 的新特性",
]

# 每个任务在独立上下文中运行,互不干扰
results = await asyncio.gather(*[
    research_agent.run(task) for task in tasks
])

# 汇总成一份技术选型报告
report = await writer_agent.run(
    f"基于以下调研结果,写一份技术选型建议:\n{results}"
)

三条铁律

1. 上下文隔离 > 上下文共享

子 Agent 之间不要共享同一个 messages 数组。每个 Worker 只知道自己需要知道的。信息跨 Agent 传递时,应该经过结构化提炼而非原样转发:

# ❌ 错误:直接把上游 Agent 的原始输出扔给下游
downstream_agent.run(context=f"上游结果: {upstream_raw_output}")

# ✅ 正确:提炼为结构化摘要
summary = summarizer_agent.run(f"提炼以下内容的关键发现: {upstream_raw_output}")
downstream_agent.run(context={
    "上游发现": summary,
    "原始结果引用": upstream.result_id,  # 需要溯源时再查
})

2. 失败隔离 > 全局重试

单 Agent 模式下,一次工具调用失败就意味着整轮对话报废。多 Agent 系统中,一个子任务失败不应该影响其他子任务:

results = {}
for sub in sub_tasks:
    try:
        results[sub["id"]] = await worker.run(sub, timeout=120)
    except WorkerTimeout:
        results[sub["id"]] = {"status": "timeout", "partial": None}
        # 记录失败,继续执行其他子任务
    except WorkerError as e:
        results[sub["id"]] = {"status": "error", "reason": str(e)}
        # 如果有回退策略,这里触发

3. 最小化多 Agent 使用

不要为了多 Agent 而多 Agent。判断标准很简单:

这个任务能不能被拆成 3 个以上互不依赖、可以并行执行的子任务?

能 → 用多 Agent。不能 → 老老实实单 Agent。每多一个 Agent,就多一份通信开销、多一个潜在故障点。

什么时候不建议用多 Agent

场景原因
简单问答单 Agent 完全够用,加 Agent 只会增加延迟
强顺序依赖的任务每个步骤都等上一步结果,多 Agent 没有加速效果
模型能力不足如果单 Agent 都做不好,多 Agent 不会变魔法
调试困难多 Agent 的调用链路复杂,排查问题需要更多基础设施

总结

多 Agent 协作不是万能药,但它确实解决了一个真实问题:单个 LLM 的注意力是有限的。当你需要同时处理大量信息、协调多个工具、或者从多个角度验证输出时,多 Agent 比单 Agent 更优雅。

三句话记住这篇文章:

  1. 单 Agent 是基础,ReAct 循环够应付 70% 的场景
  2. 并行独立模式是最值得优先尝试的多 Agent 模式
  3. 不是任务越复杂越需要多 Agent,而是任务越能被拆解越需要

下一期,我会深入分析 Hermes Agent 在多 Agent 协作中的实际表现——包括它的 delegate_task、kanban 调度、以及 context_from 链式调用的真实体验。

返回文章列表
AI Agent架构多 AgentTool Calling

评论区即将上线