单个大模型完成复杂研究任务时,常见问题是上下文过长、目标漂移、步骤不可见。把任务拆给多个 Agent 看起来很自然:一个负责规划,一个搜索资料,一个分析数据,一个撰写报告,再由另一个审核。

但把角色写进提示词,并不会自动得到组织。多个 Agent 反而会带来更多状态、通信、成本和失败路径。如果没有控制面,系统只是多次模型调用的串联。

多 Agent 系统中的控制面、执行 Agent、产物仓库、工具网关和评估系统

图 1:Agent 负责局部开放推理,控制面负责确定性的状态、预算、权限和恢复。各角色通过产物协作,不靠长对话维持一致。

先证明为什么需要多个 Agent

复杂任务不一定需要多 Agent。一个模型配合结构化工具调用,往往比角色网络更简单可靠。

我们只在三类情况考虑拆分:子任务需要明显不同的上下文或工具;子任务可以并行并独立验证;任务过程需要明确责任边界和中间产物。如果拆分只是为了让提示词看起来像团队,收益通常抵不过协调成本。

例如金融研究中,材料检索与财务指标计算适合分开。前者处理文档与来源,后者依赖结构化数据和确定公式。最终撰写可以消费两者的受控产物,而不是重新浏览全部原始上下文。

工作流拥有状态,Agent 不拥有流程

Agent 擅长在局部目标下推理和使用工具,但整个任务的生命周期应由确定性工作流控制。控制面知道当前节点、依赖、输入、输出、尝试次数和预算,Agent 只负责完成一个有边界的步骤。

我们把任务建模为有向图。节点可以是模型调用、确定性函数、人工确认或外部工具;边表达依赖和条件;运行状态持久化到数据库。这样进程重启后可以从已完成节点继续,而不是重新执行全部研究。

每个节点拥有稳定输入 Schema 和输出 Schema。模型输出先经过结构验证,缺失字段或引用格式错误会触发修复,而不是直接流入下游。自然语言仍然存在,但关键控制信息不依赖下游再次猜测。

我会把节点状态收敛成少量可枚举值,而不是用一段自然语言描述“Agent 似乎做到哪里了”。最小结构大致如下:

type NodeRun = {
  taskVersion: string;
  nodeId: string;
  status: "ready" | "running" | "waiting_user" | "succeeded" | "failed";
  inputHash: string;
  attempt: number;
  budget: { tokens: number; toolCalls: number; deadline: string };
  artifactIds: string[];
  error?: { kind: "transient" | "invalid_output" | "insufficient_evidence"; detail: string };
};

这段结构没有保存模型的完整思考,但足以回答工程上真正需要的问题:执行的是哪个版本、能否安全重试、已经产出什么、为什么停下来。

上下文要按任务分配

把所有历史对话、全部文档和所有 Agent 输出塞给每个节点,既昂贵又容易干扰推理。上下文工程的核心是为当前任务选择最少但充分的信息。

规划节点需要用户目标、可用工具与约束;检索节点需要查询意图和来源范围;分析节点需要经过筛选的事实与数据;撰写节点需要结论结构、证据和表达要求。

长材料先被切分和索引,再按问题检索。关键事实以结构化记忆保存,附带来源、时间和置信度。临时推理不会自动进入长期记忆,只有经过验证的产物才被提升。

上下文也要有版本。用户修改研究范围后,下游节点不能继续使用旧假设。通过任务版本与依赖哈希,可以判断哪些结果仍然有效,哪些必须重算。

通信使用产物,不使用角色对话

多 Agent 示例常让不同角色互相发送长消息,仿佛会议讨论。真实系统中,这会重复信息并放大误解。

更稳定的协作方式是传递明确产物:检索 Agent 输出带引用的材料列表,数据 Agent 输出指标表与计算依据,审阅 Agent 输出问题清单和通过状态。下游消费产物,不需要重放上游的全部思考。

共享黑板可以保存当前目标、已确认事实、未解决问题和产物索引。所有 Agent 读取同一份任务事实,但写入需要经过控制面验证,避免不同角色互相覆盖。

工具调用必须有安全边界

Agent 使用搜索、数据库、代码执行或文件系统时,模型输出不能直接成为无限制命令。工具层负责参数验证、权限、超时、速率限制和结果裁剪。

读操作与写操作分开授权,高风险动作需要人工确认。研究系统通常以读取为主,但导出、发送或修改外部数据仍应明确展示即将发生的动作。

工具返回错误要结构化:是否可重试、是否需要修改参数、是否缺少权限。把一段堆栈直接交给模型,可能让它在错误方向上反复尝试。

每次调用记录任务、节点、模型、工具、耗时和成本,但不保存不必要的敏感内容。审计日志既用于排障,也用于回答“这条结论是如何产生的”。

预算是系统状态的一部分

多 Agent 很容易形成调用乘法。一轮规划生成多个子任务,每个子任务继续反思和重试,成本与延迟会快速失控。

任务必须有总预算,包括模型调用次数、Token、工具次数和最长执行时间。节点获得局部预算,消耗接近上限时选择降级、请求用户缩小范围或返回当前最佳结果。

预算不是只为节省费用,它迫使工作流定义停止条件。没有停止条件的“继续思考”不等于更高质量,常常只是更多文字。

并行也需要限制。可以独立执行的检索任务并行能缩短时间,但过多并发会触发模型或数据源限流。调度器根据依赖、优先级与资源配额启动节点,而不是让 Agent 自由复制自己。

失败要能局部恢复

复杂工作流一定会失败:模型返回非法结构,数据源超时,引用无法访问,某个结论缺乏证据。可靠系统不应从头重跑。

节点执行采用幂等设计。相同任务版本与输入哈希对应同一执行,重试不会重复产生副作用。成功产物持久化,失败保留错误分类和尝试记录。

恢复策略按错误决定:临时网络错误自动退避;格式错误可以用约束更强的修复调用;证据不足返回规划节点补充检索;超过阈值进入人工确认。

人工不是工作流失败,而是一种正式节点。系统应展示需要判断的具体问题、已有证据和可选动作,用户确认后从原位置继续。

评估不能只看最终文风

最终报告读起来顺畅,可能仍然包含错误来源和遗漏数据。多 Agent 需要分层评估。

节点层检查结构合法率、工具成功率、引用覆盖和任务完成;工作流层检查总耗时、成本、重试与人工介入;结果层通过固定问题集评估事实正确、证据一致和任务价值。

对于关键计算,使用确定性程序复核,而不是让另一个模型“感觉是否正确”。对于来源,验证引用确实支持对应陈述。模型评审可以辅助发现表达和覆盖问题,不能成为唯一裁判。

线上失败样本进入评估集,每次提示词、模型或流程改变都运行回归。Agent 系统的行为受多项因素影响,没有稳定样本就无法知道优化是否真实。

可观测的是过程,不是思维链

调试系统并不需要暴露模型的私有推理。我们需要的是可执行过程:节点输入摘要、工具调用、结构化输出、状态转换、引用和错误。

界面以任务图展示进度,用户能看到正在检索、计算还是审阅,能展开中间产物,也能取消不再需要的分支。对开发者,追踪视图关联每次调用的版本、耗时和成本。

这种可观测性也改善产品信任。用户不必相信一个突然出现的答案,而是可以检查它使用了哪些材料,哪些步骤由确定程序完成,哪些判断仍有不确定性。

多 Agent 的价值在组织复杂度

多 Agent 不是让多个模型模拟一个公司。它的价值是把复杂任务拆成拥有清晰输入、工具与验证方式的工作单元,再由可靠控制面协调。

角色可以帮助模型理解局部目标,但系统边界必须由代码表达。自然语言负责开放推理,Schema 负责契约,工作流负责状态,工具层负责安全,评估负责反馈。

当这些基础设施不存在时,增加 Agent 只会增加不可预测性。当它们成立后,多 Agent 才可能在长周期、跨工具和可审计任务中产生真实价值。

具体到 Agent 之间的交接,我会要求使用结构化任务包:目标、输入 artifact、允许工具、已完成证据、未解决假设、预算和下一步验收。下游 Agent 不读取上游完整对话来猜任务:

outcome: 生成可评审的迁移计划
artifacts: [schema-v3.json, usage-scan.csv]
openQuestions: [删除字段是否仍有离线消费者]
allowedTools: [repo.read, metrics.query]
doneWhen: 风险与回滚步骤齐全

结构化交接同时降低上下文成本和责任模糊——这正是上下文工程里“最小共享事实”原则在 Agent 协作中的直接应用;工具侧的安全边界则在不要把生产密钥交给模型里单独记录。