对象:极客时间《从 0 开始构建 Agent Harness》(Tony Bai,Go + OpenClaw 哲学)
目标:不是复述课程讲了什么,而是把 24 讲背后真正值得沉淀的东西抽干、压平、反刍成你自己的系统认知。
0. 一门课如果只能记住一句话
Agent 的本质不是"聪明的模型",而是"模型 + 一套为它兜住一切的系统"。
模型负责"想"(CPU),系统负责"活"(OS):内存(上下文)满了要回收,进程(Loop)卡死要打断,外设(工具)越界要拦截,宕机(重启)要能恢复。决定 Agent 能跑多远、多稳、多省钱的,从来不是模型智商,而是底层这层 OS。 这本书的全部价值,就是把这句话从口号落地成一行行 Go 代码。
这就是为什么它敢叫 "Harness(驾驭工程)",而不是又一个框架教程------它教的不是怎么让模型变得更聪明,而是怎么让聪明的模型别在自己身上栽跟头。
1. 为什么传统框架会被推翻:一个"职责错配"的问题
1.1 历史包袱
LangChain / AutoGen 那代框架,诞生于 GPT-3 时代------当时的模型太笨,没有原生规划能力。所以框架必须当"微管家":替你意图识别、替你路由分发、用硬编码的 DAG 规定"先 A 再 B"。
1.2 现在的矛盾
模型进化到 GPT-5.x / Claude 4.x,自带极强的规划和工具调用能力。此时框架的"帮忙"变成了三层伤害:
- 静态对动态:DAG 是写死的,真实世界千变万化------网络超时、意外格式,图结构的回退机制极脆,直接崩。
- 黑盒对失控:框架维护人类读不懂的隐式状态机,一旦死循环,你连插手的位置都没有。
- 延迟对成本:一次调用包一层框架,注意力被稀释,Token 与延迟双升。
1.3 本质结论
The Framework Layer is Collapsing into the Harness.
框架层在坍塌,并收缩进"驾驭工程"里。
翻译成人话:模型越聪明,你越不该跟它抢脑子的活(怎么想),越该把精力放在它脚下的活(怎么活)。 这不是技术迭代,是分工重心的转移。
2. 全文的"公理层":为什么说 Harness 是给大模型的 OS
这是全书的理论地基,也是你必须先吃透、再去看任何细节的公理。它用一个严格的结构类比把所有问题"翻译"成了操作系统语言:
| OS 术语 | Agent 对应 | 要解决的问题 |
|---|---|---|
| CPU | 大模型 | 推理决策(不干预) |
| RAM | 上下文窗口 | 稀缺内存,决定能跑多远 |
| 外设 | read/write/edit/bash | 改变物理世界 |
| 调度 | Main Loop | 维持 ReAct 循环 |
| GC / 回收 | Context Compaction | 防内存(OOM)爆仓 |
| 中断 | Middleware / Reminder | 拦截高危、打断死循环 |
| 持久化 | 文件系统状态 | 重启不丢、可人机交接 |
| 系统日志 | Tracing / Cost / Benchmark | 黑盒可观测、可度量 |
一旦你把 Agent 的每个问题都翻译成"OS 该怎么处理",答案自己就长出来了。 内存会爆 → 压缩;进程卡死 → 打断;外设越界 → 中断;宕机 → 持久化。所有看似独立的技巧,其实都是这一个身份推演出来的结果。
一句话证明这是好理论: 它能解释既有事实,也能预测该写什么模块。你从"OS 架构师"出发,就能推导出这门课几乎全部的目录结构------而不是靠目录倒推理论。
3. 核心引擎(01-04):先把"心脏"和"大脑"搭对
3.1 Main Loop:优雅的"空"结构
ReAct(Reason + Act + Observe)循环,是所有顶级 Agent(Claude Code、OpenClaw、AutoGPT)的共同底座。它的设计精髓在于刻意地"空":
- 循环里没有业务逻辑,全凭模型决定走向;
- 不设硬性 max_turns 截断,靠后续的压缩/提醒来维持稳定;
- Context 是唯一记忆载体,数据像滚雪球一样累加;
- 确立 WorkDir 物理边界------Agent 不是全局幽灵,必须锁死在某个工作区。
为什么好? 因为职责单一。Main Loop 就是个诚实的"书记员":把模型的意图交给执行层,把环境反馈原样记回内存。任何业务判断都不该污染这个循环------污染一点,就失去一点"可驾驭性"。
3.2 慢思考:机制锁手,而非话疗
这是全书第一个"灵魂技巧",值得单独标出来理解:
事实:大模型是预测下一个 Token 的"系统1"(快思考),看到工具 JSON Schema,预测概率立刻坍塌到"调用工具"------提示语写一百遍"请先思考"都没用。
解法 :不劝,用架构锁。发起一次不带任何工具的请求(Generate(ctx, msgs, nil)),把模型关进没有工具诱惑的"小黑屋",它只能输出纯文本推理;再把推理追加回上下文,第二次请求恢复工具,让它顺着自己的计划执行。
抽象能力所在 :EnableThinking 是可开关的,映射到业界前沿的 自适应推理(Adaptive Reasoning) ------简单任务关掉省 Token,复杂任务打开换准确率,动态分配算力。这个"开关化"的自觉,比慢思考本身更值钱。
3.3 Provider 适配:别让主线知道外面的协议碎片
OpenAI(tools/tool_calls)和 Claude(messages/tool_use)是两套完全不同的协议。若主线关心厂商差异,解耦即刻崩溃。
抽象法 :LLMProvider 接口当"同声传译"------入站把内部干净的 schema.Message 翻成各家 SDK 的晦涩请求体,出站把 ToolUseBlock/FunctionCall 翻回来。主线只认自有的 schema.Message。
验证了它的优雅:同样的代码,只需改一个 BaseURL,就能用官方 SDK 直连国内智谱 GLM-4.5。"即插即换大脑",换的是实现,动不了骨架。
4. 极简工具(05-08):与"Context Bloat"对抗的艺术
4.1 Tool Registry:给意图与代码之间做绝缘
Main Loop 永远是"瞎子",职责是把模型吐的 JSON 丢给执行层。Tool Registry 是集线器+路由器,三个职责:动态挂载(Register)、暴露 Schema(给模型看)、路由分发执行(Dispatch)。
它的价值 :以后加任何能力,只需写个实现 BaseTool 接口的文件 Register 进去,主线一行不改。这是"开放-封闭原则"(OCP)在 Agent 语义下的落地。
4.2 极简工具集:克制,是最难的能力
行业(尤其 MCP 狂热)在使劲给 Agent 塞更多工具,这本书坚决反着来。论点极其硬核:
工具描述是每次请求都随上下文发给模型的。挂几十个工具 → Context Bloat → 三宗罪:成本延迟飙升、注意力稀释引发幻觉、外加维护地狱。
方案 :回归 OS 本质,只留图灵完备的 4 个基础原语------read、write、edit、bash。给一个 bash,模型自己会跑 git/grep/npm/curl,等于拥有整个 CLI 世界。
反直觉的洞见 :抽象能力边界的关键,是别替模型做它本来就会的事 。模型经海量训练已精通终端命令------你要做的不是重新教它,而是少拿高维 Schema 污染它的注意力。给得少,反而是给得对。
4.3 Edit 容错:把模型误差"吸收"进工具层
大模型改代码最大的幻觉是缩进丢失 。strings.Replace 精确匹配必然失败 → 模型无限重试 → 死循环。
解法:模糊匹配链(责任链/降级)------
- 精确匹配(最快)
- 统一换行符差异
- 忽略首尾空行
- 核心:按行切分、去每行首尾空格再比对
并设唯一性校验底线:匹配到多处相似片段时,绝不盲目替换,而是报错要求提供更多上下文定位。
可取的思想:与其让模型"永远正确",不如让系统"容忍它不完美"。容错前置到基础设施,而不是把压力全压在模型的生成质量上。
4.4 并发:物理性能不能被架构浪费
模型原生支持 Parallel Tool Calling(一次返回多个独立工具),但 Main Loop 一开始是串行 for 循环,纯属浪费性能。
解法 :Fork-Join------Goroutine + sync.WaitGroup,把 O(N) 压到 O(max(N))。前提是独立性假设:同一 Turn 的多个调用视为互不依赖、无脑并行;有强依赖的模型自然会在下一个 Turn 做(它已经被 RLHF 训出了这个纪律)。若担心并发写同文件,可加"基于路径的 RWMutex"或"只读并发、涉写串行"的批次调度。
5. 上下文工程(09-13):把"内存管理"练到极致
这章是整个体系里最像"OS 内存管理"的部分,也是决定 Agent 智商上限的生命线。
5.1 解耦 I/O(飞书接入)
真实场景里 Agent 是被团队在群里 @ 的,不是被终端用户盯着的。引擎循环必须与 I/O 解耦 ,像 Linux 内核把显示交给终端。引入 Reporter 接口 (OnThinking/OnToolCall/OnToolResult/OnMessage)做事件广播------终端跑 TerminalReporter,飞书跑 FeishuReporter,无缝切换。这是"关注点分离"(SoC)的干净示范。
5.2 会话隔离 + Working Memory
多端并发共用一个全局历史 → 上下文混杂。解法:SessionManager + 每 Session 独立历史队列 (RWMutex 保护),滑动窗口截取最近 N 条作为短期记忆。细节很关键:裁剪时丢弃"孤儿 ToolResult"(首条带 ToolCallID 的消息),否则 API 400------这是只有踩过坑才写得出的经验。
5.3 Context Compaction:阶梯降级的"GC"
Working Memory 只限条数,挡不住单条超大的工具输出瞬爆窗口。Compactor 用字符数估算水位线:
- 远期历史 → 全量掩码(不删逻辑链);
- 近期保护区超长消息 → 掐头去尾;
- 但绝不删 ToolCall 意图。
铁律:写进 Session 的永远是全量,压缩只作用于发往 API 的临时 Context。(类似 GC 不破坏程序语义。)这是终极防 OOM 的兜底。
5.4 状态外部化:抛弃内存状态机
长程任务会失忆、重启即清零。解法是彻底外部化状态 :引入 Plan Mode,让 Agent 把规划写进 PLAN.md、待办写进 TODO.md。
四重收益:透明 (纯文本谁都能读)、可干预 (人直接改文件纠偏)、可续传 (重启嗅探文件、从未打勾处继续)、零成本人机协同 (人和 Agent 共享同一份状态)。这是把"可控性"从黑盒拉到可视化的一次飞跃。
6. 稳定性与多智能体(14-17):让 Agent 能"活着"走向生产
前四章解决"能不能干活",这章解决"会不会搞砸"------是走向生产的硬门槛。
6.1 Error Recovery:把兜底变成"救援 SOP"
直接丢报错给模型,它只会机械道歉或盲目重试。RecoveryManager 用关键字分类器匹配工具/报错类型(edit 未命中、command not found),再追加祈使句风格的系统救援指南(如"先 read_file 再改"),引导模型走排障 SOP。作者坦承生产应改用稳定错误码而非中文模糊匹配------这份自省值得学。
6.2 System Reminders:斩断 Doom Loop
死循环的根源是"上下文分布偏移 + 近因偏差"。ReminderInjector 每轮对 (ToolName+Args) 做 MD5 指纹,统计同一动作连续失败次数,达阈值(3 次)就注入一条用户角色 消息作为最新上下文,借"最高近因效应"强制打断执念。原理讲得比实现更值钱。
6.3 Middleware:YOLO 与人工审批的分界
本地开发 YOLO(全权信任),但部署到远端就危险了(rm -rf)。解法是在 Tool Registry 引入 Middleware 链 :Execute 前拦截,命中危险正则就用 Go channel 挂起协程,经飞书 Webhook 等人类 approve/reject 后放行/阻断------Human-in-the-loop 落地的范式。
6.4 Subagent:给上下文"减负"
庞大探索任务会把主 Agent 上下文塞满、忘掉初心。极简到极致的解法 :把子智能体做成一个普通工具 spawn_subagent,内部用全新的 contextHistory 拉起"只读+bash"的探索子循环,跑完把精炼总结返回主Agent。把"爆炸半径"限制在子进程里,主上下文保持清醒。(和派 worker 干完整再汇报,是同构思想。)
7. 可观测性(18-20):把"玄学"变成工程
很多团队死在"好不好使全靠试"的玄学阶段。书的收官给出工程闭环,也是 OS 的"系统观测"。
| 工具 | 技术 | 类比 | 回答的问题 |
|---|---|---|---|
| CostTracker | 装饰器包 Provider | 记账 | 花了多少钱、多快 |
| Tracing | context.Context 透传 + Span 树 | 系统日志/病历 | 哪一步失败、谁耗时 |
| Benchmark | SWE-bench 式 F2P | 性能基准 | 这次改动更优了吗 |
串联成 "成本 → 归因 → 度量"闭环 :能记账、能回溯、能量化。当 Agent 的每次进步都能被数据丈量,它才从 Demo 进入工程。 这是高级工程师与普通玩家的分水岭。
8. 终局(21-22):零件全部装车,跑通闭环
- 实战上(CLI) :把所有模块按依赖注入组装成可
go build的 CLI,给定含竞态 Bug 的未知项目,Agent 全程零干预自主完成"探索 → 分析 → 多方案修复 →go run -race验证 → 写 README",约 2 分钟、耗 110k 输入 Token。验证了自驱闭环可用。 - 实战下(AgentOps) :打成后台守护进程对接飞书,用工厂方法为每请求动态组装引擎、以 context.Context 透传 Reporter 发出审批卡片。演示 Nginx 502 排障全程:读 AGENTS.md → 读日志触发 Compactor → edit_file 与 nginx reload 各自挂起等审批,人类 approve 后放行。一册基础设施的"大阅兵"。
9. 反刍:这门课真正想教你的 5 条底层哲学
把 24 讲抽干,剩下的就是 5 个相互咬合的思维模式。理解这套,你就抄走了一半的书。
-
机制 > 要求(Law of Mechanism)
别在 Prompt 里"求"模型别冲动。用
Generate(_,_,nil)这类架构剥夺,让模型"想冲动也没得冲"。凡是依赖主体自觉的防线皆脆弱,唯架构约束有确定性。 -
Context 是最稀缺的"内存"(Memory is Money)
一切围绕"榨干 Token、防止 OOM"展开。极简工具(少污染)、压缩(回收)、外部化(不占栈)、Subagent(隔离)------本质全是 OS 级内存管理。
-
信任意图,守住边界(Trust, but Truncate)
本地 YOLO 给最高自由度,底层永远埋着超时、截断、审批、自纠错回传这些确定性兜底。信任模型的能力,绝不信它的理智。
-
能落地的状态,绝不进内存(Externalize)
PLAN.md / TODO.md 代替图数据库。透明、可改、可续传、可人机交接------状态一旦外部化,Agent 才真正"可被驾驭"。
-
可度量才有进步(Measure, or It's a Demo)
成本追踪、链路追踪、基准测试三件套,把"观感"变成"数据"。无法度量的 Agent,永远停在 Demo。
最后回到那个类比:"大模型是 CPU,Harness 才是承载它的操作系统。" 当 CPU(模型)越来越强,真正拉开差距的,是这层 OS 的设计与驾驭。工程师正从"框架的使用者 / Prompt 糊裱匠",跃迁为 AI 世界物理法则的设计者。
未来深水区------沙箱隔离、细粒度权限、插件生态、Token 省流、智能体自进化------仍待书写,而这正是系统架构师的黄金时代。
以上为个人基于原课程的学习重构笔记,用于交流分享,版权归原作者 Tony Bai 及极客时间所有。