核心摘要
多智能体编排不是在三张流行架构图之间做选择,而是一套负责转移、状态、预算、副作用、终止和恢复的控制系统。先用单 Agent 或确定性流程建立基线;当一个组件需要持续掌控全局时使用 Supervisor,当专家需要接管下一轮交互时使用 Handoff,当独立治理的子团队需要嵌套协调时才引入层级,并且只对真正独立的任务做并行。模型可以提出决策,但边界必须由代码执行。
目录
- 核心要点
- 从最小控制面开始
- 分开设计拓扑与执行流
- 主要编排模式
- 先定义控制契约再写提示词
- 可运行 Go 编排器
- 故障恢复与副作用
- 安全边界
- 评估系统而不是演示
- 映射到当前主流框架
- 生产演进路径
- 常见问题
- 总结
- 一手资料
核心要点
- 多 Agent 是优化项,不是默认需求。 必须与单 Agent 和确定性流程做同口径比较。
- 拓扑和执行流是两项独立选择。 Supervisor 内部同样可以运行流水线、路由、循环或并行分支。
- Handoff 转移的是逻辑控制权。 它不会自动消除 Runtime、状态存储或模型服务的单点风险。
- 控制契约比提示词更重要。 状态所有权、允许转移、终止、预算和副作用语义必须可被机器校验。
- 没有幂等性就不能安全重试。 外部操作发出后超时,表示结果未知,而不是“肯定没执行”。
- 评估必须覆盖协作故障。 除了任务成功率,还要测错路由、漏做、重复、循环、状态丢失、越权、尾延迟和人工升级。
本文只解决编排拓扑与转移契约。若你还没有证明角色拆分的必要性,请先阅读多智能体系统:何时值得构建以及如何落地。
从最小控制面开始
默认架构应该是能够完成任务的最小动态系统。每增加一个 Agent,就增加一份提示词、一个上下文边界、一组失败入口、一段延迟和一次授权判断。
建议按以下顺序演进:
| 基线方案 | 适用条件 | 何时增加控制能力 |
|---|---|---|
| 确定性代码 | 步骤与依赖已知 | 某一步需要规则难以可靠表达的语义判断 |
| 单 Agent 加工具 | 一个上下文可以容纳任务与工具集 | 工具、上下文或权限范围过宽 |
| 单 Agent 加确定性工作流 | 大部分步骤固定,少数节点需要模型判断 | 下一位责任人无法预先确定 |
| 多 Agent | 角色确实需要独立上下文、工具、策略或并行责任 | 实测结果优于更简单的基线 |
这套顺序不是排斥 Agent,而是隔离概率推理真正产生价值的位置。固定解析、鉴权、支付写入、结果合并和终止计数都应该留在代码中,即使外围计划由 AI Agent 提出。
Agent 数量不是容量指标。两个可以循环 Handoff、并拥有生产写权限的 Agent,可能比二十个由代码扇出的只读 Worker 更难运维。选型应基于依赖关系、控制权、风险和评测证据,而不是“少于 5 个用 Supervisor、超过 15 个用层级”之类固定阈值。
分开设计拓扑与执行流
拓扑回答“谁有权决定”,执行流回答“任务如何推进”。把两者混成一个选型问题,会让架构标签掩盖真实控制语义。
三组决策彼此独立:
- 控制权归属: 确定性代码、中央 Supervisor、当前活跃专家,或嵌套 Manager。
- 执行流: 顺序流水线、条件路由、并行扇出,或有界评审循环。
- 运行时语义: 状态持久化、取消、重试、幂等、鉴权和可观测性。
Supervisor 架构可以并行分派相互独立的 Worker;Handoff 网络可以完整运行在单个中心化进程里;层级团队内部也可以使用确定性流水线。尤其要警惕 “Swarm” 这个含义不稳定的词:它可能表示对等 Handoff、群聊、去中心化规划,也可能只是“很多 Worker”。技术方案中应写清真正的控制权和转移语义。
主要编排模式
有工程价值的模式目录包含四种基础原语和它们的混合,而不是从“简单”到“企业级”的统一等级。
| 模式 | 谁选择下一步 | Worker 获得什么状态 | 主要优势 | 主要风险 | 适合场景 |
|---|---|---|---|---|---|
| 代码编排的流水线或路由 | 应用代码 | 类型化任务切片 | 可预测、易测试 | 规则逐渐僵化 | 稳定流程、高风险副作用 |
| Supervisor 调用专家 | Supervisor 保留控制权 | 每次调用所需上下文 | 集中综合与策略控制 | 中心瓶颈、路由偏差 | 调研、分析、子任务委派 |
| Handoff 网络 | 当前 Agent 转交控制权 | 交接信封与筛选后历史 | 专家直接接管对话 | 循环、上下文漂移、责任不清 | 客服分流、领域升级 |
| 层级或嵌套团队 | Manager 协调子团队 | 团队局部状态与产物 | 策略和上下文隔离 | 协调开销、信息压缩损失 | 独立治理的业务域 |
| 混合模式 | 代码约束模型可选边 | 显式产物 | 在硬边界内保留灵活性 | 需要测试更多语义 | 大多数生产系统 |
代码编排的流水线路由与并行
依赖关系已知时,代码编排是最稳妥的默认方案。模型可以识别意图或生成产物,但代码负责选择允许分支、启动并行任务、设置超时并合并结果。
前一步有明确产物、后一步消费该产物时使用流水线;只应选择一个或有限几个 Worker 时使用路由;子任务相互独立且合并规则明确时使用并行扇出与合并。不要并行执行会写同一资源或依赖共享可变对话的任务。
链式编排解释固定阶段契约,工作流编排解释持久化调度与恢复。两者都不要求每个节点必须是 Agent。
Supervisor 调用专家
Supervisor Agent 始终拥有任务控制权,并把专家 Agent 当作工具调用。专家返回产物,但不会成为当前对话的责任人。
以下条件适合 Supervisor:
- 一个组件必须负责最终综合;
- Worker 不应看到完整对话;
- 中央策略需要控制可用专家和工具范围;
- 任务需要多轮委派或评审。
Supervisor 不能成为不受约束的超级用户。代码仍应验证它提出的路由、限制调用次数、筛选 Worker 上下文并要求类型化输出。若每个请求始终走相同路径,应把模型路由替换成代码。
Handoff 交接网络
Handoff 会把当前控制权交给专家。目标 Agent 接收结构化原因、当前目标、必要状态和有界历史,然后直接回复用户,或者执行下一次被允许的交接。
它适合专家必须直接接管后续对话的场景,例如账单客服排查后发现产品故障,需要把当前会话交给技术支持。它不代表系统没有中心 Runtime 或单点故障。Runner 仍要持久化状态、执行转移图、应用 Guardrail 并记录 Trace。
安全 Handoff 更接近 API 调用,而不是转发整段聊天记录。目标 Agent 只应获得完成职责所需的最小上下文,来源和目标双方也都必须有权执行这次转移。
层级与嵌套团队
只有当子团队拥有独立策略、上下文、工具或生命周期时,层级才真正有价值,而不是因为系统里“Agent 很多”。顶层 Manager 应与子团队 Manager 交换压缩且可验证的产物,不应把每个 Worker 的完整对话向上传递。
合理边界包括不同安全域、数据地域、业务线或长期运行的专业流程。照搬组织架构、却没有降低上下文和策略复杂度的层级,只会制造额外 LLM 调用。每层 Manager 都可能压缩掉关键证据,因此必须实测该层是否改善了分解和验证。
混合编排
多数生产系统最终是混合模式:确定性代码拥有图结构,模型只能从少量目标中提议路由,Supervisor 委派分析任务,部分 Worker 并行执行,敏感副作用由人工审批。
关键边界只有一句话:模型可以提出方案,可信代码负责授权、持久化、执行和终止。
先定义控制契约再写提示词
生产级编排契约必须定义每次转移允许改变什么。提示词可以解释角色,却无法可靠执行系统不变量。
任务与产物契约
稳定的交接信封至少包含:
| 字段 | 作用 | 必须满足的不变量 |
|---|---|---|
run_id 与 task_id |
关联、恢复与重放 | 整个运行期间不可变 |
from 与 to |
控制权转移提议 | 对应边必须存在于白名单 |
goal |
当前有界目标 | 不能静默扩大范围 |
artifact_refs 或类型化产物 |
角色间传递证据 | Schema 与来源通过验证 |
hop 与 depth |
控制循环与递归 | 由代码执行硬上限 |
remaining_budget |
Token、调用、成本或工作预算 | 只能单调递减 |
deadline |
端到端时间边界 | 传播给所有子任务 |
idempotency_key |
外部副作用的稳定身份 | 在副作用边界唯一 |
principal 与策略上下文 |
鉴权 | 不能从 Agent 文本推断 |
status 与原因 |
完成或升级 | 必须匹配允许的终态 |
优先传递产物引用或任务级摘要,而不是共享完整 Transcript。Researcher 拥有证据产物,Reviewer 拥有评审结论,Orchestrator 拥有路由和预算。避免两个 Agent 并发写同一字段;必须汇聚时,使用状态版本或 Compare-and-Swap。
如果交接信封使用 JSON,可以用 JSON 格式化工具检查抓取的载荷,并用 JSON Schema 生成器从代表性样本生成初始 Schema。生产校验仍必须位于服务边界,并拒绝未知字段和错误结构。
转移与终止契约
不能只在提示词里要求 LLM “完成后停止”。代码至少应执行:
- 来源到目标的有向转移白名单;
- 最大跳数、嵌套深度、模型调用、Token、成本和总截止时间;
- 要求指定产物类型的终止谓词;
- 无进展检测,例如状态摘要重复或必填字段持续不变;
- 显式的
failed、partial或needs_human终态。
并行派发前必须先预留预算。否则多个 Worker 会同时看到相同剩余预算,最终总消耗突破上限。
上下文契约
上下文工程既是 Token 管理,也是访问控制。要为每个 Agent 明确定义:
- 可以读取哪些指令;
- 可以读取哪些对话轮次和产物;
- 可以调用哪些工具与资源范围;
- 可以写入哪些字段;
- 哪些秘密必须脱敏;
- 数据保留与删除策略。
所有同伴 Agent 产物都应视为不可信输入。不要把 Worker 输出直接拼接到更高优先级的指令通道。保留来源信息,让最终综合者能够区分用户输入、检索证据、模型判断、工具结果和策略决策。
可运行 Go 编排器
下面的纯标准库 Go 程序实现了一个有界 Supervisor 流程。各 Worker 函数是模型或工具 Adapter 的确定性替身,因此控制行为可重复验证。Engine 而不是提示词负责执行转移白名单、类型化产物、跳数与工作预算、Context 截止时间、状态拷贝,以及当前进程内已成功步骤的去重。
package main
import (
"context"
"errors"
"fmt"
"sync"
"time"
)
type Artifact struct {
Kind string
Body string
Source string
}
type Handoff struct {
RunID string
TaskID string
From string
To string
Goal string
Hop int
RemainingBudget int
Artifacts []Artifact
}
type Outcome struct {
Artifact Artifact
Next string
Cost int
Done bool
}
type Agent func(context.Context, Handoff) (Outcome, error)
type journalEntry struct {
done chan struct{}
outcome Outcome
err error
}
type Journal struct {
mu sync.Mutex
entries map[string]*journalEntry
}
func NewJournal() *Journal {
return &Journal{entries: make(map[string]*journalEntry)}
}
func (j *Journal) Do(
ctx context.Context,
key string,
fn func() (Outcome, error),
) (Outcome, error) {
j.mu.Lock()
if entry, ok := j.entries[key]; ok {
j.mu.Unlock()
select {
case <-entry.done:
return entry.outcome, entry.err
case <-ctx.Done():
return Outcome{}, ctx.Err()
}
}
entry := &journalEntry{done: make(chan struct{})}
j.entries[key] = entry
j.mu.Unlock()
entry.outcome, entry.err = fn()
j.mu.Lock()
if entry.err != nil {
delete(j.entries, key)
}
close(entry.done)
j.mu.Unlock()
return entry.outcome, entry.err
}
type Engine struct {
Agents map[string]Agent
Allowed map[string]map[string]bool
MaxHops int
Journal *Journal
}
func (e Engine) Run(ctx context.Context, h Handoff) (Artifact, error) {
if h.RunID == "" || h.TaskID == "" || h.Goal == "" {
return Artifact{}, errors.New("run_id, task_id, and goal are required")
}
for {
if err := ctx.Err(); err != nil {
return Artifact{}, fmt.Errorf("run deadline: %w", err)
}
if h.Hop >= e.MaxHops {
return Artifact{}, fmt.Errorf("maximum hops reached: %d", e.MaxHops)
}
if h.RemainingBudget <= 0 {
return Artifact{}, errors.New("work budget exhausted")
}
if !e.Allowed[h.From][h.To] {
return Artifact{}, fmt.Errorf("transition denied: %s -> %s", h.From, h.To)
}
agent, ok := e.Agents[h.To]
if !ok {
return Artifact{}, fmt.Errorf("unknown agent: %s", h.To)
}
input := h
input.Artifacts = append([]Artifact(nil), h.Artifacts...)
stepKey := fmt.Sprintf("%s/%s/%d/%s", h.RunID, h.TaskID, h.Hop, h.To)
outcome, err := e.Journal.Do(ctx, stepKey, func() (Outcome, error) {
return agent(ctx, input)
})
if err != nil {
return Artifact{}, fmt.Errorf("agent %s: %w", h.To, err)
}
if outcome.Cost <= 0 || outcome.Cost > h.RemainingBudget {
return Artifact{}, fmt.Errorf("invalid cost from %s: %d", h.To, outcome.Cost)
}
if outcome.Artifact.Kind == "" || outcome.Artifact.Body == "" {
return Artifact{}, fmt.Errorf("invalid artifact from %s", h.To)
}
remaining := h.RemainingBudget - outcome.Cost
fmt.Printf(
"hop=%d agent=%s artifact=%s remaining=%d\n",
h.Hop,
h.To,
outcome.Artifact.Kind,
remaining,
)
if outcome.Done {
if outcome.Next != "" || outcome.Artifact.Kind != "final" {
return Artifact{}, errors.New("invalid terminal outcome")
}
return outcome.Artifact, nil
}
if outcome.Next == "" {
return Artifact{}, errors.New("non-terminal outcome has no next agent")
}
h.Artifacts = append(h.Artifacts, outcome.Artifact)
h.From, h.To = h.To, outcome.Next
h.Hop++
h.RemainingBudget = remaining
}
}
func hasArtifact(artifacts []Artifact, kind string) bool {
for _, artifact := range artifacts {
if artifact.Kind == kind {
return true
}
}
return false
}
func main() {
researcher := func(ctx context.Context, h Handoff) (Outcome, error) {
if err := ctx.Err(); err != nil {
return Outcome{}, err
}
return Outcome{
Artifact: Artifact{
Kind: "evidence",
Body: "primary sources collected",
Source: "researcher",
},
Next: "reviewer",
Cost: 2,
}, nil
}
reviewer := func(ctx context.Context, h Handoff) (Outcome, error) {
if !hasArtifact(h.Artifacts, "evidence") {
return Outcome{}, errors.New("evidence artifact is required")
}
return Outcome{
Artifact: Artifact{
Kind: "review",
Body: "evidence and scope approved",
Source: "reviewer",
},
Next: "supervisor",
Cost: 1,
}, nil
}
supervisor := func(ctx context.Context, h Handoff) (Outcome, error) {
if !hasArtifact(h.Artifacts, "evidence") ||
!hasArtifact(h.Artifacts, "review") {
return Outcome{}, errors.New("verified evidence is required")
}
return Outcome{
Artifact: Artifact{
Kind: "final",
Body: "architecture brief ready",
Source: "supervisor",
},
Cost: 1,
Done: true,
}, nil
}
engine := Engine{
Agents: map[string]Agent{
"researcher": researcher,
"reviewer": reviewer,
"supervisor": supervisor,
},
Allowed: map[string]map[string]bool{
"supervisor": {"researcher": true},
"researcher": {"reviewer": true},
"reviewer": {"supervisor": true},
},
MaxHops: 4,
Journal: NewJournal(),
}
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
final, err := engine.Run(ctx, Handoff{
RunID: "run-42",
TaskID: "architecture-brief",
From: "supervisor",
To: "researcher",
Goal: "produce a source-backed architecture brief",
RemainingBudget: 4,
})
if err != nil {
fmt.Println("run failed:", err)
return
}
fmt.Println("final:", final.Body)
}
预期输出:
hop=0 agent=researcher artifact=evidence remaining=2
hop=1 agent=reviewer artifact=review remaining=1
hop=2 agent=supervisor artifact=final remaining=0
final: architecture brief ready
示例刻意把模型调用放在控制核心之外。真实 Adapter 应把模型输出解析成 Outcome,拒绝未知字段和目标,再由 Engine 执行转移。该 Journal 只能在进程存活期间去重已成功步骤,不能让外部副作用自动获得“恰好一次”语义。涉及支付、发消息、建工单等操作前,必须使用持久化 Effect Record、唯一幂等键和下游对账。
故障恢复与副作用
恢复策略必须取决于系统究竟知道什么。统一“重试三次”会重复付款、发信或写数据。
| 故障类型 | 已知事实 | 正确处理 |
|---|---|---|
| 执行前被拒绝 | 尚未启动副作用 | 修正输入、改路由或失败 |
| 临时读取失败 | 操作只读 | 在截止时间内退避重试 |
| 语义输出不合法 | 模型内容不可用 | 修复一次、重新规划或升级人工 |
| 已确认副作用失败 | 操作没有提交 | 使用同一幂等键重试 |
| 副作用结果未知 | 发出请求后超时 | 按幂等键查询对账,不得创建新操作 |
| 策略拒绝 | 行为不允许 | 停止或请求有权限的人审批 |
| 预算或时间耗尽 | 任务可能只完成一部分 | 返回类型化部分结果或升级 |
显式隔离副作用
把推理与外部操作拆成五步:
- Agent 用类型化参数提出动作;
- 策略代码校验 Principal、资源和额度;
- Effect Executor 写入幂等键;
- Executor 执行操作或对账;
- 结果成为不可变产物。
多步副作用应使用显式补偿的 Saga,而不是假装整个流程是一个事务。补偿是新的业务动作,不是数据库自动回滚:退款、关闭重复工单或发送更正通知本身都可能失败,也需要独立审计记录。
并行前先定义完成条件
并行分支必须预先选择完成策略:
- 全部成功: 所有必需分支都要完成;
- 法定数量: 达到预先定义的 Quorum 即可;
- 尽力而为: 返回成功产物和类型化失败;
- 首个有效结果: 接受第一个通过校验的结果,并取消其余任务。
合并过程应尽量确定化。使用稳定任务 ID 和产物 ID 去重,保留来源,并把父任务取消传播给所有子任务。模型可以总结合并后的证据,但不能静默决定某个必需分支缺失是否无关紧要。
Checkpoint 应保存在有业务语义的边界,而不是每个 Token 之后。有效检查点包含运行版本、当前节点、已接受产物、已预留预算、待确认副作用和下一组允许动作。Trace 与成本事件设计可参考 AI Agent 可观测性。
安全边界
每次 Agent 转移都是一次信任边界跨越。接收方不能因为另一个 Agent 发起了 Handoff,就自动继承额外权限。
至少执行以下控制:
- Principal 与策略上下文独立于自然语言消息传递;
- 每个 Agent 只获得最小工具、资源、租户、地域和消费额度;
- Handoff 与工具调用在副作用前由可信代码鉴权;
- 同伴输出、检索内容和工具结果都按不可信数据处理;
- Secret 不进入共享 Transcript 和摘要;
- 高影响或不可逆操作必须人工审批;
- 记录策略判断、Agent 提议、获批参数、副作用结果和操作者。
Supervisor 不应持有所有 Worker 的凭证。它只需要对任务类型的委派权,真正执行操作的服务仍要独立验证用户与资源权限。AI Agent 工具安全详细说明了最小权限和工具结果投毒。
OpenAI Handoff 文档还提示了一个容易遗漏的生命周期边界:Handoff 需要的鉴权或数据加载应在目标 Agent 产生副作用前完成;只挂在入口 Agent 上的 Input Guardrail 不会自动覆盖之后所有 Agent。Guardrail 的生效范围是需要验证的实现属性,不是框架名称自带的保证。
评估系统而不是演示
多智能体评测必须与更简单的端到端基线比较,并单独定位协作故障。一段成功 Transcript 只是样例,不是发布门禁。
评测集应包含正常任务、模糊路由、证据缺失、产物冲突、重复 Handoff、工具故障、慢 Worker、恶意同伴输出和副作用结果未知。每条样本要记录预期路由、必需产物、禁止动作、可接受终态和人工升级条件。
至少测量:
| 维度 | 示例指标 |
|---|---|
| 任务结果 | 相对单 Agent 与确定性基线的成功率和 Rubric 得分 |
| 路由 | 目标正确率、不必要委派和相对最佳合法路由的质量损失 |
| 覆盖 | 缺失的必需子任务或产物 |
| 重复 | 重复工作和重复外部副作用 |
| 终止 | 循环率、最大跳数耗尽率和无进展退出 |
| 状态完整性 | 丢失、过期、冲突或过度暴露的上下文 |
| 安全 | 越权提议、被拦截副作用和审批绕过 |
| 可靠性 | 重试恢复、部分结果质量和升级准确性 |
| 效率 | 模型调用、Token、工具调用、成本与 p50/p95/p99 延迟 |
MAST 研究分析了七种框架中的 1,600 多条多智能体运行 Trace,并报告了十四类故障,覆盖系统设计、Agent 间不一致和任务验证。它适合作为测试分类表,但不能证明某个固定架构或框架具有普遍失败率。
要主动做故障注入:在副作用发出后让 Worker 超时,返回错误 Schema,重放旧 Handoff,拒绝工具权限,在子任务运行时取消父任务,并让两个分支产生冲突。只有 Runtime 能在不重复副作用的前提下进入预期终态,才具备上线条件。
映射到当前主流框架
框架提供编排原语,但不会替代应用策略。下表依据文末官方文档;API 会演进,实现前仍需核验当前版本。
| 框架 | 相关原语 | 设计含义 |
|---|---|---|
| OpenAI Agents SDK | Agents as tools、Handoff、代码编排 | 明确 Manager 是保留控制还是转交控制;筛选 Handoff 输入并核验 Guardrail 范围 |
| LangChain 多智能体 | Subagent、Handoff、Skill、Router、自定义工作流 | 根据上下文和控制需求选模式;单 Agent 仍可能已经足够 |
| AutoGen AgentChat | Round-robin、Selector、Swarm、Magentic-One 团队与终止条件 | 团队预设仍需要显式停止条件和任务级评测 |
| CrewAI | Sequential 与 Hierarchical Process | 层级模式需要 Manager Model 或 Manager Agent;Process 选择不定义副作用语义 |
OpenAI 原 Swarm 仓库明确将自己定位为实验和教学项目,并引导生产用户迁移到 Agents SDK。它仍有助于理解 Handoff,但新的生产示例不应继续把 Swarm 当成当前生产 API。
Magentic-One 展示了 Orchestrator 如何在多个专家 Agent 之间规划、追踪进度并重规划。论文基准只能证明该系统在特定任务和实验环境下的结果,不能外推为“层级一定优于简单流程”。
生产演进路径
可靠上线顺序是在控制契约可观测之后逐步增加自主性。
- 建立基线。 分别用确定性代码和单 Agent 完成任务,记录质量、成本、延迟与错误类型。
- 抽取类型化边界。 在增加角色前定义任务、产物、转移、终态和副作用 Schema。
- 只增加一个专业角色。 先委派最明确的有界任务,并只授予只读工具,然后比较结果。
- 约束动态路由。 模型只能从白名单目标中提出选择,预算和鉴权继续由代码负责。
- 持久化运行状态。 增加 Checkpoint、Lease、幂等记录、取消和可重放恢复。
- 测试恶劣故障。 注入循环、旧上下文、畸形输出、并行部分失败、超时和策略拒绝。
- 最后开放敏感副作用。 加入人工审批、窄权限凭证、对账与 Kill Switch。
- 只按证据扩展。 评测确认具体收益后,再增加 Handoff、并行或层级。
除非运行记录了带版本的图结构和迁移语义,否则不要在一个进行中的 Run 内热切换拓扑。恢复时应使用创建 Checkpoint 的图版本,或者执行显式状态迁移。
常见问题
什么是多智能体编排
多智能体编排是协调专业 Agent 的控制层。它决定下一位执行者、限制每个角色可见的状态、校验输出、授权转移和工具、合并并行结果、持久化进度,并判断完成或人工升级。只有一张拓扑图,还不能构成生产编排设计。
什么时候应该用多 Agent 而不是单 Agent
当专业化产生可测量收益时才使用多 Agent,例如隔离上下文、拆分工具、区分权限、并行独立任务或建立责任边界。先与单 Agent 和确定性流程比较。如果只是把相同模型、上下文、工具和策略拆成多个角色提示词,协调成本往往上升,却没有增加能力。
Supervisor 和 Handoff 有什么区别
Supervisor 保留控制权,只调用专家获取有界产物;Handoff 改变当前责任人,由目标专家接管下一轮交互,并可能继续转交。两种模式都可以使用同一个中心 Runner 和持久化状态库。逻辑上的对等控制不等于物理上的去中心化基础设施。
如何防止 Agent 无限 Handoff
使用转移白名单、最大跳数与深度、端到端截止时间、单调递减预算、显式完成条件、重复状态检测和人工升级终态。记录每次提议和获准的转移。不能只依赖“不要循环”这样的提示词。
多智能体框架应该如何选择
先定义控制契约,再选择最容易映射该契约的框架。OpenAI Agents SDK 直接区分 Manager 调用专家和 Handoff;LangChain 提供多种模式与自定义工作流;AutoGen 提供团队预设和终止条件;CrewAI 提供顺序与层级流程。用同一套评测集测试最小可行方案,而不是只比较功能列表。
总结
生产级多智能体编排,本质是在不确定条件下执行受控状态转移。先从确定性代码或单 Agent 开始,分开设计拓扑与执行流,只在评测证明收益的位置增加自主性。转移白名单、预算、终止、鉴权、持久化和副作用幂等都必须位于提示词之外。最佳架构不是 Agent 最多的架构,而是能够达到目标、并在失败时保持有界和可解释的最小系统。
QubitTool 相关阅读
- 多智能体系统:何时值得构建以及如何落地
- AI Agent 可观测性:隐私安全的 Trace、评估与成本
- AI Agent 工具安全:权限与工具投毒
- 多智能体系统中的 MCP:协议边界而非策略引擎
- Supervisor Agent
- Router Agent
- Planner-Executor
一手资料
- OpenAI Agents SDK:多 Agent 编排 — Manager、Handoff 与代码编排模式
- OpenAI Agents SDK:Handoff — 结构化输入、Callback、Filter 与 Guardrail 范围
- LangChain:多智能体 — Subagent、Handoff、Skill、Router、自定义工作流与上下文工程
- Microsoft AutoGen:团队 — 团队预设与终止条件
- CrewAI:流程 — 顺序与层级流程语义
- MAST:多智能体 LLM 系统为何失败 — 跨框架 Trace 故障分类
- Magentic-One:通用多智能体系统 — 规划、进度追踪、重规划与有边界的基准结果