多 Agent 编排与置信度过滤
多 Agent 编排与置信度过滤
学习目标
读完本章后,你将能够:
- 理解 Orchestrator 模式下 Command 如何编排多个专项 Agent
- 设计置信度打分过滤系统减少噪音报告
- 选择并行 vs 顺序执行的适用场景
- 实现只读分析与可写实现的权限分离
核心概念
Orchestrator 编排模式
在 Orchestrator 模式中,一个主 Command 充当编排者,在适当阶段启动专项 Agent。编排者保留写入权限,分析 Agent 仅保留读取权限。
关键设计特征:
| 特征 | 说明 |
|---|---|
| 阶段门控 | 每个关键阶段后等待用户确认,不自动推进 |
| 只读分析 | 分析 Agent 无写入权限,决策由编排者保留 |
| 并行效率 | 多个 Agent 同时启动,减少总等待时间 |
| 结构化输出 | 每个 Agent 定义独立输出模板,便于聚合 |
置信度打分过滤系统
代码审查 Agent 使用定量置信度打分来过滤噪音:
| 分数 | 含义 | 报告? |
|---|---|---|
| 0 | 完全没信心 — 误报或已有问题 | 不报告 |
| 25 | 有些信心 — 可能是问题,可能是风格偏好 | 不报告 |
| 50 | 中等信心 — 真实问题但可能是小毛病 | 不报告 |
| 75 | 高度信心 — 已复核,很可能是真实问题 | 不报告 |
| 100 | 完全确定 — 确定真实,会频繁发生 | 不报告 |
阈值 = 80:仅报告置信度 ≥ 80 的发现。
为什么需要阈值过滤?
自动代码审查的最大问题是噪音过多。没有过滤的审查器会报告数十个低优先级问题(风格偏好、命名建议、已有模式),淹没真正重要的发现。阈值过滤确保只报告高置信度的 Critical 和 Important 级别问题。
分数分组用于报告:
| 分组 | 分数范围 | 报告分类 |
|---|---|---|
| Critical | 91-100 | 严重 bug 或规范违规 |
| Important | 80-89 | 需要关注的中等问题 |
| Ignored | 0-79 | 低于阈值,不报告 |
并行 vs 顺序执行
| 维度 | 并行 | 顺序 |
|---|---|---|
| 速度 | 快(所有 Agent 同时工作) | 慢(逐个完成) |
| 可理解性 | 多个报告同时到达,需要聚合 | 一份报告完成后再看下一份 |
| Token 效率 | 较低(Agent 可能重复读取相同文件) | 较高(前一个 Agent 的结果可被后一个利用) |
| 适用场景 | 全面审查、时间紧迫 | 深入分析、需要链式推理 |
选择指南:
- 需要覆盖多个独立维度(代码质量、测试、错误处理、类型设计)→ 并行
- 后一个分析依赖前一个的结果 → 顺序
- 用户指定
all parallel→ 并行全量审查
模型路由策略
不同 Agent 角色使用不同模型以平衡成本和质量:
| 角色 | 模型 | 理由 |
|---|---|---|
| 深度代码审查 | Opus | 需要理解复杂代码路径和边界条件 |
| 代码简化/重构 | Opus | 需要确保重构后功能不变 |
| 代码探索 | Sonnet | 理解代码结构,不需要深度推理 |
| 架构设计 | Sonnet | 基于已有模式做设计决策 |
| 测试分析 | inherit | 轻量任务,继承调用者模型 |
| 注释分析 | inherit | 轻量任务,继承调用者模型 |
只读分析与可写实现的权限分离
专项分析 Agent 通常不授予写入权限:
# code-explorer Agent 的工具列表tools: Glob, Grep, LS, Read, NotebookRead, WebFetch, TodoWrite, WebSearch, KillShell, BashOutput# 注意:没有 Write, Edit, Bash(写权限)为什么分离?
- 安全性:分析 Agent 不应意外修改代码
- 职责清晰:分析 ≠ 实现,分析 Agent 提供信息,编排者做决策
- 可追溯:所有写入操作由编排者统一执行,变更来源清晰
陷阱与对策
| 陷阱 | 表现 | 对策 |
|---|---|---|
| 并行 Agent 重复读取相同文件 | Token 浪费,成本翻倍 | 编排者预先读取共享文件,注入各 Agent 上下文 |
| 置信度阈值过低 | 噪音过多,用户忽略报告 | 提高阈值至 80+,聚焦关键问题 |
| 置信度阈值过高 | 漏报中等严重问题 | 保留 Important 分组(80-89),不只看 Critical |
| 结构化输出不一致 | 编排者无法正确聚合 | 在 Agent 系统提示中强制输出模板 |
| Agent 描述不够具体 | 不会被正确触发或调用 | 使用 <example> 块教导何时主动调用 |
设计取舍
为什么 Agent 不互相通信?
独立的 Agent 各自保持不同的分析视角。如果 Agent A 的结果影响 Agent B,B 可能被 A 的偏见影响,失去独立发现问题的能力。这在安全审查和 bug 检测中尤其重要——多个独立视角比一个共识视角更有效。
为什么分析 Agent 没有写入权限?
写入权限意味着可以修改代码库。分析阶段的目标是理解问题,而非解决问题。如果分析 Agent 在分析过程中就开始修改代码,可能破坏后续 Agent 需要的分析基线。
为什么需要定量置信度而非定性分级?
定性分级(“高/中/低”)在不同 Agent 之间含义不一致。定量打分(0-100)提供了一个统一的数值基准,使得阈值过滤(≥80 才报告)成为可能。
参考来源
- Claude Code Subagent 文档 — 子代理的创建和隔离
- Claude Code Code Review 文档 — 代码审查的最佳实践
补充:CrewAI 的 Crew 与 Flow 双模式编排
来源:CrewAI(crewAIInc/crewAI)lib/crewai/src/crewai/crew.py、lib/crewai/src/crewai/flow/flow.py,commit 77a6127
CrewAI 提供了两种互补的编排抽象,而非单一的 Orchestrator 模式:
Crew 模式:“谁做什么”
Crew 关注Agent 的角色分工和任务分配。核心元素:
- Agent:role/goal/backstory 三元组定义角色
- Task:description + assigned agent + optional tools
- Process:Sequential(链式)或 Hierarchical(Manager 委派)
Flow 模式:“什么之后做什么”
Flow 关注事件驱动的控制流。核心元素:
@start():入口点,可依赖其他方法@listen(condition):监听完成事件,支持 AND/OR 组合@router(condition):动态路由,返回值决定下一步self.state:线程安全的共享状态(StateProxy+threading.Lock)
两种模式的决策矩阵
| 场景 | 推荐 | 理由 |
|---|---|---|
| 多角色协作完成内容生成 | Crew | 角色分工清晰,任务间数据流线性 |
| 复杂审批流程(批准/拒绝/修改循环) | Flow | 动态分支,条件判断多 |
| 需要人工介入的流水线 | Flow | 内置 @human_feedback 和 self.ask() |
| 需要断点恢复的长流程 | Flow | @persist 装饰器实现方法级快照 |
| 简单的多步数据处理 | Crew | 配置简单,代码量少 |
| 多个独立子流程并行 | Flow | OR 条件天然支持并行触发 |
嵌套使用
Crew 可以嵌入 Flow 方法内部——Crew 继承自 FlowTrackable:
class MyFlow(Flow[MyState]): @start() def research_phase(self): crew = Crew(agents=[researcher], tasks=[research_task]) result = crew.kickoff() self.state.research_result = result return result
@listen("research_phase") def writing_phase(self): # 基于 Flow 状态执行下一步 ...设计取舍:Crew 专注于 Agent 角色的声明式定义,Flow 专注于流程控制的精确编排。两者的选择不是互斥的——实际项目中可以组合使用。
补充:AutoGen 的多 Agent 编排模式家族
来源:AutoGen(microsoft/autogen)python/packages/autogen-agentchat/src/autogen_agentchat/teams/,commit 027ecf0
AutoGen 在 AgentChat 层提供了四种预置的多 Agent 编排模式,覆盖从简单到复杂的不同场景:
RoundRobinGroupChat:轮流发言
最简单的编排模式。参与者按注册顺序依次发言,每轮每个 Agent 发言一次。
适用场景:需要每个 Agent 都参与的确定性流程,如多人轮流审核。
局限:无法动态跳过不需要的 Agent,也无法让某个 Agent 连续发言。
SelectorGroupChat:LLM 选择下一个发言者
使用 LLM 动态选择下一个最合适的发言者。
关键设计:每个 Agent 的 description 字段是 LLM 选择的依据。描述越具体,选择越准确。
适用场景:任务类型不固定,需要灵活路由到不同专长的 Agent。
局限:LLM 选择不稳定可能导致死循环(同一个 Agent 被反复选择)或跳过关键 Agent。
Swarm:Agent 主动 Handoff
每个 Agent 可以通过 Handoff 主动将控制权转移给另一个 Agent。
核心机制:Handoff 是一个特殊的消息类型,包含目标 Agent 名称和转移原因。编排器收到 Handoff 消息后,将控制权转移到目标 Agent。
适用场景:Agent 知道自己什么时候”搞不定”,主动寻求帮助。
局限:需要防止 Handoff 循环(A → B → A),通常通过设置最大轮次限制。
MagenticOneGroupChat:Ledger 编排器
最复杂的编排模式,基于 Planner-Executor-反思循环。
**Ledger(任务日志)**包含三个部分:
- Facts:从任务中提取的已知事实
- Plan:当前执行计划
- Progress:已完成的步骤列表
Stall Detection(停滞检测):如果连续 N 轮没有实质进展,触发计划更新。如果超过最大停滞次数,强制终止并返回当前最佳答案。
适用场景:需要多步推理和规划的复杂任务,如研究、代码生成。
局限:Token 消耗高(Orchestrator 每轮都需要 LLM 调用做评估)。
四种模式的决策矩阵
| 场景 | 推荐模式 | 理由 |
|---|---|---|
| 固定流程,每个角色必须参与 | RoundRobin | 简单、可预测 |
| 任务类型多变,需要灵活路由 | Selector | LLM 动态选择 |
| Agent 自主决定何时求助 | Swarm | 去中心化、灵活 |
| 复杂任务需要规划和反思 | MagenticOne | 结构化思考 |
| 需要图结构对话流 | Selector + DiGraph | 有向图定义对话路径 |
补充:对抗辩论与轮流三方评审模式
来源:TradingAgents(TauricResearch/TradingAgents)tradingagents/graph/setup.py、tradingagents/graph/conditional_logic.py、tradingagents/agents/utils/agent_states.py,commit 61522e1
TradingAgents 在 Orchestrator 并行打分类之外,引入了两种基于辩论的多 Agent 决策模式,用于在不确定性高的场景中平衡不同视角。
对抗辩论模式(Bull vs Bear)
两个 Agent 分别持对立立场,通过交替发言进行结构化辩论,最终由第三个 Agent(Judge)综合裁决。
关键设计要素:
| 要素 | 说明 |
|---|---|
| 角色极化 | Bull 被提示只生成看涨论据,Bear 只生成看跌论据,确保视角覆盖 |
| 回合限制 | max_debate_rounds 控制最大轮数,防止无限循环 |
| 状态分离 | InvestDebateState 独立维护 bull_history、bear_history、judge_decision |
| 条件边路由 | should_continue_debate 检查当前发言者,交替路由到对方;达到回合上限路由到 Research Manager |
| 计数器 | count >= 2 * max_debate_rounds(每轮 2 次发言) |
为什么需要对抗辩论?
单一 Agent 的综合分析容易产生确认偏误——先形成的倾向会影响后续判断。对抗辩论强制系统同时生成支持和反对的证据,再通过第三方裁决综合,降低了单边偏见对最终决策的影响。
陷阱:
- 辩论质量依赖提示词中立场的严格性——如果 Bull/Bear 立场不够鲜明,辩论退化为平庸的综合分析
- 回合数过少时辩论深度不足;过多时 Agent 可能开始重复论点而不产生新信息
- Judge 需要看到完整的辩论历史,上下文窗口需容纳
bull_history + bear_history + reports
轮流三方评审模式(Aggressive → Conservative → Neutral)
三个 Agent 按固定顺序轮流发表风险评估,形成循环,最终由 Portfolio Manager 裁决。
关键设计要素:
| 要素 | 说明 |
|---|---|
| 固定顺序循环 | Aggressive → Conservative → Neutral,每轮 3 次发言 |
| 立场继承 | 每个 Agent 看到前一个 Agent 的发言,可以反驳或补充 |
| 计数器 | count >= 3 * max_risk_discuss_rounds(每轮 3 次发言) |
| 状态分离 | RiskDebateState 维护 aggressive_history、conservative_history、neutral_history、latest_speaker |
| 退出路由 | should_continue_risk_analysis 根据 latest_speaker 路由到下一个,达到上限路由到 Portfolio Manager |
与 Bull/Bear 的对比:
| 维度 | Bull/Bear 对抗辩论 | 三方评审 |
|---|---|---|
| Agent 数 | 2 | 3 |
| 立场关系 | 完全对立 | 梯度分布(激进 → 保守 → 中立) |
| 路由复杂度 | 简单双向交替 | 三向循环 |
| 适用场景 | 二元决策(买 vs 不买) | 多维评估(风险、收益、时机) |
| 偏见风险 | 中等(两个极端视角) | 低(三个视角覆盖全谱) |
设计取舍:
TradingAgents 将辩论限制在”研究团队”和”风控团队”两个阶段,而分析师阶段是顺序执行的。这种混合架构(顺序分析 + 辩论决策)的取舍是:
- 优势:分析师提供独立视角,辩论阶段综合并检验这些视角,避免了每个分析师都参与辩论的 Token 爆炸
- 代价:分析师阶段不辩论,可能导致矛盾的分析结果直接传递到研究团队,依赖 Bull/Bear 在辩论中识别并化解
与 SelectorGroupChat 的对比:
AutoGen 的 SelectorGroupChat 使用 LLM 动态选择下一个发言者,而 TradingAgents 的辩论使用确定性条件边。确定性路由的优势是可预测、不会死循环;代价是缺乏适应性——如果 Bull 的论点已经很充分,系统不会自动跳过 Bear 直接到 Judge。
补充:Warp 的终端内多 Agent 编排(OrchestrationV2)
来源:Warp crates/ai/src/agent/orchestration_config.rs + app/src/ai/agent_sdk/driver.rs,commit 94d29fe
Warp 将多 Agent 编排嵌入终端 UI 的上下文,形成独特的终端内编排模式:
RunAgents 批量工具调用
不同于 Orchestrator 模式(编排者逐轮启动 Agent),Warp 的 RunAgents 工具允许在一次工具调用中批量启动多个子 Agent,共享 run-wide 配置:
// 伪代码:批量 Agent 启动请求struct RunAgentsRequest { summary: String, // 任务摘要 base_prompt: String, // 所有子 Agent 共享的基础 prompt model_id: String, // 统一的模型 ID harness_type: String, // 统一的 Agent CLI(oz/claude/codex/gemini) execution_mode: RunAgentsExecutionMode, // Local 或 Remote agent_run_configs: Vec<RunAgentsAgentRunConfig>, // 每个子 Agent 的独立配置 plan_id: String, // 关联的执行计划 ID}关键设计:
- 配置继承:子 Agent 的请求 =
base_prompt + "\n\n" + per_agent_prompt,共享模型和 harness 类型,但每个 Agent 有独立的名称和提示词 - 用户确认机制:
OrchestrationConfigStatus跟踪用户是否已批准当前配置。已批准时自动启动(auto-launch),未批准时显示确认卡片 - 双执行模式:
Local在本地终端运行,Remote在云端环境运行(带environment_id和worker_host) - SSE 事件流驱动:通过
AgentEventDriver监听所有子 Agent 的事件,使用since_sequence游标实现断线续传
Pill Bar UI:可视化 Agent 层级
Warp 在终端 UI 顶部渲染编排 Pill Bar,直观展示父 Agent 与所有子 Agent 的关系,点击可切换到任意子 Agent 的对话视图。这与通用的多 Agent 框架不同——它将编排状态直接映射到终端的视觉层。
与通用编排模式的对比:
| 维度 | 通用 Orchestrator | Warp 终端编排 |
|---|---|---|
| 触发方式 | 编排者代码决定何时启动 | 用户通过终端 UI 或 LLM 工具调用触发 |
| UI 集成 | 通常无 UI 或独立 Dashboard | 直接在终端中展示,与命令输出混合 |
| 执行模式 | 通常在同一进程中 | 本地子进程或云端远程 |
| 恢复机制 | 内存状态或持久化 | Harness transcript 反序列化 + 终端快照 |
| 用户交互 | 通常无用户介入 | 确认卡片、实时中断、Shell 控制权转移 |
陷阱:本地 Harness(如 Claude Code、Codex)的启动需要处理环境变量(OZ_RUN_ID_ENV、OZ_PARENT_RUN_ID_ENV)、MCP Server 启动等待(20s 超时)、Skill 目录解析。任何一个环节失败都需要通过 SSE 事件流回传错误,而不是直接抛出异常——因为 Agent 可能在远程运行。
Team Mode:并行多 Agent 共享状态编排
与传统的「主编排器 → 子 Agent → 汇总结果」模式不同,Team Mode 引入了 Lead + 多个并行成员 + 共享状态的编排模式,更接近真实软件开发团队的协作方式。
核心架构:
12 个 team_* 工具族:
| 工具 | 功能 |
|---|---|
team_create | 创建新成员 Agent |
team_send_message | 向成员发送消息 |
team_task_create | 在共享任务列表中创建任务 |
team_task_claim | 声明对任务的独占执行权(文件锁) |
team_task_complete | 标记任务完成 |
team_status | 查询团队状态 |
team_mailbox_send | 向共享邮箱发送消息 |
team_mailbox_read | 读取邮箱中的消息 |
team_grid | 获取 tmux 网格布局状态 |
team_focus | 聚焦到特定成员的 pane |
team_terminate | 终止成员 Agent |
team_list | 列出所有成员 |
关键设计特征:
| 特征 | 说明 |
|---|---|
| 并行执行 | Lead + 最多 8 名成员真正并行运行,非顺序执行 |
| 共享邮箱 | 成员间通过延迟确认邮箱通信,避免直接 session 耦合 |
| 文件锁任务声明 | 成员通过文件锁定机制声明对任务的独占权,防止多人同时处理同一任务 |
| 可选 git worktree | 每个成员可在独立的 git worktree 中工作,避免编辑冲突 |
| tmux 可视化 | 每个成员的 session 输出流到独立 tmux pane,实时监控 |
与传统 Subagent 模式的对比:
| 维度 | 传统 Subagent | Team Mode |
|---|---|---|
| 执行模型 | 顺序或有限并行 | Lead + 成员真正并行 |
| 通信方式 | 返回值聚合 | 共享邮箱 + 消息传递 |
| 状态隔离 | 独立 session | 共享任务列表 + 可选 worktree |
| 可见性 | 完成后展示结果 | 实时 tmux 可视化 |
| 适用场景 | 独立、可并行的短任务 | 协作性强的长任务 |
陷阱:
- 多 Agent 同时编辑同一文件时的冲突——推荐通过 git worktree 或文件锁隔离
- 成员过多时上下文膨胀——限制
max_parallel_members并定期清理已完成成员 - 共享状态的文件锁竞争——使用原子操作和超时释放机制