第 22 章 · 通往大模型
用好大模型:Context、Harness 与 Agent
绝大多数人既不训练也不部署大模型,而是直接使用别人训练好的那个。 这一章把“用”这件事讲透:从 prompt engineering 到 context engineering, 再到 harness engineering。你会看到:提示词、RAG、工具调用、memory、MCP、Agent 并不是一堆散乱热词,而是在一步步给模型接上上下文、工具、状态、验证和工程护栏。
上一站(第 21 章)讲了工程与基建;本站讲你不训练、也不部署,只使用它时的系统方法——Prompt / Context / Harness / Agent。这也是这条主线的终点。
读完这一章,你会明白
- 为什么“用好模型”的重心正在从 prompt engineering → context engineering → harness engineering 迁移;
- 提示词(prompt)、上下文学习、few-shot、思维链(CoT)分别是什么;
- RAG、工具调用和 MCP 怎样把外部知识、工具说明和执行结果放进上下文;
- 为什么幻觉只能靠证据、工具、自检和系统兜底层层压低,不能靠一句提示词根除;
- 为什么很多评测会奖励“不会也猜”,以及机制可解释性怎样开始解剖模型内部电路;
- 提示、RAG、微调三招各自改什么、该在什么时候用;
- Agent 为什么会把“上下文管理”和“外部护栏”变成系统问题;
- 上下文工程为什么是 Agent 的工作记忆:动态压缩、外部 memory、经验手册、子 Agent 隔离上下文;
- Harness 工程怎样用执行循环、工具注册、上下文管理、状态存储、hooks 和评测接口,把模型变成稳定工作系统;
- 用大模型时该守的安全与常识底线;
- 为什么未来工程师的重点会从“写代码”转向“设计 Agent 的工作环境”。
从 Prompt 到 Context,再到 Harness
早期大家谈“用好大模型”,重点几乎都在 prompt engineering: 怎么写指令、怎么给例子、怎么让它一步步想。后来任务变长、工具变多、Agent 开始循环做事, 问题就不再只是“这一句话怎么写”,而是模型每一步应该看见什么——这就是 context engineering。再往后,模型要真的写代码、点浏览器、跑测试、维护状态、接受审查, 就需要一整套包在模型外面的工程外壳,也就是 harness engineering。
Prompt 是给模型一句好指令;Context 是给它一份好工作记忆;Harness 是给它一套能执行、能验证、能恢复的工作环境。
| 层级 | 核心问题 | 典型手段 | 失败时的表现 |
|---|---|---|---|
| Prompt engineering | 这次该怎么问? | 角色、目标、格式、few-shot、思维链 | 答非所问、格式不对、一步硬猜 |
| Context engineering | 这一步该给它看什么? | RAG、上下文压缩、memory、经验手册、子 Agent 摘要 | 上下文污染、忘记目标、看了也抓不住重点 |
| Harness engineering | 怎样让它长期稳定做事? | 文件系统、沙箱、工具执行、计划/交接、评测器、hooks、后台清理 | 做一半停下、无法复现、越改越乱、自评过度乐观 |
1. Prompt engineering:把话说清楚
模型参数固定了,你唯一能调的就是输入——也就是提示词(prompt)。 回忆第 17、19 章:模型会把你给的整段文字当上下文,一路影响它对“下一个词”的预测。所以 提示写得好,等于把模型往你要的方向“推”了一把。这件事有个正经名字叫 上下文学习(in-context learning):不改一个参数,只靠上下文就让模型临场“学会”做某件事。
- zero-shot 零样本直接下命令:“把下面这段翻译成英文”。
- few-shot 少样本先给几个示范再出题:“中文→英文:猫→cat;狗→dog;鸟→?”。给了例子,它照葫芦画瓢的成功率大增(这正是第 20 章说的“涌现”能力之一)。
- 思维链 CoT加一句“一步一步想”,让它把推理过程写出来。别小看这句话——复杂题目的正确率往往因此明显提高,因为它把“一步到位猜答案”变成了“顺着写、边写边推”。
第 19 章的 temperature / top-k / top-p 通常也开放给你调。要稳定、确定的答案 (如改代码、抽取信息),把温度调低;要发散、有创意的内容(如头脑风暴),把温度调高。 道理和第 19 章完全一样,只是换了个使用场景。
· 给角色和目标:“你是一位资深 C++ 工程师,帮我 review 下面这段代码的内存安全问题。”
· 说清输出格式:要表格就说“用表格”,要 JSON 就把字段列出来,别让它猜。
· 一次交代清上下文与约束:相关背景、必须遵守的限制,别挤牙膏。
· 复杂任务拆步骤:先让它“列个计划”,再逐步执行,比一句“全给我做完”靠谱得多。
· 给范例(few-shot):想要什么风格/格式,甩一两个例子最省事。
2. Context engineering:让模型看见该看的
Context engineering 不是“把所有东西都塞进去”,而是为这一步选择最该看的材料、工具结果、长期记忆和任务状态。 RAG、工具调用、memory、AGENTS.md、playbook、MCP,本质上都在回答同一个问题:这次调用模型时,上下文窗口里应该放什么?
2.1 RAG:把外部知识放进上下文
第 20 章说过大模型的两个硬伤:知识截止(不知道最新的事)和幻觉(没依据也敢编)。 最实用的解药叫 RAG(检索增强生成)——不重新训练,而是先查资料,再让它带着资料回答。
RAG:把“开卷考试”的资料先塞进上下文,模型据此回答,而不是凭记忆硬编。
它的核心机制,处处都是你学过的东西:
- 把你的文档切成小片段(chunk),每段几百字;
- 用专门的文本/句向量 embedding 模型把每段变成向量,存进“向量库”;
- 提问时,把问题也变成向量,用向量相似度(点积/余弦)找出最相关的几段;
- 把这几段和问题一起塞进提示,让模型“看着材料”回答。
把它想成从“闭卷”变“开卷”:闭卷时模型只能凭记忆(容易编),开卷时正确资料就摆在上下文里, 它只需照着答。这也解释了为什么片段不能太大——太大既降低检索精度,又可能撑爆上下文窗口(第 20 章)。
2.2 可靠回答:幻觉、证据与验证
RAG 是最实用的一招,但它只是一道防线。你可能会问:那今天最顶级的模型,是怎么把幻觉压到“少见且可控”的? 先接受一个前提——幻觉无法被彻底消除,只能层层拦截。根因在第 20 章说过:模型本质是概率续写器, 在它内部,“我知道”和“我编一个通顺的”并没有一条天然的分界线。所以顶级模型不追求“消灭幻觉”,而是在从训练到产品的每个环节都设一道关卡,像漏斗一样逐层过滤。
OpenAI 等作者的论文 Why Language Models Hallucinate 把这个问题说得很清楚:幻觉不只是“模型笨”,也是训练和评测制度在奖励它猜。 预训练只教它“什么文本像真的”,却很少系统告诉它“哪些相似说法是假的”;而很多排行榜又把“不知道”直接判 0 分。 于是模型在不确定时,猜一个答案往往比诚实弃权更像“好考生”。
对抗幻觉是组合拳而非单一银弹:从训练、推理、输出后到系统层,四道防线层层收窄,把幻觉率一级级压低。
训练阶段:让它倾向于“诚实”
- RLHF 对齐(第 20 章):人类反馈里明确惩罚“自信地胡说”、奖励“不确定就坦白”,让模型学会校准语气——没把握时说“可能 / 据我所知”,而不是一口咬定。
- 教它说“我不知道”:很多幻觉来自“被问到知识边界外还硬答”。训练时特意加入“该拒答 / 该表示不确定”的样本,让弃权成为一个合法选项,而不是硬憋一个答案。
- 事实性专项偏好:用“有据可查 vs 凭空编造”的对比数据做偏好训练,把说真话的倾向直接拉高。
推理阶段:给它外挂和草稿纸
这一阶段是效果最立竿见影的,核心思路是:别让它只靠“脑内记忆”硬答,而是把答案锚定到外部的真实证据上。
- RAG 检索增强(上一节):回答前先捞真实资料,让它照着材料答。这是性价比最高、最主流的一招。
- 工具调用(见 下文 §2.4):算数用计算器、查实时信息调 API、跑代码验证——把“需要精确”的事外包给确定性工具,不靠脑补。
- 先推理再答(思维链 / reasoning 模型):像先在草稿纸上分步推演再下结论,能显著减少“一步硬猜”导致的推理型幻觉。
- 要求给出处:让答案附引用。一旦被逼着给来源,模型编造的空间就小了,用户也能顺着链接核对。
输出后:自检与交叉验证
- 多次采样自检(self-consistency):同一问题采样多个答案,互相不一致的地方往往就是模型没把握之处,取多数或触发复查。
- 让另一个模型当“事实核查员”:用一个校验模型逐句核对“生成内容 vs 检索到的证据”是否吻合(RAG 里叫 groundedness / 忠实度检查),对不上就打回重来。
- 系统兜底:检索不到证据、置信度过低时,产品宁可回一句“无法确认”也不硬答;医疗、法律、金融等高风险场景则要求人工复核 + 显示信息来源。
MaxProof 这类数学证明系统说明了一件事:难题不一定要押宝“模型一次答对”。 更稳的做法是把一次回答拆成一个小型搜索系统:先生成多条候选路线,再让验证器挑错, 把有希望的路线交给修复器局部补洞或整体重写,最后用排序/投票选出一个提交答案。 这和 Agent 做事很像——大模型不只是“说出答案”,而是在一个生成 → 验证 → 修复 → 选择的循环里逐步逼近答案。
复杂任务的可靠性来自系统结构:多候选扩大搜索空间,验证器压低明显错误,修复器把“差一点”的答案救回来,选择器负责最后提交。
对抗幻觉靠的是组合拳:训练时让它倾向诚实、会拒答 → 推理时用 RAG / 工具 / 推理链把答案锚在真实证据上 → 输出后自检和交叉验证 → 系统层加护栏和人工兜底。 对普通开发者最够用的三样是:RAG + 工具调用 + 要求给出处。
评测也会塑造模型:别把“不知道”判成错
很多事实没有规律可推,比如某个人的生日、冷门论文标题、一个小项目的真实配置。 训练集中没见过,模型就不能靠“更聪明”凭空算出来。此时最可靠的行为应该是承认不确定, 或者要求检索/工具/更多上下文。但如果评测只看最终答案对不对,问题就来了:
| 模型不确定时 | 0/1 评分下的结果 | 学到的倾向 |
|---|---|---|
| 说“不知道” | 通常直接 0 分 | 诚实没有收益 |
| 猜一个看似合理的答案 | 错了 0 分,但猜中就 1 分 | 不会也要试着答 |
| 说明证据不足并请求检索 | 许多榜单仍不给分 | 谨慎反而吃亏 |
这就是论文说的“好考生”效应:在许多 benchmark 里,猜测有期望收益,弃权没有。要减少幻觉,主流评测也要给合理的不确定表达、证据不足和请求澄清留分。
所以“抗幻觉”不只是模型公司的训练技巧,也是整个生态的评分问题。 如果主流榜单继续奖励硬猜,模型就会被优化成看起来什么都敢答;如果榜单奖励校准、引用证据和合理弃权, 模型才会更像一个可信助手。
可解释性:不只看输出,还看内部电路
另一条正在发展的路线,是机制可解释性:不只问“模型答了什么”,还追问“它内部为什么这么答”。 Anthropic 2025 年的 On the Biology of a Large Language Model 用 归因图(attribution graph) 去追踪 Claude 3.5 Haiku 的内部计算: 节点是被激活的概念特征,边表示这些特征怎样影响后面的特征和最终输出。
归因图像一张粗略的“神经通路图”:先提出内部机制假设,再通过抑制或替换某些特征验证它是否真的影响输出。
这类工作已经能看到一些很具体的内部过程:多步推理里先出现中间事实,写押韵诗前会预先激活候选押韵词, 拒答时会把具体危险线索汇入更抽象的有害请求特征,幻觉时也可能是“应该补一个看似合理答案”的路径压过了“我知道/不知道”的信号。 它还远不是完整解剖,但方向很重要:可信模型不只要输出正确,还要逐步变得可检查、可干预、可追责。
2.3 提示、RAG 还是微调:三招该用哪个?
讲完提示和 RAG,一个很自然的问题冒出来了:要让模型在我的场景里表现更好,到底是改提示、接 RAG, 还是干脆微调(fine-tune,拿你的数据接着训一小段,属于第 20 章后训练的范畴)? 它们不是三选一的对立关系,而是成本从低到高、按需叠加的三层台阶。
| 手段 | 改的是什么 | 最适合解决 | 成本 |
|---|---|---|---|
| 提示工程 | 只改输入(上下文) | 让它听懂任务、按格式输出;通用能力它本来就有 | 最低,改一句话即可 |
| RAG | 输入 + 一个外挂知识库 | 补上最新的、私有的知识;治幻觉、防知识截止 | 中,要搭检索/向量库 |
| 微调 | 模型参数本身 | 固化一种稳定的风格/口吻/领域习惯,或压缩提示长度 | 最高,要数据、算力和训练 |
先用提示,不行再上 RAG,最后才考虑微调。 大多数问题(“它不按我要的格式来”“它没理解任务”)其实改提示就解决了,根本不用动模型。 如果问题是“它不知道某些事实”(公司内部文档、今天的新闻),那是知识缺口,RAG 最对症。 只有当问题是“它知道、但就是不肯照我要的风格/领域习惯稳定地做”,而且提示怎么调都不够,才值得为微调付出数据和算力的代价。
很多人一上来就想“用我的文档微调一个模型”。但微调更擅长教风格和形式, 往里灌事实既低效又容易带来遗忘和新的幻觉——而且知识一更新就得重训。 要“记住并用上一批资料”,RAG 通常才是更省、更准、更好维护的选择。
2.4 工具调用:把工具说明和结果放进上下文
大模型不擅长精确计算,也查不到实时数据(第 20 章)。那就别让它硬算——让它调用外部工具。 这套机制最早叫 function calling(函数调用):
- 你把可用的工具清单(计算器、搜索、日历……)连同问题一起给模型;
- 模型判断该用哪个工具、要传什么参数,把这个“意图”返回;
- 由程序真正执行工具、拿到结果,再喂回模型;
- 模型结合工具结果,给出最终回答。
于是“3897 × 421 等于几”“今天北京天气”这类它本来做不好的事,就交给计算器和天气 API,它负责理解、调度、总结。 模型从“一张嘴”升级成了“会用工具的手”。
2.5 Agent:从回答问题到循环做事
当模型从“一次回答”升级成循环做事的 Agent,context engineering 就不再只是“塞几段资料”, 而是变成工作记忆问题:每一步该看什么、工具结果怎么回流、哪些探索噪声该隔离出去。
当一个系统能感知环境 → 思考决策 → 执行动作,还能看着结果继续下一步,它就成了一个 Agent(智能体)。如果负责“思考决策”的大脑是一个大模型,那它就是我们现在常说的 AI Agent。
Agent = 大模型当“大脑”,加上感知与执行的“手脚”,并能循环多步,直到把任务办成。
你正在用的这个编程助手,本质就是一个 Agent:它读你的需求(感知)、决定改哪个文件、跑什么命令(思考), 真正去编辑和执行(执行),再根据报错继续修(循环)。RAG 和工具调用,都是喂给这个“大脑”的能力。
2.6 Agent 的工作记忆:动态压缩、memory 与子 Agent
到这里,你可能会觉得 Agent 的关键是“会不会调用工具”。其实还差一块更底层的东西: 上下文工程(context engineering)。它关心的不是“提示词怎么写得漂亮”, 而是每一次调用模型时,到底该把哪些信息放进上下文窗口。
很多人以为窗口越长越好,把日志、网页、工具输出、历史对话全塞进去就万事大吉。但模型的注意力不是无限的。 上下文越长,模型越容易“看见了但没抓住重点”,这类现象常被称为 context rot: 不是超过某条线突然失效,而是随着 token 增加,检索细节、保持目标和长距离推理的精度逐渐下降。 所以上下文工程的目标是:用最少的高信号 token,换最大的任务成功率。
Agent 不是把所有历史都塞给模型,而是每一步都重新组织一份“刚好够用”的上下文。
动态压缩:保留状态,丢掉噪声
长任务做着做着,对话历史、工具输出和中间尝试会迅速膨胀。最直接的办法叫 compaction(上下文压缩):当窗口接近上限时,把历史压缩成一份高保真状态摘要, 再带着这份摘要开启新的上下文窗口继续工作。
好的压缩不是“越短越好”,而是能让 Agent 接着干活。它应该保留:
| 该保留 | 为什么重要 | 常可丢掉 |
|---|---|---|
| 当前目标与验收口径 | 防止后续动作偏离任务 | 寒暄、重复确认 |
| 关键决策与约束 | 避免反复推翻已经确定的方向 | 无关分支讨论 |
| 已完成/未完成清单 | 让 Agent 知道下一步从哪里接 | 过期 TODO、已解决报错全文 |
| 重要文件、接口、命令结果 | 保留可复现线索和边界条件 | 大段原始日志、完整工具输出 |
| 失败原因与排除路径 | 防止同一个坑重复踩 | 中间失败的冗余堆栈 |
这里最容易犯的错是摘要化过猛:把“为什么这么做”“哪些尝试失败过”“哪个文件刚改过”都压没了。 Anthropic 的工程经验里,压缩更像给接班人写交接单:保留架构决策、未解 bug、实现细节和最近访问文件, 而不是把历史改写成一段漂亮短文。
Memory:把长期经验放在窗口外
memory 是另一种思路:别把所有信息一直留在上下文里,而是让 Agent 把关键状态写到外部,
需要时再读回来。它可以很简单,比如一个 TODO.md、NOTES.md、项目记忆文件,
也可以是数据库、向量库或专门的记忆服务。
有价值的 memory 更像工作手册:记录稳定事实(项目结构、接口约定)、过程状态(做到哪一步、还差什么)、 失败经验(某命令会超时、某参数不能这么传)、偏好与规范(输出风格、验证命令)。 它不应该存一切原文,而应该存“以后真的会用到的压缩知识”。
真正难的是什么时候写、什么时候读。写得太少,下一轮忘事;写得太多,检索回来又污染上下文。 一个实用做法是把 memory 分层:
- 工作记忆:当前任务的 TODO、最近改动、下一步动作,更新频繁,生命周期短;
- 项目记忆:仓库结构、常用命令、验证脚本、部署规则,比较稳定;
- 经验手册:反复踩坑后的规则,如“改章节后跑锚点检查”“工具输出太长先摘要再读”。
可演化 playbook:从执行反馈里长经验
ACE 论文把上下文看成一份会演化的 playbook,而不是一段每次整体重写的 prompt。 它把过程拆成三种角色:
- Generator:拿当前上下文去做任务,暴露成功路径和失败轨迹;
- Reflector:根据成功/失败提炼经验,指出哪些策略有用、哪些误导;
- Curator:把这些经验整理成结构化条目,合并回上下文手册。
关键是它用增量条目而不是整段重写。每条经验都像一颗小积木,有自己的编号、内容和“有用/有害”计数。 这样能避免两个常见问题:
- brevity bias:为了摘要得短,把领域技巧、工具细节和失败模式全删掉;
- context collapse:每轮都重写整份上下文,越写越像空泛总结,细节逐轮流失。
- id: tool-calendar-timezone
helpful: 7
harmful: 0
note: 调日历工具前先确认 timezone;缺省时不要猜,先查用户资料或请求澄清。
- id: codebase-anchor-check
helpful: 12
harmful: 1
note: 修改电子书 h2/h3 标题后,必须跑 check_anchors.py;不要手算 slug。
这类条目比“以后注意工具参数”更有用,因为它具体、可检索、能被计数淘汰。Agent 下一次遇到类似任务时, 只需要取回相关条目,不必重读全部历史。
子 Agent:把探索噪声隔离出去
还有一种重要技巧是隔离上下文。复杂研究或大代码库排查时,一个主 Agent 如果亲自读完所有文件、日志和网页, 很快会把自己的上下文塞满。更稳的做法是让子 Agent 在独立窗口里深挖一个局部问题,最后只返回一份高密度摘要。
| 手段 | 解决什么 | 适合场景 |
|---|---|---|
| 动态压缩 | 长对话快满时保留连续性 | 持续编码、长时间调试、连续研究 |
| 外部 memory | 把稳定经验放到窗口外,按需取回 | 项目长期协作、反复执行的工作流 |
| 可演化 playbook | 从执行反馈中沉淀策略,避免每次从零开始 | Agent 产品、领域任务、工具链使用 |
| 子 Agent | 隔离大量探索噪声,主 Agent 只读结论 | 并行研究、大仓库定位、复杂信息搜集 |
所以,Agent 的“聪明”不只来自模型参数,还来自这套上下文操作系统: 该压缩时压缩,该外存时外存,该检索时检索,该隔离时隔离。 会管理上下文的 Agent,才能在很长的任务里保持方向感。
2.7 MCP:工具和数据源的标准上下文接口
Agent 要调用各种外部工具和数据源,如果每接一个都要定制一套对接,就太乱了。 MCP 模型上下文协议由 Anthropic 提出,给“Agent ↔ 外部工具/数据源”定义了一套标准插头: 工具说明、资源、数据和调用结果都能用统一方式进入上下文。有了它,任何遵守协议的工具都能被任何 Agent 即插即用, 不用一个个定制(可以类比 USB 之于外设)。
A2A 也曾试图规范 Agent 与 Agent 之间怎么通信、协作,但这条线还不如 MCP 稳定,本章只点到这里,不展开成主线。 你只需要记住一个方向:大模型正从“一个聊天框”,长成一个能连接工具、数据源和专职 Agent 的工作生态。
3. Harness engineering:让模型可靠做事
如果说上下文工程解决的是“模型每一步看什么”,那 Harness 工程(harness engineering) 解决的是“模型怎么在真实环境里长期、安全、可恢复地做事”。LangChain 有个很干脆的说法: Agent = Model + Harness。模型负责智能;Harness 负责把这种智能接到状态、工具、文件、沙箱、评测和控制流上。
原始模型只能接收输入、吐出文本。它不会天然保存状态,不会真的执行代码,不会访问实时世界,也不会自动知道什么时候该停。 Harness 就是模型外面的工程系统:给它文件系统保存中间产物,给它工具和浏览器操作世界,给它沙箱限制风险, 给它测试和评测器判断好坏,给它 hooks/middleware 做确定性检查,给它交接文档跨越上下文重置。
Harness 把模型包进一个可执行系统:状态能落盘,工具能调用,风险有边界,结果能验证,长任务能交接。
还可以把 Harness 理解成一座约束金字塔。越往下越便宜、越普及,但越依赖模型自己记住规则; 越往上越少见、成本越高,却越像外部系统给模型加的硬护栏。
Harness 的约束从下到上越来越硬:prompt 和 context 让模型“记住规则”,独立 Agent 负责复核,hook / sandbox / CI 则用程序直接拦截高风险行为。
Prompt 和 context 很有用,但它们本质上仍是软约束:上下文一长,规则会被稀释,模型可能忘记早先的限制。 所以关键边界不能只押在模型记忆上。独立 reviewer / tester / evaluator 用另一个上下文检查结果, 能减少模型既当运动员又当裁判的问题;hooks、权限、沙箱和 CI 则是不靠模型“记得”的最后防线。
注意,hook 也不是神谕。它不会因为注意力涣散而忘规则,但它可能写漏、误杀或接错位置,所以仍然要被测试和维护。 真正可靠的 Harness,是把软规则、独立审查和硬拦截叠在一起。
3.1 Harness 的六个部件
一篇 2026 年的 Agent Harness survey 把这层工程外壳写成一个很清楚的六元组: H = (E, T, C, S, L, V)。它的意思不是让你背公式,而是提醒你: Agent 的可靠性不只取决于模型多强,还取决于模型外面这六件事有没有被设计好。
| 字母 | 部件 | 它负责什么 | 坏掉时的表现 |
|---|---|---|---|
| E | Execution loop 执行循环 | 观察环境、调用模型、执行动作、读回结果、进入下一步 | 做一步就停、失败不重试、状态和行动脱节 |
| T | Tool registry 工具注册表 | 告诉模型有哪些工具、参数怎么填、权限和返回值是什么 | 工具太多选错、参数乱填、危险工具暴露给错误任务 |
| C | Context manager 上下文管理器 | 决定每一步给模型看哪些需求、文件、检索结果、工具回执和历史摘要 | 关键事实被冲淡、旧错误反复回流、长上下文里抓不住重点 |
| S | State store 状态存储 | 把计划、进度、文件、记忆、checkpoint 和交接产物放在窗口外 | 上下文一重置就失忆,长任务无法恢复或复现 |
| L | Lifecycle hooks 生命周期钩子 | 在开始、工具调用前后、提交前、结束时做确定性检查和自动维护 | 危险命令没人拦、格式没人查、临时产物没人清理 |
| V | Evaluation interface 验证接口 | 把测试、CI、截图、日志、reviewer、rubric evaluator 接进反馈回路 | 模型自己给自己打高分,结果看似完成但不可用 |
这也是为什么“换一个更强模型”不总能解决 Agent 的问题。模型像发动机,但执行循环、工具、上下文、状态、hook 和验证接口决定了它能不能把能力稳定地传到真实任务上。很多所谓“模型不行”,其实是工具接口混乱、上下文污染、 没有状态恢复,或者没有外部验证。
这篇文章目前还是 preprint,而且引用了不少产业报告和工程博客。它最有价值的地方不是某个单点数字, 而是把分散的经验归纳成一个可检查清单:一个 Agent 系统如果缺了执行、工具、上下文、状态、hook 或验证中的任何一层, 长任务可靠性就会很快掉下来。
3.2 长任务 Harness:Planner、Generator、Evaluator
Anthropic 在长时间应用开发实验里,把单个“全能 Agent”拆成三个角色:
- Planner:把一句产品需求扩展成高层产品规格和交付清单,但避免过早写死细节实现;
- Generator:按 sprint 一次实现一个功能,把工作落到代码、文件和版本控制里;
- Evaluator:像用户一样点应用、跑测试、看数据库/API 状态,按明确标准给出失败原因。
这个设计的关键不是“多几个模型一起聊天”,而是职责隔离。做事的 Agent 不负责给自己打高分; 评估者用独立上下文、明确标准和真实环境反馈来挑错。长任务中间如果上下文变脏,可以直接重置 Agent, 通过结构化 handoff artifact 把当前状态和下一步交给新 Agent,而不是让同一个 Agent 背着越来越重的历史继续硬撑。
多 Agent 协作在软件工程里还有一个更硬的版本。2026 年论文
Effective Strategies for Asynchronous Software Engineering Agents 提出
CAID(Centralized Asynchronous Isolated Delegation):一个中央 manager 先把任务拆成带依赖的子任务,
多个 engineer Agent 在各自隔离的 git worktree 里并行实现,完成后用 git commit / git merge
回到主线,并用可执行测试验证整合结果。它的重点不是“大家在同一个聊天里讨论”,而是把人类软件团队早就成熟的
branch-and-merge 搬给 Agent 用。
| 协作问题 | CAID 的做法 | 为什么重要 |
|---|---|---|
| 任务怎么拆? | Manager 先建依赖图,只分配依赖已满足的任务 | 避免两个 Agent 各做各的,最后拼不起来 |
| 并行怎么不互相踩? | 每个 engineer 使用独立 worktree,不要共用同一份工作区 | 指令里的“别改同一文件”是软约束,隔离 workspace 才是硬边界 |
| 进度怎么回主线? | 完成后提交 commit,再显式 merge 到 main | 冲突会在 merge 时暴露,不会悄悄污染最终代码 |
| 质量怎么判断? | Engineer 自测,manager 整合,测试和错误日志进入下一轮 | 把“我觉得做好了”变成可执行验证 |
这篇论文的实验也给了一个很实用的提醒:多 Agent 不是越多越好。并行度要匹配任务本身的模块化程度和 manager 的调度能力; 人数太多、切得太碎,反而会增加合并冲突、沟通成本和验证成本。对长代码任务来说,正确问题不是“要不要多个 Agent”, 而是哪些任务能隔离并行,哪些依赖必须先合并验证。
3.3 Harness 里的确定性护栏
Harness 还要处理模型不擅长但工程系统很擅长的事:确定性约束。比如 OpenAI 的 Harness Engineering 讨论里, 他们让 Codex 从空仓库开始生成应用逻辑、测试、CI、文档、可观测性和内部工具;人的主要工作从“写代码”转成 设计环境、明确意图、构建反馈回路。这不是把一个巨大说明书塞进上下文,而是把知识、约束和反馈做成 机器可读、可执行、可维护的仓库结构。
一个关键经验是:AGENTS.md 不该是百科全书,而该是地图。真正的信息放进结构化的 docs/、
架构文档、执行计划、产品规格、生成的 schema、参考资料和质量评分里;简短入口告诉 Agent 下一步该去哪查。
这样既避免上下文爆炸,又让知识有所有权、可交叉链接、可被 lint/CI 检查新鲜度。
另一条经验是让应用本身对 Agent 可读:让 Codex 能按 worktree 启动独立实例,用浏览器协议查看 DOM 和截图, 用日志/指标/追踪回答“启动是否低于 800ms”“关键用户旅程是否超过 2 秒”。当 UI、日志和指标都能被 Agent 读取, 它才有能力复现问题、验证修复,而不是只靠人类 QA 口头描述。
最后是熵管理。完全由 Agent 高速产出的代码会复制仓库里已有模式,包括坏模式。OpenAI 的做法是把“黄金原则”编码成 架构约束、结构测试、自定义 lint 和后台 Codex 任务,定期扫描偏差、更新质量评级、发起重构 PR。可以把它想成给 Agent 生成的代码加垃圾回收:小问题定期扫掉,技术债不要等积成山再一次性还。
| Harness 组件 | 它给模型补什么 | 例子 |
|---|---|---|
| 文件系统 / Git | 持久状态、版本、回滚点 | 代码、计划、handoff、checkpoint |
| 沙箱 / 权限 | 可控执行边界 | 跑代码、装依赖、浏览网页但限制危险操作 |
| 测试 / 评测器 | 外部反馈 | 单测、Playwright、lint、rubric evaluator |
| 编排逻辑 | 流程和角色分工 | Planner/Generator/Evaluator、子 Agent、重试 |
| 可观测性 | 让 Agent 自己看见运行状态 | DOM 快照、截图、日志、指标、trace |
| Hooks / Middleware | 确定性检查和自动维护 | 压缩、继续执行、格式检查、后台清理 PR |
所以这条演进线可以这样记:Prompt 让模型听懂你;Context 让模型看见该看的;Harness 让模型在真实系统里可靠地做完。
4. 用它,但别全信它
· 关键事实要核对:它会一本正经地编(第 20 章的幻觉),涉及数字、引用、法律医疗等,务必自己复核。
· 小心提示注入:让它读的网页/文档里可能藏着“骗它执行的指令”,给 Agent 授予真实权限(删文件、付款)时要谨慎。
· 注意隐私:别把敏感信息随手贴进第三方模型。
· 它没有立场也没有真正的“懂”:它在做极其复杂的模式延续,语气再笃定也不等于正确。
把这些记在心里,你就能既享受它的强大,又不被它的“自信”带偏。理解原理的人,用起工具来总是更稳、更有分寸。
小结
- 提示词是你唯一的旋钮:zero-shot 直接问、few-shot 给例子、CoT 让它一步步想。
- RAG = 先检索再回答,用词嵌入+相似度找资料,把“闭卷”变“开卷”,治幻觉与知识截止。
- 对抗幻觉是组合拳:训练时让它倾向诚实/会拒答,推理时用 RAG+工具+推理链锚定证据,输出后自检交叉验证,系统层加护栏与人工兜底;幻觉只能压低、无法根除。
- 复杂任务越来越像搜索系统:生成多个候选,用验证器挑错,用修复器补洞或重写,最后排序/投票选答案。
- 幻觉也来自评测激励:如果“不知道”永远 0 分、猜测有机会得分,模型就会被塑造成爱猜的考生;机制可解释性则尝试用归因图追踪内部特征和电路。
- 提示 / RAG / 微调是成本递增的三层:先改提示,缺知识上 RAG,只有要固化风格才微调——别拿微调补知识。
- function calling 让模型调用计算器/搜索/API,补上它不会算、查不到的短板。
- Agent = 大模型当大脑 + 感知与执行 + 多步循环;上下文工程负责管理它的工作记忆:压缩历史、写外部 memory、维护经验手册、用子 Agent 隔离噪声;MCP 则把工具和数据源变成标准上下文接口。
- Harness 工程把模型包进工作系统:执行循环负责多步推进,工具注册表治理可用能力,上下文管理器决定每步看什么,状态存储保存进度,hooks 提供硬拦截,测试/评测器提供外部反馈;多 Agent 协作还要靠依赖图、隔离工作区、显式 merge 和测试验证来避免互相踩踏。
- 始终核对关键事实、防提示注入、护隐私——理解原理才能用得稳。
动手与思考
问题 1:few-shot 和 CoT 都不改模型参数,为什么还能提升表现?
因为它们改变的是上下文。模型预测下一个词时会被整段输入影响(上下文学习):给了示范,它照着模仿;让它“一步步想”,它就把推理写出来、逐步推进,而不是一步硬猜。参数没变,但输入把它推向了更好的轨道。
问题 2:RAG 为什么能缓解幻觉和知识截止?它用到了哪些前面的知识?
问题 3:为什么要让大模型“调用工具”,而不是让它自己算、自己查?
因为它本质是概率文本预测器,不擅长精确计算,也没有实时数据。把算术交给计算器、把实时信息交给搜索/API,让模型负责理解意图、调度工具、总结结果,整体又准又可靠。
从一个神经元到大模型的原理主干,到这里就全通了(强化学习那套学习范式,我们已在第 12 章讲过)。 接下来第六部分 · 代码实战对着三份 C++ 程序把全书对一遍号: 第 23 章 MNIST, 第 24 章 字符级语言模型, 第 25 章 井字棋 Q-learning。
下一章进入代码实战:第 23 章 先把 MNIST 程序逐行对上号。