AutoGen:把多 Agent 应用表达成可编程对话

原始来源

Qingyun Wu 等,2023:AutoGen: Enabling Next-Gen LLM Applications via Multi-Agent Conversation,本页按 arXiv v2 阅读。

本页是原创学习导读,不含原文复刻;论文版权与完整内容以原始来源为准。

学完后你应该能做到什么

读完本篇,你应该能够:

  1. 用角色、内部上下文、能力和回复规则定义一个 Conversable Agent,而不是只给模型起一个角色名。
  2. 区分 Conversation Programming 中的 computation 与 control flow。
  3. 追踪一条消息怎样触发 LLM、工具、代码执行或人类输入,并最终产生下一条消息。
  4. 为双 Agent 与多 Agent 流程明确发言者选择、终止、最大轮次、异常处理和人工接管。
  5. 判断一个任务真的需要多 Agent,还是单 Agent 加工具就足够。

问题背景:复杂应用为什么不能只靠一段提示词

一个“帮我分析股票数据并画图”的任务,表面上只有一句话,实际却包含多种工作:理解要求、写代码、安装或调用依赖、执行程序、读错误、修改代码、检查图表,再决定是否结束。把这些能力都塞进一次模型调用,会遇到几个困难:

  • 模型可以生成代码,却不能天然证明代码真实执行过。
  • 工具执行结果和人类反馈需要回到模型,但谁负责转发并不明确。
  • 不同任务需要不同的人类参与程度和不同的停止条件。
  • 当角色增加时,谁下一位发言、消息发给谁、怎样避免无限对话会成为新的控制问题。

AutoGen 的回答是:把 LLM、人类和工具能力封装成能够收发消息的 Agent,再把整个应用写成这些 Agent 的对话计算与控制流。这里的“对话”不是闲聊,而是一种应用编排接口。

先记住几个术语:

  • Conversable Agent:拥有特定角色、内部上下文和一组能力,并能接收、处理和回复消息的实体。
  • Capability:Agent 处理消息时可以调用的能力,例如 LLM 推理、人类输入、代码执行或函数调用。
  • Conversation:Agent 间的消息序列;消息既传递内容,也推动状态机前进。
  • Auto-reply:收到消息后自动执行 generate_reply 并把结果发回,直到满足终止条件。
  • Conversation Programming:定义 Agent 及其能力,再定义它们的对话计算和控制流。

Agent 不等于一个模型实例

一个 Agent 可以由 LLM、工具、人类或它们的组合支撑;多个 Agent 也可能共享同一种模型。真正的差异来自上下文、能力、权限、回复函数和控制规则,而不是名字。

机制契约:消息驱动的应用状态机

部分AutoGen 论文中的含义设计时需要明确的问题
输入一条来自用户或其他 Agent 的消息消息格式是什么,发送者是谁,是否可信
Agent 状态角色、收发消息形成的内部上下文、能力配置哪些历史可见,哪些工具可用,是否允许人工输入
ComputationAgent 为生成回复所执行的动作调 LLM、执行函数、运行代码还是请求人类
Control flow计算以什么顺序和条件发生下一位发言者是谁,发给谁,何时转入子对话
输出新消息、工具结果、代码结果或人类反馈怎样被下一位 Agent 消费,是否需要结构化
停止条件终止消息、程序化谓词、最大自动回复数、人工终止谁有权结束,结束是否等于任务验收通过
flowchart TD
    M["收到一条消息"] --> R["Agent 更新自己的会话上下文"]
    R --> D{"选择回复能力"}
    D -->|"LLM"| L["推理或生成内容"]
    D -->|"Tool / Code"| T["执行函数或代码"]
    D -->|"Human"| H["请求或接收人类输入"]
    L --> G["generate_reply 形成新消息"]
    T --> G
    H --> G
    G --> E{"满足终止条件?"}
    E -->|"是"| X["结束会话并交付结果"]
    E -->|"否"| C["控制流选择接收者或下一位发言者"]
    C --> M

这套机制把一个隐含的工作流拆成两部分:每个节点“会算什么”,以及消息“下一步流向哪里”。

核心机制一:Conversable Agent 怎样工作

论文中的 Conversable Agent 具备四个关键属性。

1. 角色定义处理责任

角色说明这名 Agent 在会话中负责什么,例如“提出代码方案”“执行代码”“审查结果”。角色影响模型提示和回复行为,但角色名本身没有隔离效果。

2. 内部上下文由消息历史形成

Agent 根据自己发送和接收的消息维护上下文。不同 Agent 可以看到不同历史,因此能形成信息隔离。例如执行器只需要收到代码和运行参数,不必读取规划者的全部推理;评审者可以只收到候选产物、要求和独立证据。

3. 能力可以组合

论文把常见后端能力概括为三类:

  • LLM:理解消息、生成回复、写代码、吸收反馈。
  • Human:在配置的轮次或条件下请求人类输入,人也可以选择跳过。
  • Tools:执行代码或函数调用,把真实结果重新放入对话。

一个 Agent 可以只拥有其中一种,也可以混合使用。论文中的预配置 AssistantAgent 主要由 LLM 支撑;UserProxyAgent 可以代理人类输入,并执行模型建议的代码或函数。这是论文版本的历史抽象,不代表当前 AutoGen 库 API 永远保持相同。

4. 统一消息接口触发回复

Agent 通过 send、receive 和 generate_reply 一类统一接口协作。默认自动回复机制是:收到消息后调用回复逻辑,生成新消息并发回,除非终止条件已经满足。回复函数可以来自 LLM、代码/函数执行、人类输入,也可以由开发者注册自定义逻辑。

因此,一条消息不是静态文本,而像事件循环中的事件:它更新状态、触发计算、产生下一事件。

核心机制二:Conversation Programming 分开“计算”与“控制”

论文把 Conversation Programming 拆成两个概念:

  1. Computation:Agent 为回复当前消息做的动作。它可能调用 LLM、执行代码、调用工具、让人审阅,最后都表现为一条新消息。
  2. Control flow:这些计算发生的次序与条件。它决定消息发给谁、哪位 Agent 下一步行动、何时进入子会话,以及什么时候终止。

控制可以通过三种方式表达:

  • 自然语言控制:例如要求 Agent 完成所有任务后回复 TERMINATE,或规定先提出方案再执行。
  • 编程语言控制:用 Python 谓词判断终止、设置人类输入模式、限制自动回复次数、注册自定义回复函数。
  • 两者之间切换:代码调用带控制指令的 LLM,或由 LLM 提议函数调用,让自然语言决策进入程序化路径。

这种融合提供灵活性,也带来可靠性差异。max_auto_reply 一类代码限制是确定的;要求模型“合适时结束”则可能漏判。安全关键条件应尽可能落到可执行控制上。

双 Agent 案例:写代码和执行代码怎样闭环

考虑任务:“读取本地销售 CSV,计算月度增长率并保存图表。”下面是一条简化但机制完整的对话轨迹。

步骤发送者 → 接收者消息或动作系统状态
1UserProxy → Assistant发送任务、允许读取的文件路径和验收要求建立目标与权限边界
2Assistant → UserProxy生成 Python 代码,请求执行候选代码进入消息,但尚无执行证据
3UserProxy在隔离环境运行代码真实执行发生
4UserProxy → Assistant返回 KeyError: revenue 和实际列名环境反馈进入会话上下文
5Assistant → UserProxy修改列名映射并再次请求执行生成第二版候选代码
6UserProxy执行成功,检查输出文件存在获得运行结果和最小断言
7UserProxy → Assistant返回统计摘要、图表路径和断言结果模型可以基于事实总结,而非假装执行
8Assistant → UserProxy给出最终说明并发送终止标记对话满足终止规则
9UserProxy / 人类核对业务口径后接受或要求修改“会话终止”才映射成“任务验收”

这个模式的价值不在于一定要有两个模型。UserProxy 可以没有 LLM,只负责人工交互和受控执行。分开两者,是为了让“提出代码”和“拥有执行权限”处在不同信任边界。

多 Agent 案例:发言者选择本身就是算法

任务复杂后,可以加入 Engineer、Critic、Executor 与 User Proxy,并由 Manager 管理群聊。论文中的动态群聊管理器执行三个步骤:选择一位发言者、请求其回复、再把回复广播给其他成员。

sequenceDiagram
    participant U as User Proxy
    participant M as Manager
    participant E as Engineer
    participant C as Critic
    participant X as Executor
    U->>M: 任务、限制与验收标准
    M->>E: 选择 Engineer 提出方案
    E-->>M: 代码与假设
    M->>C: 选择 Critic 独立审查
    C-->>M: 风险与修改意见
    M->>E: 回传审查意见
    E-->>M: 修订代码
    M->>X: 请求隔离执行
    X-->>M: 日志、测试和产物
    M->>U: 汇总证据,请求最终验收

Manager 不是装饰。若总是轮流发言,Executor 可能在代码尚未准备好时运行;若模型随意选择发言者,又可能让 Engineer 与 Critic 互相重复。发言策略必须结合当前任务状态,例如 DRAFTED → REVIEWED → EXECUTED → ACCEPTED,而不只看最后一段自然语言。

多 Agent 真正有价值的情况包括:

  • 角色拥有不同工具或权限,例如只有 Executor 可以运行代码。
  • 角色拥有不同信息,例如 Critic 不看生成者的自我辩护,只看需求与产物。
  • 工作可以并行,例如多个检索者查不同数据源。
  • 需要独立的规则检查器,例如棋盘 Agent 验证合法走法。

如果所有角色看到相同上下文、调用相同模型、没有独立工具和验收标准,那么增加角色常常只会复制 token 和错误。

用伪代码表示对话控制

agents = {
    "assistant": AssistantAgent(llm=True, tools=[]),
    "executor": UserProxyAgent(
        human_input="on_demand",
        code_execution="sandbox",
    ),
}
 
message = user_task
sender, receiver = "executor", "assistant"
 
for turn in range(MAX_TURNS):
    receiver_state = update_context(receiver, sender, message)
    reply = agents[receiver].generate_reply(receiver_state)
 
    if violates_policy(reply):
        request_human_review(reply)
        break
    if accepted_result(reply):
        finish(reply)
        break
 
    sender, receiver = receiver, choose_next_agent(reply)
    message = reply
else:
    stop_as_incomplete("maximum conversation length reached")

真实实现还要把异常、超时、重试、幂等性和权限放进控制层。重点是:模型生成回复只是 computation;choose_next_agent、策略门禁和终止判断才是 control flow。

证据该怎么看

论文用数学、编程、问答、运筹、在线决策、娱乐等应用展示框架,并报告部分基准和试点结果。它主要证明 AutoGen 能以统一抽象表达多种会话模式,并在若干应用中取得有用结果;它不是“多 Agent 普遍优于单 Agent”的大规模受控实验。

一个很能说明边界的例子是动态群聊试点:作者在 12 个手工构造的复杂任务上比较双 Agent、使用角色扮演发言选择的四 Agent 群聊,以及使用任务式发言选择的同成员群聊。GPT-4 对应成功数分别为 9、11、8。也就是说,四个 Agent 加上不合适的选择策略,反而低于两个 Agent。样本很小,不能外推为稳定排名,但足以说明编排策略和终止设计比角色数量本身重要。

论文的会话棋盘示例还移除了负责规则验证的 Board Agent;只提示两个玩家“保证走法合法”会产生非法走法并打断游戏。这个消融支持一个工程判断:当规则可执行时,独立验证组件通常比让生成模型自我保证更可靠。

失败模式与调试顺序

失败现象常见根因修复方向
Agent 互相重复、对话不结束终止条件模糊,状态只存在自然语言里增加结构化阶段、最大轮次和程序化终止
Reviewer 总同意生成者上下文、模型和标准没有独立性提供独立证据、不同工具或确定性规则检查
工具结果被误当成模型文本消息没有类型和来源元数据区分 tool_result、human_input、assistant_message
多 Agent 比单 Agent 更差通信开销、上下文复制、发言顺序错误先建立单 Agent 基线,再验证每个新增角色的增益
代码执行造成越权或污染执行 Agent 权限过大、缺少隔离最小权限、沙箱、资源限额和危险操作审批
对话结束但任务未完成TERMINATE 被当成业务验收将终止与外部测试、产物检查、人工验收分开

历史贡献与今天的工程解释

论文的历史贡献是提出并实现 Conversable Agent 与 Conversation Programming:用统一消息接口组合 LLM、人类和工具能力,并用自然语言与代码共同描述静态或动态的多 Agent 对话流程。

今天更稳妥的工程解释是:多 Agent 是一种模块化工作流表达方式,而不是自动提高智能的按钮。应先证明不同角色确实需要不同的上下文、工具、权限、并行分工或独立验证,再承担额外的延迟、成本和失败面。

论文描述的是 2023 年 AutoGen 及其当时的内置 Agent 和示例。后续库的包结构与 API 可能改变;本篇用于掌握机制,不应作为当前版本的复制粘贴手册。

与 MCP 的区别

AutoGen 重点是应用内部的参与者、消息和控制流;MCP 重点是Host 与外部 Server 之间怎样用共同协议暴露资源、提示和工具。AutoGen 回答“谁与谁协作以及下一步轮到谁”,MCP 回答“外部能力如何被发现和调用”。一个 AutoGen Agent 可以使用 MCP Client,但两者不处在同一抽象层。

自测:确认你真的掌握了机制

  1. 用四个字段定义一个 Conversable Agent:角色、上下文、能力和回复规则。为什么只有角色名不够?
  2. 在“写代码—运行—修复”的双 Agent 案例中,哪些步骤属于 computation,哪些属于 control flow?
  3. 为什么 TERMINATE 只能结束会话,不一定证明任务成功?
  4. 四 Agent 群聊在什么条件下可能比双 Agent 更差?
  5. 设计一个必须人工确认的工具调用:确认点应放在哪一条消息与哪一个权限边界之间?

上一篇:Voyager · 下一篇:MCP 发布文章 · 返回 里程碑原典目录