单个大模型完成复杂研究任务时,常见问题是上下文过长、目标漂移、步骤不可见。把任务拆给多个 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 协作中的直接应用;工具侧的安全边界则在不要把生产密钥交给模型里单独记录。