AutoGen PSE 架构解析:用 Planner/Specialist/Evaluator 模式构建可靠的多智能体协作系统

作者:

🇬🇧 English

引言:多智能体协作的困境

2024 年以来,以 AutoGen、LangGraph、CrewAI 为代表的多智能体框架层出不穷。它们让开发者能够编排多个 AI Agent 协同工作,但实际落地时往往会遇到三个核心问题:

  1. Token 爆炸:多轮对话中,上下文不断累积,每次重试都在历史消息上追加新的内容,导致单次请求轻松突破数万甚至数十万 Token,成本随之失控。
  2. 角色混沌:Agent 之间的职责边界模糊,Plan 和 Execute 混在一起,Evaluator 既做评审又给建议,最终谁也说不清问题出在哪。
  3. 不可审计:Agent 的决策过程像一个黑盒——它为什么 PASS?为什么 FAIL?用了多少 Token?花了多少钱?这些信息在大多数框架里都缺失。

这些问题促使我开发了 autogen-pse,一个基于微软 AutoGen 的 Planner-Specialist-Evaluator(PSE)三角色 Agent 框架。本文将从架构设计的角度,深入解析它的核心思想和实现细节。

项目地址:https://github.com/erishen/autogen-pse

一、PSE 三角色模型:为什么是这三个角色?

PSE 模式的灵感来自软件工程中的角色分工:

  • Planner(规划者) → 相当于 Tech Lead:拆解需求、制定计划、分配任务、做交付决策。不做具体执行。
  • Specialist(执行者) → 相当于 Developer:负责编写具体的交付物。只执行被分配的任务。
  • Evaluator(评审者) → 相当于 Code Reviewer:独立验证交付物质量,输出 PASS/PARTIAL/FAIL 判决。不给建议,不替 Specialist 改代码。

角色约束

每个角色都有明确的「能做什么」和「不能做什么」:

角色 职责 限制
Planner 分析需求、拆解任务、分配执行、做交付决策 不写代码、不做计算
Specialist 执行具体任务、撰写交付物 只做被分配的事、完成后汇报
Evaluator 独立验证交付物、输出判决 不信任 Planner、不给建议、只输出 PASS/PARTIAL/FAIL

这种严格的分工带来了几个好处:

  • 职责清晰:任何失败都可以追溯到具体环节。是 Plan 错了?Execute 有 Bug?还是 Evaluation 标准有问题?
  • 减少幻觉:Evaluator 不参与执行,它只做验证,视角更纯粹,更容易发现问题。
  • 可审计:每一轮的 Plan→Execute→Evaluate 都被完整记录。

二、架构总览

                     用户入口
                 CLI / Makefile / Web
                         │
                         ▼
              ┌──────────────────────┐
              │    Orchestrator      │
              │  ┌────────────────┐  │
              │  │  循环控制引擎    │  │
              │  │  step_buffer    │  │
              │  │  Trace 记录     │  │
              │  │  Token 统计     │  │
              │  └────────────────┘  │
              └──────────────────────┘
                         │
                         ▼
           ┌─────────────────────────┐
           │   RoundRobinGroupChat   │
           │                         │
           │  Planner → Specialist   │
           │      → Evaluator        │
           │      → ToolAgent        │
           └─────────────────────────┘
                         │
              ┌──────────┼──────────┐
              ▼          ▼          ▼
          Planner    Specialist  Evaluator
          read_file  read_file   read_file
          bash       (只读)      bash
                                 pytest
                                 ruff
                         │
                    ToolAgent
                    write_file
                    read_file
                    bash
                    pytest
                    ruff

为什么需要第四个 Agent——ToolAgent?

Planner、Specialist、Evaluator 都不是直接调用工具的。它们通过 DSML(Domain-Specific Markup Language)发送工具调用请求,由 ToolAgent 统一执行。

Planner: "我需要创建一个文件,内容如下:<tool_calls>..."
                                                            ↓
ToolAgent 解析 XML,执行 write_file,返回结果

这种设计遵循了 最小权限原则

  • Planner 有 read_file + bash(可以读文件、执行命令,但不能写)
  • Specialist 只有 read_file(只能读,不能写也不能执行命令)
  • Evaluator 有 read_file + bash + pytest + ruff(可以验证,但不能写)
  • ToolAgent 有全部工具,但只被动执行,不主动做决策

三、循环控制与 step_buffer:解决 Token 爆炸的关键

这是 autogen-pse 最核心的设计。每个任务由多个「Plan → Execute → Evaluate」循环组成:

循环开始
  ↓
Planner 制定计划
  ↓
Specialist 执行并产出交付物
  ↓
Evaluator 验证交付物
  ↓
   ├── PASS → 交付完成,退出
   ├── PARTIAL → 修复后重试(最多 3 次)
   ├── FAIL → 重新制定计划(最多 2 次)
   └── BLOCKED / TIMEOUT → 终止

step_buffer 策略

传统的多轮对话中,每次重试都会把完整的历史对话传给 Agent。这就导致:第 1 轮 10K Token,第 2 轮 20K,第 3 轮 30K……呈线性增长。

autogen-pse 的 step_buffer 策略做了两件事:

PARTIAL 重试时:只把 Evaluator 的判决摘要(约 2000 字)作为新的任务提示传入。Planner 只需要知道「上次的问题是什么」,不需要重新阅读整个对话历史。

原始任务: "请撰写一份项目进展周报"
                     ↓ FAIL
新任务: "上一轮被判 FAIL(原因:缺少风险评估部分)。
         请基于原始任务重新制定计划。"

FAIL 重试时:清空整个对话上下文,基于「原始任务 + 失败原因」重新生成计划。这迫使 Planner 产生一个全新的、不被之前错误污染的方案。

原始任务: "请撰写一份项目进展周报"
                     ↓ FAIL × 2
新任务: "连续 PARTIAL 3 次,已达上限。
         请评估是否仍有可交付内容,或宣布 BLOCKED。"

这个策略在实践中效果显著。以一份典型的定期报告生成任务为例,一次完整的 PSE 分析通常包含 3 轮对话,消耗约 200K Prompt Token + 28K Completion Token,费用约 ¥0.65。如果没有 step_buffer,同样的任务可能轻松突破 500K Token。

循环控制参数

所有参数都可以通过环境变量配置:

MAX_PARTIAL_RETRIES = 3   # PARTIAL 最大重试次数
MAX_FAIL_RETRIES = 2      # FAIL 最大重试次数
TURNS_PER_CYCLE = 20      # 每轮对话最大轮次(防止死循环)

四、工具系统:最小权限设计

autogen-pse 的工具系统体现了安全设计的最佳实践:

# Planner:可以读和执行
create_planner(client, task):
    tools=[read_file, bash]

# Specialist:只读
create_specialist(client, task):
    tools=[read_file]

# Evaluator:可以读、执行和测试
create_evaluator(client, task):
    tools=[read_file, bash, run_pytest, run_ruff]

# ToolAgent:全部权限,但被动执行
create_tool_agent(client):
    tools=[write_file, bash, read_file, run_pytest, run_ruff]

DSML 工具调用协议

Agent 之间不直接调用函数,而是通过 XML 标签嵌入在文本消息中:

<tool_calls>
<invoke name="bash">
<parameter name="command" string="true">python3 script.py</parameter>
</invoke>
</tool_calls>

ToolAgent 解析这些标签并执行,然后将结果返回给对话。这种间接调用有几个好处:

  1. 权限隔离:Agent 只能「请求」工具调用,不能「执行」工具调用
  2. 集中审计:所有工具调用都在 ToolAgent 这里过一道,方便日志记录
  3. 灵活扩展:要添加新工具,只需要在 ToolAgent 的 system prompt 中声明即可

Token 追踪与成本核算

每个 Agent 的 Token 消耗都被精确追踪:

class TokenTracker:
    def feed(self, message):
        if hasattr(message, "models_usage"):
            stats = self.report.agents[source]
            stats.prompt_tokens += usage.prompt_tokens
            stats.completion_tokens += usage.completion_tokens

输出报告示例:

============================
📊 Token 消耗报告
============================
  Planner     | 轮次: 4  | 输入: 48672   | 输出: 2008    | 合计: 50680
  Specialist  | 轮次: 4  | 输入: 56152   | 输出: 13472   | 合计: 69624
  Evaluator   | 轮次: 4  | 输入: 102396  | 输出: 11942   | 合计: 114338
  ToolAgent   | 轮次: 3  | 输入: 3970    | 输出: 263     | 合计: 4233
---------------------------------------------------------------
  总计        | 轮次: 15 | 输入: 211190  | 输出: 27685   | 合计: 238875
---------------------------------------------------------------
  💰 预估费用: ¥0.6438
============================

五、实际应用:结构化报告自动生成

autogen-pse 的一个典型应用是「多源数据的结构化报告自动生成」任务。这个任务采用了「零 LLM 成本预处理 + LLM 深度分析」的两层架构:

第一层:规则引擎(零 LLM 成本)

make summarize

读取结构化的业务数据源(JSON/CSV),执行多类规则检查:

  • 数据完整性检测:缺失或异常的字段
  • 一致性校验:跨源数据之间的冲突
  • 阈值越界检测:关键指标超出预警线
  • 结构性异常:分布比例失衡

同时自动获取关联的外部参考数据。整个过程不使用任何 LLM,0 成本。

第二层:PSE 深度分析(LLM 驱动)

make review

将规则引擎的输出作为输入,交给 PSE 三人组进行深度分析。Planner 制定分析框架,Specialist 逐项撰写,Evaluator 独立验证。

如果配置了 RAG 知识库,还会自动检索相关领域知识文档,注入到分析上下文中。

技术细节:如何从对话中提取最终报告?

一个有趣的问题是:PSE 三人组的最终产出是一段对话历史,我怎么从中提取出完整的报告?

方案不是让 Agent 把报告写到文件里(这样有竞态风险),而是在执行完成后,解析 trace JSON,找到 Specialist 最后一次输出中标记为 ## 最终结论 的章节:

for msg in reversed(trace["cycles"][-1]["messages"]):
    if msg["source"] == "Specialist" and "## 最终结论" in msg["content"]:
        report = extract_under_heading(msg["content"], "## 最终结论")

这种「事后提取」的方式比「即时写入」更可靠,不会受到对话顺序和时序问题的影响。

六、Web Dashboard

除了 CLI 和 Makefile,autogen-pse 还提供了一个完整的 Web Dashboard:

技术栈

  • FastAPI + Server-Sent Events:SSE 让用户能实时看到 LLM 的输出流
  • Vite + React + Chart.js:前端显示资产趋势图和执行历史
  • Docker 多阶段构建:Node 构建前端 + Python 运行后端

核心功能

  1. 一键执行:点按钮即可运行任务,实时日志输出
  2. 资产趋势图:Chart.js 展示总资产随时间的变化曲线
  3. 执行历史:最近 10 次 trace 的可视化列表,颜色标识判决结果
  4. Trace 详情:点击展开每一轮的完整对话,支持按 Agent 筛选 Token 消耗

七、从开发到部署的完整体验

本地开发

cp .env.example .env   # 配置 API Key
uv sync                 # 安装 Python 依赖
make dev                # 启动前端 Dev Server + API Server
make test               # 运行 31 个单元测试
make lint               # ruff 代码检查

Docker 部署

# 多阶段构建
FROM node:18 AS frontend      # 构建 React 前端
FROM python:3.12 AS backend   # 运行 FastAPI 后端
COPY --from=frontend /app/web/dist /app/web/dist

添加新任务

三步即可注册一个新任务:

mkdir -p tasks/my-task/prompts
# 1. 编写三个 Agent 的 system prompt
#    tasks/my-task/prompts/planner.md
#    tasks/my-task/prompts/specialist.md
#    tasks/my-task/prompts/evaluator.md
# 2. 编写入口脚本 tasks/my-task/run.py
# 3. 注册到 tasks/_registry.json

八、技术栈一览

层级 技术
Agent 框架 AutoGen RoundRobinGroupChat
LLM 后端 DeepSeek / OpenAI 兼容
Web 后端 FastAPI + SSE
Web 前端 Vite + React + Chart.js
配置管理 pydantic-settings
RAG 知识库 FAISS + Ollama Embeddings
测试 pytest(31 个用例)
项目管理 uv + hatchling
容器化 Docker 多阶段构建

九、设计原则总结

回顾 autogen-pse 的架构设计,有几个值得借鉴的原则:

1. 职责分离

Planner 不做执行,Evaluator 不给建议,Specialist 不写测试。每个角色只做一件事,且只做一件事。这让系统更可控、更可调试。

2. 最小权限

Agent 能调用的工具与其职责严格匹配。尤其是 write_file 只有 ToolAgent 能调用,这从根本上防止了 Agent 意外篡改文件。

3. 状态管理

step_buffer 策略解决了多轮 Agent 对话中的 Token 爆炸问题。关键在于:重试不等同于重新执行——PARTIAL 时保留上下文但压缩,FAIL 时彻底清空重来。

4. 可审计性

每一次执行都被完整记录到 trace JSON 文件中,包括每轮的判决、Token 消耗、耗时。7 天后自动清理旧 trace。

5. 渐进式成本控制

用规则引擎做零成本的预处理,只在必要时才调用 LLM 做深度分析。这种「先规则、后 AI」的思路比纯 LLM 方案更经济、更可靠。

十、未来方向

autogen-pse 是一个面向「可验证、可追溯」的多智能体协作框架,其设计本身与具体业务领域无关。计划中的改进方向包括:

  • 并行执行:支持多个 Specialist 并行工作,提高效率
  • 记忆系统:跨会话的知识持久化,让 Agent 记住历史决策的理由
  • 规则引擎扩展:将规则检查从单一示例任务泛化为通用断言框架
  • 更丰富的 Dashboard:可视化 Agent 的思考过程和决策链路

结语

构建可靠的多智能体系统,关键不在于用什么框架,而在于如何设计角色分工、状态管理和权限控制。autogen-pse 在实践中证明了一点:给每个 Agent 清晰的边界和明确的职责,比给它们更强大的能力重要得多。

如果你对 autogen-pse 感兴趣,欢迎访问 GitHub 项目主页:https://github.com/erishen/autogen-pse,也欢迎提交 Issue 或 PR。


本文首发于 erishen.cn,作者 Erishen Sun。

PSE 系列其他文章

为什么需要第四个 Agent(ToolAgent)?

把”调用工具”从 Specialist 的职责中拆出来,由 ToolAgent 统一承接所有工具调用。这样既强化了最小权限(工具权限集中管控),也让 Specialist 专注于”思考与产出”,职责更清晰。

step_buffer 解决了什么问题?

多智能体多轮对话会导致上下文(token)快速膨胀、成本失控甚至超出模型窗口。step_buffer 通过缓冲与截断策略控制每步注入的上下文规模,在成本与信息完整之间取得平衡。

工具系统的最小权限是怎么设计的?

每个工具显式声明自己能访问的资源,调用需遵循 DSML 工具调用协议,框架对每次调用做权限校验与 Token 追踪,确保工具不会越权且成本可核算。

PSE 如何做成本控制?

采用渐进式成本控制:先用规则引擎做零 LLM 成本的粗筛与格式化,只有确需深度判断的环节才调用 LLM(Evaluator/Specialist),避免为每一步都付出模型推理开销。

PSE 的设计原则有哪些?

职责分离、最小权限、状态管理、可审计性、渐进式成本控制。这五条贯穿三角色模型、工具系统与部署全过程,是框架”可验证、可追溯”的工程基石。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

首页 首页 简历 关于 隐私政策 商店 Web Chat Nsbp

@ 2026 ESN
沪ICP备2024079226号-1   沪公网安备31010502007082号