上一篇《我对当前 AI Agent 的理解》里,我把“安排上下文和状态”写成了设计 Agent 的一个步骤。后来再看,那一节写得太轻了。模型可以推理、调用工具,也可以连续工作很久,但这些能力最终都落在同一个问题上:它在当前这一步究竟看到了什么。
这里的“看到”比提示词宽得多。任务要求、工具说明、检索结果、历史对话、已经做过的决定,甚至另一个 Agent 留下来的工作痕迹,都会影响下一次判断。模型越来越强以后,我反而更少把问题归结为“提示词还不够好”。很多失败发生在模型调用之前:资料入库时丢了版面,检索只返回了半句话,压缩历史时删掉了一个决定,或者两个 Agent 在不同上下文里各自做了合理但互相冲突的选择。
这篇先补几件彼此相关的事:知识怎样进入系统,每一步该给模型看什么,工具和系统提示词怎样分工,同一套资产如何适配不同模型,以及什么时候才值得把一条执行线拆成多个 Agent。
知识库不只是向量数据库
说到 Agent 知识库,一个常见做法是把 PDF 转成文本,按固定长度切块,生成向量,再放进向量数据库。这个流程能工作,但它很容易让人产生一种错觉:文件进了库,知识就保留下来了。真正要设计的不是一个“存片段的库”,而是一条从原始资料到可验证证据的路径。
真实文档没有这么规整。一份年报里的数字可能在表格主体,单位写在表头,统计口径藏在脚注,旁边的柱状图又给出了跨年趋势。只保留 OCR 文本后,这几部分往往会被拆开。检索虽然命中了“营业收入增长 7.3%”,模型却不知道这是哪个地区、哪一年,也不知道这个数字已经剔除了某项一次性收入。
多模态知识库首先要解决入库时的信息损失。我会同时保留三类表示。原始文件负责还原和审计,解析后的文本、标题层级、表格单元格与元数据方便精确查询,页面图像则保留版面、图表和视觉关系。三者都带着稳定的文档 ID、页码或时间位置,检索结果才能回到原文。
ColPali选择直接对文档页面图像生成多向量表示,避免把视觉丰富的页面先压扁成纯文本。VisRAG也采用视觉模型完成检索和生成,并在论文使用的数据集上报告了相对传统文本 RAG 的提升。它们并不意味着 OCR 和文本索引已经没用。设备编号、合同条款号、报错代码这类内容,关键词检索仍然很有效。更实际的做法是保留多条检索路径,让问题决定走哪一条。
我会把知识库的构建和运行时检索分开看。入库阶段处理版本、权限、去重、解析、索引和来源定位。除了文本和向量索引,还可以从实体、事件和关系中构建知识图谱,使用 GraphRAG 这类方法回答“哪些事实共同指向一个原因”或“几个实体之间怎样关联”的问题。图谱适合补足跨文档关系,但不应替代原文证据:最终回答仍要能够回到具体页面、段落或表格。
到了运行阶段,Agent 先判断问题需要什么证据,再决定是否拆解任务。例如“供应商过去两年是否反复延迟交付,原因是什么”可以拆成时间范围、延迟记录、正常交付基线、共同上游因素和原因证据几个子问题。每个子问题再通过自适应路由选择关键词、向量、视觉、元数据或图谱查询,而不是所有问题都固定走同一个向量检索器。

问题和资料也未必使用同一种模态。用户可能用一句话询问“仪表盘上那条突然下降的蓝线是什么”,答案却分散在截图、指标字典和一次会议录音里。入库时可以为图像、音视频转录和结构化数据建立关联,运行时则先判断需要的是视觉定位、精确字段还是语义解释。Agent 找到截图后还应继续取回图例和指标定义,而不是让视觉模型只凭曲线形状猜原因。多模态的价值在这里很具体:保住原始证据之间的关系,并让检索可以沿着关系继续走。
传统 RAG 常常只做一次检索:把用户问题转换成查询,取回最相似的若干片段,然后生成答案。Agentic RAG 多了一段反馈循环。Agentic RAG 的综述把规划、反思和工具选择等 Agent 模式放进检索过程。换成更直接的话,就是 Agent 可以检查现有证据够不够,再决定是否拆问题、改写查询、换数据源或停止。
例如用户问:“这个供应商过去两年是否反复延迟交付,原因是什么?”第一次检索可能只找到三张延期工单。Agent 发现缺少正常交付的基线,就继续查订单记录;看到两次延期都提到同一个上游零件,又去检索采购异常和邮件附件;如果图谱显示这些记录属于同一批次,再回到原文核对时间和责任归属。每一轮都应记录已覆盖的子问题、证据质量和剩余缺口,直到验收条件满足或预算耗尽。这里真正起作用的是连续检索和证据检查,top-k 参数只是其中一小部分。
检索循环也需要边界。每次运行要限制查询次数和费用,低质量来源不能因为重复出现就变成事实,最终结论必须带文档与位置。评估时要把“有没有检索到证据”和“拿到证据后有没有正确回答”分开,还要观察路由是否选对、拆解是否遗漏关键子问题、迭代是否在证据足够后及时停止。这样才知道该改索引、图谱、查询策略、路由规则还是生成提示词。
还有一个容易忽略的例外:资料足够少时,RAG 可能是多余的。Anthropic 在介绍 Contextual Retrieval 时提到,如果整个知识库能放进模型上下文,可以直接提供完整资料并配合缓存。具体容量会随着模型变化,判断原则不变。先估算资料规模、更新频率和访问权限,再决定是否建立检索系统。向量数据库不是知识库的入场券。
上下文工程是在管理模型此刻能看到什么
知识库保存的是系统可能用到的资料,上下文是某一步实际交给模型的内容。两者经常混在一起讨论,结果就是把“召回更多”当成“上下文更好”。事实上,多放十篇文档可能提高召回,也可能把真正有用的两段话埋掉。
我比较喜欢 LangChain 对上下文工程的归纳:写入、选择、压缩和隔离。这四个词足够朴素,也基本覆盖了长任务里最常见的操作。
- 写入,是把计划、已确认事实、来源位置和未完成事项保存到上下文窗口之外。它可以是一份任务状态、一组结构化字段,也可以是工作目录里的文件。
- 选择,是在下一步只取回相关的资料、工具和状态。选择的对象不只是知识片段,工具说明和少量示例也需要按需加载。
- 压缩,是在内容变长时保留继续工作所需的信息。它不是把十页文字随便总结成一页,而是明确保留做过的决定、依据、尚未解决的问题和人的确认。
- 隔离,是让某些内容留在沙箱、状态对象或子任务中,需要时只返回引用或摘要。它可以节省上下文,也会带来信息交接的风险。

上下文工程最难的地方是选择。一个 Agent 可以访问二十个工具,并不表示每一步都应该看到二十份说明。工具名字相近、职责重叠时,模型会在选择上浪费判断,甚至调用一个“看起来也能用”的错误接口。知识检索也一样。语义相似只能说明两段文字谈的是相近主题,不能说明它们足以支持结论。
长任务还会遇到另一种问题:早期的错误会留在上下文里,后续每一步都把它当成前提。第一次查询把客户 A 认成客户 B,下一轮据此筛选订单,第三轮再为错误结果写解释。上下文越长,这个错误看起来越像经过多轮验证的事实。保存状态时要区分原始观察、模型推断和已经确认的结论,推断还应带着它依赖的证据。
我会把任务状态写得比聊天记录更正式一点。至少保存当前目标、完成条件、已确认事实、关键决定、待办和阻塞项。工具返回的大对象留在外部环境,状态里只放引用、必要摘要和校验信息。需要压缩时,先按这些字段重建一份可以继续执行的状态,再丢掉旧消息。直接要求模型“总结以上对话”太含糊了,它可能留下讨论气氛,却删掉真正影响下一步的约束。
这也是上下文工程和普通提示词优化的区别。提示词优化关心一句话怎样表达更容易被模型理解;上下文工程还要决定什么时候加载哪份提示、哪些工具结果进入下一轮、什么内容写到外部状态,以及何时压缩或重新检索。它贯穿整个执行循环,不是在系统提示词开头补一段背景介绍。
工具设计也是上下文工程
上一篇写过工具契约,这里再补它和上下文工程的关系。模型每次调用工具前要阅读名称、说明和参数,调用之后还要理解返回值。工具越多、描述越长、格式越别扭,这些内容占用的上下文越多,模型花在“这个工具到底怎么用”上的判断也越多。
我更愿意提供少量、职责清楚的通用原语。四个可以顺序组合的工具,能力空间经常大于四十个按场景命名的专用工具,因为前一个工具的结果可以成为后一个工具的输入。搜索、读取、转换和提交这类原语可以组成很多任务;如果为“查询合同”“查询发票”“查询工单”分别注册一批相似工具,模型还要先猜它面对的是哪个预设场景。
少而通用不等于把所有能力塞进一个 do_everything。一个带几十种 action、参数随模式变化的万能工具,只是把工具选择的负担搬进了参数选择。通用原语仍然要有稳定职责:搜索负责找候选,读取负责取得原始内容,转换只产生新结果,提交才会改变外部状态。边界清楚以后,组合才可靠。
工具还要降低理解和格式负担。参数名使用业务里的普通说法,类型、单位和默认值写清楚;能传文件引用就不要让模型手工转义几千行 JSON;能返回结构化字段和一段短摘要,就不要只给一大段混杂日志。结果很大时提供分页、游标或产物路径,让模型知道怎样继续取,而不是默默截断。
安全约束应当做到工具里。只读和写入分开授权,写操作验证范围与参数,高风险动作先返回预览并要求确认;能做幂等处理的接口要接受请求 ID,避免重试造成两次扣款或两次提交。提示词可以告诉模型什么时候应该谨慎,真正的权限、额度和不可逆边界不能由模型自觉维持。
错误信息也是工具输出的一部分,它会直接进入下一轮上下文。只有 failed 的返回值逼着模型猜。更有用的错误至少说明原因、是否能重试、已经完成了哪些部分,以及推荐的下一步:
code: PERMISSION_DENIED
message: 当前凭证只能读取华东区域订单
retryable: false
completed: 查询条件已验证,尚未读取订单
next_action: 申请华南区域只读权限,或缩小 region 参数工具接口做得好,系统提示词可以短很多。模型不必记住每个失败码的补救办法,也不必靠一长串规则约束危险动作。工具自己提供边界和反馈,提示词只负责教模型怎样判断。
系统提示词应该提供强启发式
Agent 出现一次失败后,最容易做的修复是在系统提示词末尾追加一条规则。来源选错了,就写“必须使用官方来源”;搜索太久了,就写“不要进行不必要的搜索”;下一次又因为官方资料缺失提前停止,于是再加一条例外。几轮下来,每条规则单独看都有道理,放在一起却不知道谁优先。
我不认为系统提示词应该穷举所有行为。开放任务的分支太多,模型还会遇到编写提示词时没有见过的工具返回和资料组合。规则越长,冲突越难发现,真正重要的边界也越容易被埋在中间。更麻烦的是,提示词里的“禁止”并不是权限控制。只要工具仍然允许写入,系统就不能靠一句“不要误删数据”承担安全责任。
系统提示词更适合放少量、长期有效的强启发式。例如:
优先寻找能直接支持结论的一手来源;找不到时,说明降级后的来源类型。
先用低成本方式确认任务范围,再按问题难度增加检索和调用次数。
事实、推断和建议分开表达;缺少证据时不要把推断改写成事实。
涉及不可逆操作或责任归属时停止执行,展示将要发生的变更并请求确认。
证据已经满足验收条件时结束;继续搜索只为补足明确缺口。这些句子没有规定每一种查询该输入什么关键词,却给出了遇到新情况时仍然可用的判断方向。Anthropic 在介绍其多 Agent 研究系统时也提到,他们的提示策略侧重把熟练研究者的启发式教给 Agent,而不是写死所有规则,同时用明确的护栏限制失控行为。
不同性质的内容应该放在不同层。身份、目标、风险边界、来源偏好和停止原则留在系统提示词;金额上限、文件访问范围、审批要求等确定性约束由代码与权限系统执行;领域术语和会变化的业务规则进入知识库;某次任务的输入、输出格式和验收条件写在任务模板里。工具的适用条件则跟着工具定义走。这样修改一项业务规则时,不必重新翻整份系统提示词。
强启发式也不是凭感觉写完就算。每一段新增内容都应该对应一个能复现的失败案例,再用评估集确认它修复了什么,有没有让别的场景退步。如果一次失败源于工具返回含糊,应该先改工具;源于权限过宽,就收紧权限。只有模型缺少可泛化的判断原则时,才去改系统提示词。否则,提示词会慢慢变成系统所有问题的收容所。
同一份提示词换模型后怎么办
同一份系统提示词交给不同模型,结果不会自动一致。模型对指令优先级、长上下文、工具选择、结构化输出和不确定性的处理都有差异。小模型可能需要更窄的任务和更明确的示例;另一个模型能理解开放式启发,却容易在工具格式上出错。即使供应商和模型名称没变,版本更新也可能改变行为。
我会先把“同一份提示词”当成基线测试。让候选模型使用相同的核心提示、工具和任务样本,可以看出差异来自哪里。但生产系统没必要追求一份字符串在所有模型上原样运行。真正应该稳定的是语义契约:目标、业务边界、来源优先级、停止条件和验收标准不能因为换模型而改变。
核心提示之外可以保留一层很薄的模型适配。适配层处理消息怎样分段、工具说明需要多细、是否增加少量示例、怎样请求结构化输出,以及推理与 token 预算如何设置。它不复制业务规则,也不为每个模型维护一套互相漂移的完整提示词。模型被替换时,先换适配层,再用同一套评估集检查语义有没有走样。
评估不能只看最后一段回答像不像。至少要比较任务完成率、工具选择、参数与格式合规、引用是否支持结论、安全边界、延迟和费用。模型与推理参数要固定版本并写进运行记录,否则两次结果不同,却不知道变化来自提示词、模型更新还是采样设置。长任务还应比较完整轨迹,因为两个模型可能给出相似答案,中间却一个用了五次正确查询,另一个靠猜测碰巧答对。
如果差异来自能力上限,继续给提示词打补丁通常没有用。一个模型始终无法稳定选择十个工具,可以让它处理分类和摘要,把开放式调查交给更强的模型;高风险任务则只使用通过相应安全评估的模型。路由的依据应是任务难度和评估结果,不是模型名听起来更强。
模型升级也应该像工具和代码升级一样经过影子运行或小流量验证。先在真实任务副本上比较新旧模型,再逐步切换,保留回退路径。这样“模型可替换”才不是一句架构口号:替换会产生差异,但团队知道差异在哪里,也有证据决定是否接受。
单 Agent、多 Agent 与多模型编排
Cognition 的 Don’t Build Multi-Agents 不是说任何任务都只能用一个 Agent,而是在提醒两件事:共享上下文时,最好共享完整的执行轨迹;动作本身带着隐含决定,互相冲突的决定很难在最后补救。Anthropic 的 Building Effective AI Agents 也给出同一个起点:先用能解决问题的最简单方案,再用评估证明额外复杂度值得。
所以我会先问两个问题:后一步是否依赖前一步的判断?各个结果能否在不共享全部过程的情况下独立验收?前一个问题的答案是“是”时,优先保留一条执行线;后一个问题的答案是“是”时,才考虑并行。这里的“并行”也不一定意味着多个 Agent,可能并行的是任务、会话、假设或模型。
| 模式 | 上下文与决策权 | 适合的任务 | 主要代价 |
|---|---|---|---|
| 单 Agent 串行 | 一个上下文,一个最终决策者 | 连续依赖、共享代码库、同一文档或需要统一风格的修改 | 延迟较高,长任务容易挤满上下文 |
| Claude Code subagents | 子 Agent 使用隔离上下文,主 Agent 单向接收结果 | 研究、测试、日志分析等高噪声且可独立验收的子任务 | 交接会丢失细节,主 Agent 需要定义返回格式 |
| Claude Code agent teams | 负责人协调独立会话,成员可直接通信并共享任务列表 | 并行代码审查、竞争性假设验证、多个独立方向的探索 | 协调和 token 成本高,不适合同文件编辑和强顺序任务 |
| Claude Code dynamic workflows | JavaScript 脚本持有扇出、循环和中间结果,运行后只返回汇总 | 大规模迁移、代码库审计、多来源交叉研究和可重跑流程 | 需要维护脚本,运行规模越大越要控制费用和失败重试 |
| Grok 4 Heavy | 一个模型在 test-time 并行探索多个假设再汇总 | 需要多种解法或更高可靠性的推理问题 | 不是独立工作区的 Agent 团队,外部难以控制每个假设的过程 |
| OpenRouter Fusion | 模型面板并行回答,analyst 比较共识、冲突、缺口和盲点,外层模型成稿 | 研究、批评和比较问题,错误代价高于额外调用成本的场景 | 多次 completion 带来延迟和费用,融合结果仍需来源核验 |
Claude Code 把“子任务隔离”和“成员协作”拆成了两种产品形态。subagents 在自己的上下文里工作,适合把大量搜索结果、测试输出或日志留在支线,只把摘要和产物引用带回主线。它们默认不互相交谈,因此主 Agent 必须在派发任务时写清目标、边界、工具和返回格式。agent teams 则是多个独立 Claude Code 会话组成的团队:一个会话负责分派和综合,成员可以直接发送消息、领取共享任务并互相挑战。这对并行审查或竞争性排查很有用,但同一个文件由多个成员同时修改,仍然会制造比它解决的问题更多的冲突。
Dynamic workflows 更像把编排本身写成程序。Claude Code 生成 JavaScript 脚本,由运行时批量启动 subagents,把扇出、依赖、循环检查和交叉复核放进脚本变量,而不是持续塞回主对话。这样适合逐文件迁移、全库审计和多来源研究,也可以保存后重跑。它解决的是规模和可重复性,不是让每个 Agent 拥有更大的决策权;脚本仍然需要定义停止条件、失败重试和最终验收。
Grok 4 Heavy 是另一条路线。xAI 将它描述为 parallel test-time compute:模型同时考虑多个假设,再汇总为一个回答。这里并没有多个拥有独立工作区、工具权限和长期状态的 Agent,更接近一次请求内的并行推理。它适合需要多种解法或希望降低单一路径出错概率的问题,但不能据此推导出“多 Agent 团队更强”。
OpenRouter Fusion 把多模型意见组织成一个显式流水线:Fusion Router 先让最多八个模型并行回答,再由 analyst 结构化比较共识、矛盾、覆盖缺口、独特见解和盲点,最后交回外层模型写答案。它的思想不是简单多数投票,而是保留分歧,让分析器说明哪些结论有共识、哪些只来自单个模型。这个模式适合研究和比较问题,却仍需要对关键来源重新核验。
OpenRouter 的其他路由能力要单独看:Body Builder 根据自然语言生成发往多个模型的请求,应用再并行执行它们;Auto Router 根据任务选择模型并配置回退。前者是请求生成器,后者是模型选择器,都不自动形成 Agent 之间的协作。把“多个模型被调用过”直接写成“多 Agent”,会掩盖真正的上下文和决策边界。
这些案例背后的共同点,是把不确定性放在可以隔离和复核的位置。子 Agent 返回证据、完成范围、未解决问题和产物引用,而不是替主线做不可逆决定;模型面板保留冲突和盲点,而不是只返回一个没有出处的平均答案;工作流把循环和停止条件写进代码,而不是靠主 Agent 临场记忆。并行化带来的收益必须覆盖额外 token、延迟和协调成本,否则一次并行工具调用就够了,不必再包装成多个会自行决策的 Agent。
我最后会用一张短清单做选择:任务是否能独立拆分?是否会修改同一份状态?结果能否单独验收?是否确实需要竞争性观点或多模型互校?额外的 token、延迟和协调成本,是否有评估结果证明值得?如果这些问题答不上来,优先使用单 Agent 串行执行。
暂时的结论
知识库决定系统能够找到什么,上下文工程决定模型下一步实际看到什么,工具决定它能以多大负担和怎样的边界行动。系统提示词提供遇到新情况时的判断倾向,模型适配层把这些要求交给不同模型,编排则决定上下文和决定由谁持有,又怎样交接。并行化的对象可以是任务、会话、假设或模型,名称相似不代表机制相同。
其中任何一处出了问题,都可能表现成“模型不够聪明”。换模型有时确实有效,但它也可能只是暂时遮住资料丢失、状态混乱或任务拆分错误。把这些层分开,至少能让下一次失败更容易定位,也更容易留下可以复用的修复。
参考资料
- Cognition:Don’t Build Multi-Agents
- Anthropic:Building Effective AI Agents
- Anthropic:How we built our multi-agent research system
- Claude Code:Create custom subagents
- Claude Code:Orchestrate teams of Claude Code sessions
- Claude Code:Orchestrate subagents at scale with dynamic workflows
- xAI:Grok 4
- OpenRouter:Fusion Router
- OpenRouter:Body Builder
- OpenRouter:Auto Router
- LangChain:Context Engineering
- Anthropic:Contextual Retrieval in AI Systems
- Tony Wu 等:ColPali: Efficient Document Retrieval with Vision Language Models
- Shi Yu 等:VisRAG: Vision-based Retrieval-augmented Generation on Multi-modality Documents
- Abul Ehtesham 等:Agentic Retrieval-Augmented Generation: A Survey on Agentic RAG
