本节摘要:一个有能力的模型,不够。可靠的 Agent 需要一个工作台(workbench)——指令、状态、范围、反馈、验证、审查、交接。把这些剥掉,即便是前沿模型产出的工作也不安全到可交付。诊断很扎心:你把一个前沿模型丢进真实仓库,让它「加输入校验」,它打开四个文件、写出看起来合理的代码、宣布成功、停下。你跑测试——两个失败;第三个被改的文件和校验毫无关系;没有任何记录说明 Agent 假设了什么、先试了什么、还剩什么没做。模型没在 Python 上犯错,它在**「工作」上犯错——它不知道什么算「完成」、哪里允许写、哪些测试是权威的、下一次会话该怎么接手。这不是模型 bug,是工作台 bug**。本节是第 15 章压轴主题(工作台工程,第 31~42 节)的开篇,定义工作台的七个面(Instructions/State/Scope/Feedback/Verification/Review/Handoff),并给出一个关键洞见:工作台独立于模型——你可以换模型保留这些面,但不能换掉这些面还指望保留可靠性。更重要的是,本节把这七面还原到底层的分布式系统八原语(函数/工人/触发器/运行时/HTTP-RPC/队列/会话持久化/授权策略)——所有流行的工作台/外壳(harness)模式(Ralph Loop、PEV、OAP、Guides-Sensors、渐进压缩、MCP、沙箱)都只是这些老原语换了新名字。 receipts 也很硬:Terminal Bench 2.0 同模型只换外壳就从 30 名外冲到第 5;Vercel 删掉 80% 工具,成功率从 80% 跳到 100%;Harvey 法律 Agent 单靠外壳优化准确率翻倍;88% 企业 AI Agent 项目到不了生产,失败聚集在运行时而非推理。读完本节,你应能用「提示 vs 工作台」「框架 vs 工作台」两道区分,把厂商 UX 描述翻译回工程原语。
对应原课程:Phase 14 · Lesson 31 ·
agent-workbench-why-models-fail(原英文phases/14-agent-engineering/31-agent-workbench-why-models-fail/docs/en.md)。前置:第 01 节(Agent 循环)、第 26 节(失败模式)。
阅读完本节,你应当能够:
你把一个前沿模型丢进真实仓库,让它加输入校验。它打开四个文件,写出看起来合理的代码,宣布成功,停下。你跑测试——两个失败。第三个被改的文件和校验毫无关系。没有任何记录说明 Agent 假设了什么、先试了什么、还剩什么没做。
模型没在 Python 上犯错。它在**「工作」上**犯错。它不知道什么算「完成」、哪里允许写、哪些测试是权威的、下一次会话该怎么接手。
这不是模型 bug,是工作台 bug。模型周围的面,缺了把「一次性生成」变成「可靠、可续跑的工程」的那些部分。
循环闭合在状态文件上,而非聊天历史。聊天是易失的;仓库才是真相之源(system of record)。
工作台是任务期间包裹模型的运行环境。它有七个面:
| 面 | 承载什么 | 缺失时的失败 |
|---|---|---|
| 指令(Instructions) | 启动规则、禁用动作、完成定义 | Agent 猜「交付」是什么意思 |
| 状态(State) | 当前任务、动过的文件、阻塞、下一步 | 每次会话从零重启 |
| 范围(Scope) | 允许/禁用文件、验收标准 | 编辑泄漏进无关代码 |
| 反馈(Feedback) | 真实命令输出捕获进循环 | Agent 在 400 上宣布成功 |
| 验证(Verification) | 测试、lint、冒烟、范围检查 | 「看起来不错」进了 main |
| 审查(Review) | 用不同角色的第二遍 | 建造者给自己批作业 |
| 交接(Handoff) | 改了什么、为什么、剩什么 | 下次会话重新发现一切 |
工作台独立于模型。你可以换模型、保留这些面;但你不能换掉这些面、还指望保留可靠性。
提示告诉模型「这一轮你要什么」。工作台告诉模型「跨轮、跨会话如何做工作」。大多数 Agent 失败故事,是穿着提示工程外衣的工作台失败。
框架给你运行时(LangGraph、AutoGen、Agents SDK)。工作台给 Agent 一个在运行时里面干活的地方。两者都需要。这个小专题(第 31~42 节)讲的是第二个。
当下关于「外壳工程(harness engineering)」的写作很多。Addy Osmani、OpenAI、Anthropic、LangChain、Martin Fowler、MongoDB、HumanLayer、Augment Code、Thoughtworks 等都在谈。它们对外壳的边界、范围、词汇各执一词。我们不必选边——七个面是 UX 层;每个工作台底下,都是同一套撑起任何可靠后端的分布式系统原语。
暂时剥掉 Agent 标签。一次 Agent 运行,是跨越时间、进程、机器的计算。要让它可靠,你需要和生产系统一样的原语:
| 原语 | 是什么 | 对 Agent 承载什么 |
|---|---|---|
| 函数(Function) | 类型化处理器,尽量纯,拥有自己的输入输出 | 工具调用、规则检查、验证步骤、模型调用 |
| 工人(Worker) | 拥有一个或多个函数与生命周期的长寿命进程 | 建造者、审查者、验证器、一个 MCP 服务器 |
| 触发器(Trigger) | 调用函数的事件源 | Agent 循环 tick、HTTP 请求、队列消息、cron、文件变更、钩子 |
| 运行时(Runtime) | 决定什么在哪跑、带什么超时与资源的边界 | Claude Code 的进程、LangGraph 的运行时、worker 容器 |
| HTTP/RPC | 调用方与工人之间的线 | 工具调用协议、MCP 请求、模型 API |
| 队列(Queue) | 触发器与工人间的持久缓冲;背压、重试、幂等 | 任务板、反馈日志、审查收件箱 |
| 会话持久化(Session persistence) | 跨崩溃、重启、换模型存活的状态 | agent_state.json、检查点、KV 存储、仓库本身 |
| 授权策略(Authorization policy) | 谁能以什么范围调用什么函数 | 允许/禁用文件、审批边界、MCP 能力列表 |
现在把七个工作台面映射到这些原语:
AGENTS.md)是挂在运行时启动上的策略。Agent 循环本身是一个工人——消费事件(用户消息、工具结果、定时 tick)、调用函数(模型、再模型选的工具)、写记录(状态、反馈)、发触发器(验证、审查、交接)。毫无神秘;和作业处理器同形。
每个流行的外壳模式都归约到这八个原语。翻译表:
| 厂商/社区模式 | 它实际是什么 |
|---|---|
| Ralph Loop(Claude Code、Codex、agentic_harness 书)——Agent 想提前停时,把原始意图重新注入干净上下文 | 一个用干净上下文重新入队任务的触发器;会话持久化把目标带下去 |
| Plan/Execute/Verify(PEV) | 三个工人,各一个角色,经状态与阶段间队列通信 |
| 外壳-计算分离(OpenAI Agents SDK,2026-04)——分控制面与执行面 | 重述控制面/数据面,比 Agent 标签早几十年 |
| Open Agent Passport(OAP,2026-03)——执行前按声明式策略签名审计每次工具调用 | 由前置动作工人强制的授权策略,带签名审计队列 |
| Guides 与 Sensors(Birgitta Böckeler / Thoughtworks)——前馈规则 + 反馈可观测性 | 授权策略 + 验证函数 + 可观测性追踪 |
| 渐进压缩,5 阶段(Claude Code 逆向,2026-04) | 一个类 cron 跑在会话持久化上的状态管理工人,保持其在预算内 |
| 钩子/中间件(LangChain、Claude Code)——拦截模型与工具调用 | 包在运行时调用路径周围的触发器 + 函数 |
| 技能即 Markdown 带渐进披露(Anthropic、Flue) | 一个函数注册表,函数元数据按需即时加载进上下文 |
| 沙箱 Agent(Codex、Sandcastle、Vercel Sandbox) | 计算面:带隔离文件系统、网络、生命周期的运行时 |
| MCP 服务器 | 经稳定 RPC 暴露函数的工人,能力列表即授权 |
表里每一项,都是 Agent 社区到达了一个在分布式系统里早有名字的原语、然后给它起了个新名字。做营销标签有用;做工程词汇没用。
「外壳胜过模型」的主张,现在有数字撑腰。值得知道,因为它们也是对「等个更聪明的模型就行」唯一诚实的反驳:
要点不是「外壳永远赢」。模型确实会随时间吸收外壳技巧。要点是:今天,承重的工程在模型周围,不在模型内部;而承载那分量的原语,是每个生产系统一直都需要的那些。
⚠️ 厂商写作停在哪里:不必客气地说——LangChain 的《Anatomy》枚举了十一组件,却不命名队列、工人作为部署单元、触发器语义、会话持久化为独立关注点、授权策略,把外壳当成你配置的对象而非你部署的系统。Addy Osmani 落地了
Agent = Model + Harness与棘轮模式,却没说外壳用什么造的。Anthropic 与 OpenAI 在面上最深,但留在自家运行时内。这些都是在写一个已存在系统的 UX 描述;而我们写的是系统本身。系统造对了,七面从原语里自然掉出来;造错了,再多AGENTS.md抛光也修不好缺失的队列。听到「外壳工程」时,翻译回原语:提示与规则是策略与函数,脚手架是运行时,护栏是授权+验证,钩子是触发器,记忆是会话持久化,Ralph Loop 是重新入队,子智能体是工人,沙箱是计算面。词汇会变,工程不变。
原课程 code/main.py 把一个小仓库任务跑两遍:先仅提示,再接好七个面。同模型、同任务。脚本数失败运行缺失了哪些面,打印失败模式报告。
仓库任务故意很小:给一个单文件的 FastAPI 式处理器加输入校验,并写一个通过的测试。
# 仅提示运行:Agent 没有范围/反馈/验证/审查/交接 def prompt_only_run(task): files_touched = agent.edit_files(task, allowed=ALL_FILES) # 无范围 return {"claim": "success", # 在 400 上宣布成功 "touched": files_touched, # 含无关文件 "tests_run": False} # 没跑验证 # 工作台运行:七面接好 def workbench_run(task): scope = load_scope_contract(task) # 范围:允许/禁用 glob state = load_agent_state() # 状态:上次到哪 while not done(state): out = agent.step(state, scope) # 循环读状态与范围 feedback = capture(out.shell_cmd) # 反馈:真实命令输出进队列 state = update(state, out, feedback) if verify(state, scope): # 验证:测试+lint+范围检查 if reviewer.approve(state): # 审查:第二角色 write_handoff(state) # 交接:持久记录 return "shipped" return "blocked"
运行 python3 code/main.py 会输出两次运行的并排日志、一份总结仅提示运行的 failure_modes.json、工作台运行的一行裁决。
💡 设计要点:这节的 Agent 是个微小的基于规则的桩;重点是面,不是模型。在剩余的小专题里,你会把每个面重建为真实、可复用的产物。核心心法是「循环闭合在状态文件上,而非聊天历史」——聊天易失,仓库才是真相之源,这与第 07 节 MemGPT「外部存储是磁盘」、第 17 节「会话存储」一脉相承,只是这里把整个工程纪律显式化。
工作台面在野外已存在,只是没人这么叫:
AGENTS.md/CLAUDE.md 是指令面;斜杠命令是范围;钩子是验证。工作台工程,就是把这些面显式化、可复用,而不是让每个团队重新发现的纪律。
原课程 outputs/skill-workbench-audit.md:一个可移植的技能,审计一个已有仓库的七个工作台面,报告哪些缺失、哪些部分、哪些健康。丢到任何 Agent 设置旁,它告诉你先修什么。
main.py,让仅提示运行也产出一条假的「成功」声明。验证验证门能抓住它。下一节,我们开始逐个重建工作台面——从最小 Agent 工作台起步:用最少代码搭出一个带范围、状态、反馈、验证的能跑真实仓库任务的骨架,后续节再逐面加深。