跳到主要内容

01 · Agent 设计:先按失败成本选骨架

用失败成本和可验证性选择 Agent 运行时骨架,沿着四个源码入口定位该借什么、该避开什么。

本章任务

要回答的问题

失败成本不同的 Agent 产品,应该从哪套运行时骨架借什么?

读完你能

  • 按可验证性、自治度和运行边界选择参考系统
  • 识别可直接复用与不能跨场景照搬的实现假设
  • 为自己的产品排出后续章节阅读顺序
适合现在读
正在选型、做架构评审,或第一次进入本站的读者
先修知识
知道 Agent 会通过工具改变外部状态
实践产物
一份按失败成本排序的 Agent 架构选择表
证据边界
比较基于固定源码快照,说明实现取舍,不构成通用性能排名

假设你正评审两个产品:

  • 仓库修复 Agent:会改真实代码和执行命令;一次错误提交可能阻塞发布,但测试、Diff 和 Git 可以提供外部证据。
  • 每周研究助理:要跨会话追踪主题、来源和用户偏好;单次答案允许不完美,但错误记忆会在后续任务里持续放大。

两者都叫 Agent,却不该共用同一套默认骨架。先填下面四格:

要先回答的约束你的答案会改变什么
最坏副作用能否回滚?决定审批、沙箱、幂等键和人工门禁的强度
有什么外部信号能证明完成?决定 Verifier 是测试、规则、来源核验还是人工复核
状态要活多久?决定只保留单次轨迹,还是要 Session、Memory 与后台任务
是否跨用户、通道或并发运行?决定身份、路由、Session lane 和隔离边界

完成标准:读完本章,你应能为自己的产品选出一个“主参考系统”、一个“只借局部机制的系统”,并明确至少一条不能照搬的假设。

把失败成本映射到四个可借鉴边界

Section titled “把失败成本映射到四个可借鉴边界”
四系统在「短期可控性 ↔ 长期自治度」这条轴上的分布
同一条轴,四个 agent 各占一格:左端强调单次运行的可审计性,右端强调跨会话连续性。

四家不是同一件产品的四种实现,而是四份针对不同失败面的工程答案:

决策 CodexClaude CodeOpenClawHermes
首先控制的失败 错误 Patch、危险命令和不可复核修改无法解释的重试、压缩与上下文漂移多用户、多通道运行的竞态与路由混乱长期任务中偏好、反馈与记忆无法延续
主要外部信号 Diff、Patch 校验、测试、策略与 rollouttransition.reason、hook、token 与压缩状态runId、session lane、tool/lifecycle eventscheckpoint、memory、insights 与 skill feedback
最值得借的边界 事件化 Loop、执行策略、Git 与 Sandbox继续原因、分层压缩和 IDE 状态恢复异步 Run、Session 控制面和插件 Hook跨会话记忆、后台任务和输入扫描
最容易误抄的假设 所有任务都有测试或可机器验证产物一套紧耦合查询循环适合外部二开可观察的后台 Job 天然可恢复副作用保存反馈就等于长期成功率会提升
先按失败面定位源码,再决定读哪一章

Codex · 用 patch、策略和目标状态提供可复核信号

Section titled “Codex · 用 patch、策略和目标状态提供可复核信号”

Codex 是 OpenAI 官方的 coding agent,核心是 Rust 写的 codex-rs workspace,外加 TypeScript 写的 CLI 包装层 codex-cli。它最先处理的问题是:模型说自己做完了,在生产环境基本不能信。模型经常没完成但觉得完成(改了一个文件就以为整个 bug 修好;跑一次测试通过就以为修好,但是测试覆盖不全)。

因此 Codex 源码把几类可复核信号分开处理;它们是否组成某个项目的完成门禁,由宿主工作流配置:

  • apply_patch 校验:patch 必须符合 V4A 语法。
  • run tests 退出码:宿主若配置测试,exit code 可作为失败信号。
  • goals.rs 收敛检测:跟踪 Goal 的子目标状态,不能单独证明业务完成。
  • execpolicy 命令审查:每条 shell 命令过 Allow、Prompt、Forbidden 三态决策器。

这些信号让部分状态可以机器复核,但不等于所有任务都有自动完成证明。

loop 结构上 Codex 不写 while True(那样跑挂了状态全丢),而是拆成 submit、event、turn、goal 四层事件机器。外部动作(用户输入、超时、中断)通过 submit(Op) 进入。loop 每步事件通过 next_event() 输出给外部观察者。Turn 是一次「模型说话 → 工具执行 → 模型再说话」的最小循环。Goal 是 Turn 之上的更长周期任务目标。

每步通过 flush_rollout() 写进 rollout JSONL,这个文件就是 loop 的物理时间线。机器重启读 rollout 重建状态,用户看历史回放 rollout,行为分析聚合多份 rollout,跨 agent 通信也走这套机制。

代价是这些信号主要服务 coding 场景。PRD 或调研任务没有 patch 和测试,Goal 状态也不能替代内容评审;宿主必须另接来源核验、人工复核或领域检查。

Claude Code · 用 7 种 transition.reason 把 loop 状态机做到最显式

Section titled “Claude Code · 用 7 种 transition.reason 把 loop 状态机做到最显式”

Claude Code 是 Anthropic 自家的 CLI 工具,核心是 src/query.ts 一个文件 1729 行的 queryLoop()(241 行起)。它最先处理的问题是:loop 跑挂的最大原因不是模型不会,而是外部观察者不知道 loop 在做什么。一份 rollout 写满 message 但看不出当时为什么决定再跑一轮:是模型主动要继续,还是用户问题没回完,还是上下文压缩了需要重启?不知道原因就没法做分析、监控、告警、优化。

所以 Claude Code 把「为什么 loop 还要再跑一轮」的转移原因都显式建模成 transition.reason 标签,共 7 种 reason:

  • reactive_compact_retry:反应式压缩之后必须重跑。
  • collapse_drain_retry:contextCollapse 折叠后需要重新调模型。
  • max_output_tokens_escalate:输出超 token 限制需要升级到大模型。
  • max_output_tokens_recovery:升级也不够要做恢复。
  • stop_hook_blocking:stop hook 强制阻止本来的退出。
  • token_budget_continuation:接近预算上限主动 nudge。
  • next_turn:正常进入下一轮。

loop 状态机变成带原因注释的状态机。

工程亮点几个:

  • 4 道上下文压缩管线applyToolResultBudget 按工具上限砍返回值(便宜)走 snipCompactmicrocompact 做局部裁剪(便宜)走 contextCollapse 把已确认的历史折叠成 view 引用(开始变贵)走 autocompact 越阈值就 fork 独立 agent 总结整段历史(最贵)。任一档失败连续 3 次走断路器。注释直接写线上数据:「1,279 sessions had 50+ consecutive failures (up to 3,272) in a single session, wasting ~250K API calls/day globally」。
  • TOKEN_BUDGET 软 verifierquery/tokenBudget.ts 用 60 行算法定义 diminishing returns(90% 阈值加 500 token 增量阈值加 3 轮连续低增量)。它只说明 Claude Code 采用了这组启发式;换模型或任务前,要用自己的 stop/continue 记录重新校准。
  • Task.ts 多 agent 模型:7 种 TaskType(local_bashlocal_agentremote_agentin_process_teammatelocal_workflowmonitor_mcpdream),queryTracking 追踪 subagent 调用链。
  • Memory prefetch:TS 5 using 关键字让 loop 任何路径退出都自动 dispose,省掉手动 finally。

代价是 1729 行所有路径耦合在单文件,没有插件钩子。想给 verifier 加自定义中间件、替换压缩策略、接外部观测器,只能 fork 整个 query.ts。这是 Claude Code 在二开友好度上的明显短板。

OpenClaw · 把 loop 写进公开文档,并用中间件承载 verifier

Section titled “OpenClaw · 把 loop 写进公开文档,并用中间件承载 verifier”

在这四个样本里,OpenClaw 把整个 loop 写进了公开文档(docs/concepts/agent-loop.md 18-148 行)。文档能先给出运行边界,源码仍然是核对细节的入口。

它最先处理的问题是:作为同时支持 Telegram、Slack、Web、IDE 多通道入口的开源 agent,loop 不能是函数调用式(同步等到结果才返回),必须是可观察的后台 job:用户调用 agent RPC 立即返回 runId,job 在后台跑,外部任何时候都可以通过 runId 订阅事件流看进度。这让 loop 变成一等公民的后台资源,对接多通道、多用户场景天然适配。

5 步管线写得很清楚:

  1. agent RPC 验证持久化 session metadata。
  2. agentCommand 解析 model 和 skills 参数。
  3. runEmbeddedPiAgent 内部串行化(session lane 同 session 内多个 run 串行加 global lane 控制全局并发)构建 pi-agent-core 会话。
  4. subscribeEmbeddedPiSession 把内部事件桥成 3 个外部流:assistant(模型说话)、tool(工具调用)、lifecycle(会话状态变更)。
  5. agent.wait 阻塞在 lifecycle: enderror 事件上拿最终结果。

请求 → 调度 → 执行 → 观察 → 等待,一个完整管线。

最值得参考的两件事:

  • session lane:同 session 内多个 run 强制串行化(不并发),避免工具状态和历史消息的竞态。Codex 和 Hermes 都没显式做这一层,默认假设单用户单 session,并发场景容易出问题。
  • 工具栈拆分tool-policy-pipeline 把权限、审计、缓存做成中间件链(before_tool_callafter_tool_calltool_result_persist 三个 hook 都可插),tool-loop-detection 4 种 detector 处理不同循环形态,tool-fs-policy 是文件系统专用的二级权限层。OpenClaw 的可扩展性主要来自这组 hook,代价是调用链更长。

Hermes · verifier 摊到时间轴上,靠跨会话记录反馈

Section titled “Hermes · verifier 摊到时间轴上,靠跨会话记录反馈”

Hermes 是 Python 写的、跑在用户本机的长期助理。它选择不把所有验收都塞进单次 loop,而是用事后分析和 memory prefetch 记录反馈。这样适合需要跨会话积累上下文的场景,但是否改善结果要用任务样本和人工复核验证。

具体实现:

  • 单 loop 默认 90 步,subagent 50 步(subagent 故意比父短,防止跑太多步浪费父的 budget)。
  • 耗尽不直接退出,给模型一次 grace call 说最后一句话(让模型有机会总结当前进度而不是中断在半截)。
  • grace call 后还不够就剥掉所有工具,强制做最终总结。
  • agent/insights.py 在 loop 结束后调一次 LLM 看「这次跑得怎么样」(4-5 个维度评分加改进建议),结果写回 memory。
  • 下次类似任务 memory_manager.prefetch_all() 在 loop 开始前一次性把跨会话偏好和经验注入 context。批量预取省掉 N 次 RAG 延迟。

短期验收不严格,长期效果取决于 memory 质量、触发条件和任务分布;源码本身没有给出跨会话收益评测。

最独有的工程动作是注入前对外部文件做 prompt injection 扫描。其他三家默认本地仓库 AGENTS.mdCLAUDE.md 可信(假设是开发者自己写的)。Hermes 假设用户可能 clone 了一个带恶意 AGENTS.md 的 repo(攻击者通过 PR 投毒),把不信任边界拉到文件读取层。

_scan_context_content 扫 9 类危险 pattern(ignore previous instructionsdo not tell the user、假冒系统消息的 system: ... 等)加 10 类不可见 Unicode 字符(U+200B 零宽空格、U+202E 右到左覆盖等藏指令的字符),命中就把整个文件替换成 [BLOCKED] 占位符。

这层扫描可降低一类来自外部文件的注入风险,但不是完整的安全边界;短会话也可能发生泄露。SUMMARY_PREFIX 是可复用的提示隔离做法,接入生产前仍应配合权限、来源标记和对抗测试。

四家在取舍上分歧很大,但源码里能看到 7 条共同约束。它们适合做设计检查表,不是上线认证标准:

1. 需要多次行动的任务通常要有状态机(详见 02 章)。修 bug 往往要 Read、Grep、Edit 和测试;简单问答则未必需要完整 loop。四个样本都能映射到 Observe、Plan、Act、Verify,但实现边界并不相同。

2. 给「模型自信不等于真实状态」留可复核信号(详见 05 章)。Codex 暴露 patch、测试、策略和 Goal 状态,Claude Code 用 token 预算判断是否还值得继续,OpenClaw 提供 hook 与循环检测,Hermes 把反馈写回跨会话记忆。它们解决的是不同问题;宿主仍要按任务风险决定哪些信号组成完成门禁。

3. 有副作用或有成本的 loop 要有明确结束条件(max_steps、token_budget、goal_done)。四个样本各自提供上限;OpenClaw 的 global circuit breaker 在源码中默认关闭,不能当作每个 session 都启用的保护。Claude Code 注释里的 API 调用数字是来源方的案例,不是通用事故率。

4. 可以把稳定 context 和运行时 context 分层(详见 03 章)。这样有机会改善缓存命中和更新成本,但 provider 的缓存规则不同,是否值得拆分要用 token、延迟和命中日志验证;四个样本也不是同一套缓存实现。

5. 工具签名用 JSON schema,不是自然语言(详见 04 章)。schema 把参数类型和必填关系写成机器可读的约束,减少模型猜测;具体失败率要按模型、工具集和任务记录,不能从这四个源码样本推导一个通用百分比。即使是 Codex 的 apply_patch 这种 DSL,schema 槽位也保留(参数是 diff 字符串)。

6. 高影响工具应有显式权限层。四个样本都在工具执行前提供某种策略或审批入口,但默认模式和覆盖范围不同;低风险、只读工具是否需要同样的门禁由威胁模型决定。

7. 有副作用的事件要可检索(用于审计和调试)。四个样本提供 rollout、trajectory 或 tool events 的不同组合;是否另建事件流取决于部署。至少保留工具、参数摘要、结果状态和时间,并处理敏感数据。

四家 Agent 在短期可控性、长期自治度两条轴上的分布与场景映射
横轴:短期可控性(每步审批的难度)。纵轴:长期自治度(自跑加自学)。四家分布在对角线上,对应不同产品形态。

四家的核心分歧是「短期严格性对比长期累积性」的取舍。不同产品形态需要不同取舍点,没有通用最优解。

让模型改真实 repo,并让每一步可 review:可以先看 Codex。patch 解析、测试退出码、命令策略和 Goal 状态分别提供可复核信号,rollout 记录则支持回放与恢复。宿主只有把其中适用的信号接成完成门禁,才能约束具体 coding 工作流;它们本身不保证业务正确。客服、写作和调研需要另一套验收依据。

在 Anthropic 生态里、想拆一份完整实现:可以从 Claude Code 路线开始。它把 tool_use、Messages API、prompt caching、transition.reason 和 4 道压缩管线放在同一套运行时里,适合研究耦合点;源码快照显示 query.ts 仍是单文件主循环,外部扩展要付出 fork 或包裹的维护成本。

agent 要接 Telegram、Slack、Web、WhatsApp 加处理多用户并发请求:可以重点看 OpenClaw。session lane 串行化同一会话的运行,plugin hook 承载 verifier、权限和工具拦截,PromptMode 区分主 agent 与 subagent。代价是 hook 链路会拉长调试路径,而且 coding verifier 需要另行接入。

agent 要在电脑上长期运行,并尝试保留偏好或跨任务反馈:可以评估 Hermes 路线。memory_manager.prefetch_all()insights 和 skill 触发提供了跨会话记录机制;收益和污染风险需要按任务评测。文件扫描可作为一层防注入措施,但不能替代权限和隔离。

按失败代价,而不是框架名做选择

Section titled “按失败代价,而不是框架名做选择”
场景约束先看哪条源码代价
改错一次就不可接受,且有 tests 或 patch 信号Codex 的 rollout、goals、execpolicy只适合可机器验证的 coding 任务
需要解释重试和压缩原因Claude Code 的 transition.reason 与 compaction定制要跟随单文件实现
多用户、多通道,需要异步观察OpenClaw 的 session lane 与 hooks中间件链需要自己的 trace
任务跨会话,价值在持续积累Hermes 的 checkpoint、memory、insights单次结果缺少硬证据

按你的目标读

先读这几章

  • 想做 coding agent:02 Agent Loop → 04 工具系统 → 07 Shell 执行 → 11 沙箱
  • 想做 agent server:02 Agent Loop → 04 工具系统 → 11 会话生命周期 → 14 多通道入口
  • 想做长跑助理:02 Agent Loop → 03 上下文系统 → 16 Memory → 19 Self-improvement
  • 想做架构评审:01 总览 → 02 Agent Loop → 05 Verifier → 20 Security

再读这几章

  • 想参考具体代码:每章末尾都给到 REF/ 路径加行号
  • 想看四家对比:02 章保留了 5 组可展开的源码对照(prompt、压缩、重试、工具、退出)
  • 想看真实数据:注意章节里那些「线上一天浪费 250K API 调用」之类的原话引用

可以跳的章节

  • 一上来就扎进源码:先读系统画像和取舍判断,再沿入口下钻
  • 只读你认得的那家:四系统并列读才会冒出对比认知
Observe Plan Act Verify
四家都跑这同一个最小循环。差别在每个节点怎么实现。

交付检查:用一页选择记录结束

Section titled “交付检查:用一页选择记录结束”

把开篇四格收成一页,不要只留下“我喜欢哪家”的印象:

  1. 主参考系统:它首先控制的失败,是否正是你的最高损失项?
  2. 局部借用机制:从另一套系统只借一个边界,例如 transition reason、session lane 或 memory provenance。
  3. 不能照搬的假设:写出至少一条,例如“我的任务没有测试 Oracle”或“外部副作用不可回滚”。
  4. 下一章:按当前最危险的未解决问题进入 Loop、Verifier、Session、Memory 或 Security,而不是顺序通读。

下一步实验:拿两个失败成本明显不同的真实任务分别填表。如果它们仍得到完全相同的架构答案,检查你是不是用框架偏好代替了约束分析。

按需展开练习和十道复盘题
  1. 🟢 选型:把你过去 3 个月的「AI agent 用例」列出来。按本章的失败成本分类,看自己该用哪家,或者该自己写一个。
  2. 🟠 阅读:选一家系统,照章末入口顺序读 30 分钟。回答三个问题:这家的主循环在哪个文件?停止条件是什么?最特殊的工程动作是什么?
  3. 🔴 对比:四家里挑两个最不像的(比如 Codex 和 Hermes),对比它们的系统画像。写 5 行具体例子,证明「同一个问题,四家给出完全不同答案」。
Q1 · 概念:「Agent Harness」和「Agent 模型」是同一回事吗?

不是。Agent 模型指 LLM 本身(GPT-4、Claude、Gemini 这一类参数加解码器)。Agent Harness 指模型之外的全部支撑系统:主循环、上下文系统、工具系统、沙箱、verifier、memory、observability、安全。本书拆的是 Harness,不是模型。

为什么这层值得专门拆?不少 agent 故障发生在模型周围:loop 没有明确的退出信号,工具协议让模型反复重试,或上下文把错误状态带进下一轮。差异需要用同一模型、同一任务集和运行日志测量,不能凭一句“换 harness 就好”下结论。

四个系统的定位不同:Codex 是 OpenAI 的工程参考,Claude Code 是 Anthropic 的闭源实现快照,OpenClaw 是开源控制面,Hermes 偏研究型长跑 agent。读者应按自己的失败代价和部署边界选择借鉴对象。

源码:见本章的支撑这条选择的源码追问:「LangChain、AutoGPT 算 harness 吗?」算,但属于框架级 harness(给开发者拼装);本书拆的是产品级 harness(最终用户跑得起来的成品)。

Q2 · 场景选型:你接到一个需求”把内部知识库做成可对话的 agent”,怎么从四家里选参考?

先拆需求:单用户、问答型、轻工具(多数知识库),还是多用户、写操作、有数据库(更像内部 ops)。前者偏 Hermes 或 Claude Code 路线,后者偏 OpenClaw 路线。

单用户问答场景:参考 Claude Code 的上下文压缩加 transition 标签(query.ts 最像现代 RAG agent 的样本)。不要照搬 Codex,因为 Codex 假设 coding repo。

多用户 ops 场景:参考 OpenClaw 的 session lane(一个 session 对应一个用户或对话),每个 session 自己跑 loop。memory 模块独立做(参考 Hermes 的 memory_manager)。

不要从头照搬任何一家。插件、channel 和 cron 等外围代码会显著扩大维护面;先抽取系统画像里的骨架,再按 Verifier 和 Memory 章节补齐。

源码openclaw/src/config/sessions/hermes-agent/agent/memory_manager.pyclaude-code/src/services/compact/compact.ts追问:「为什么不直接用 LangChain?」知识库小可以。规模上去后 LangChain 的工具协议过抽象,调试痛苦,可以参考工具系统自行拼装。

Q3 · 架构:四家都把”对话”分成 turn 这一个时间单位,但 turn 内的步数不一样。为什么?

Turn 的标准定义:从模型一次回复(含可能的工具调用)到下一次模型回复之间的时间段。但「turn 内能塞几次工具」差异很大:

  • Codex:一个 turn 一个 tool(serial)。每个 tool 后等 verifier 检过再放下一个,loop 形状更可预测,但吞吐会受串行等待影响。
  • Claude Code:一个 turn 可 dispatch 多个 tool_use block 真并行执行(dispatchToolUseBlocks 用 Promise.all),turn 末 stop_hooks 统一 verify。
  • OpenClaw:turn 设计成 event 流,tool 是其中的 event,外部可以看到每个 event 决定是否暂停。
  • Hermes:一个 turn 一个 tool。trajectory 是单线性的,并发会让 memory 注入逻辑混乱。

设计差异的根源:取决于协议(Anthropic 鼓励多 tool_use 一 turn,OpenAI 历史一 turn 一 call)和 verifier 类型(硬 verifier 倾向 serial,软 verifier 可并发)。

源码codex/codex-rs/core/src/session/turn.rsclaude-code/src/query.tsopenclaw/src/runtime.tshermes-agent/run_agent.py:9333-9540追问:「并行 tool 内部失败一个怎么办?」Claude Code 在 stop_hooks 里把 partial failure 当 transition reason,整体 turn 完成但 verifier 标 fail。Codex 不会遇到这问题,因为 serial。

Q4 · 工程:四家都用 markdown 当主要协议格式(不是 JSON)。这是巧合还是工程选择?

工程选择。原因有 4 个:

  1. 格式先做实测:markdown 便于人读、追加和 diff,但不能从未知训练语料推断模型一定更少出错。用目标模型比较 markdown、JSON 和 XML 的格式成功率与维护成本。
  2. 人类可读:debug 时直接看 prompt 就能读懂。JSON 嵌套层级深,看 system prompt 还得来回折叠展开。
  3. 可流式追加:markdown 的 section(## ###)天然支持「再加一段」。JSON 要重排整个对象。
  4. diff 友好:prompt 文件入仓后 git diff 易读。

四家都把 prompt 写成 markdown:Codex 一份大 .md,Claude Code 在 constants/prompts.ts 做字符串拼接,OpenClaw 用 buildXxxSection() 返回字符串,Hermes SOUL.md 直接是 markdown。但工具调用协议都用 JSON(Anthropic tool_use、OpenAI tool_calls),因为工具结构化要求高,模型解析失败成本大。

源码codex/codex-rs/core/src/context/prompts/claude-code/src/constants/prompts.tshermes-agent/docker/SOUL.md追问:“那 XML 标签呢?比如 <thinking>...</thinking>?” XML 在 prompt 内部当 section 边界标记(Anthropic 文档明确推荐),但整体仍在 markdown 里。

Q5 · 架构:四家都有”工具”这一层抽象,但工具的命名/边界完全不同。怎么定义”工具”?

工程定义:工具是「模型可触发、harness 实际执行、返回结构化结果给模型」的函数。三个条件缺一不可。

四家边界不同:

  • Codex:把 apply_patchrun_shellread_file 当工具,但「如何选 patch 算法」放在 prompt 里让模型自己决定。
  • Claude CodeBashReadWriteGrepGlobEditMultiEditTodoWrite 等 12+ 工具明确列出(src/tools/),每个工具是一个独立类。
  • OpenClaw:工具就是 plugin(PluginEntry),通过 hook 注册,最少。
  • Hermes:工具叫 skill(skill_loader.py 加载)。一个 skill 可包含多个 tool function,按需开启。

工具粒度直接影响 prompt size 和模型决策。粗粒度(一个 tool 干很多事)提示较短,但参数语义更宽;细粒度(每个动作一个 tool)约束更清楚,也会增加工具列表。Claude Code 采用细粒度工具集;是否更准,要用目标任务集验证。

源码:见 第 04 章 工具系统追问:「tools 越多越好吗?」不是。工具列表越长,schema 和选择负担通常越高;错误率和可用区间要用目标模型、工具集和任务日志测量。

Q6 · 工程:四家都假设 agent 跑在本机或可信网络。如果要部署到云端多租户场景,哪一家最容易改?

OpenClaw 最容易。它已经有 SessionManager 和 plugin 解耦,多租户基本就是一个 user_id 对应一个 session_id。需要加的:

  1. session 级权限:plugin 的 onSessionStart hook 检查 user 配额。
  2. tool 调用审计:plugin onToolUse hook 写入数据库。
  3. memory 隔离:一个 user 一个 memory namespace。

Codex 最难。codex-rs 假设 single-user CLI/IDE 调用,状态全在本机文件,rollout 在 ~/.codex/。改云端需要:

  • 把 rollout 改成 db。
  • 引入 user 维度的 ACL。
  • 重写 IPC(codex 的 codex_app_server 用 axum,本身可对外但默认单用户)。

Claude Code 中难。query.ts 没有 user 概念,需要外包一层。上下文压缩涉及的 forked agent 在云端要确保隔离。

Hermes 中难。memory_manager 假设单用户 home dir,但代码相对解耦,改成多 user 不复杂。

源码openclaw/src/agents/pi-embedded-runner/session-manager-init.tscodex/codex-rs/app-server/hermes-agent/agent/memory_manager.py追问:「给租户做 sandbox 隔离要怎么选?」参考 Hermes 的 tirith 子进程模式。每个 tool call 都 subprocess 加 redact,跨租户也安全。

Q7 · 实操:你拿到一个 “AI 客服 agent”,想给它加上 Codex 的 verifier 思路。怎么做?

Codex 的 verifier 思路有 3 个核心:

  1. goals.rs 把任务拆 N 个 goal:客服场景就是把客户原始问题拆成「我要查订单 / 我要改地址 / 我要退款」等子目标。
  2. 每步打 goal-touched 标签:每次 agent 调工具,记录这次操作覆盖了哪个 goal。
  3. 全 goal 触达即收敛:所有 goal 都被触达后视为完成。

落地到客服 agent:

  • 用一个轻量 NLU 模型把客户消息拆成 goals 列表(也可让主 agent 自己拆,但需要 schema 约束)。
  • 在 tool 调用层加 hook:每个工具声明它能贡献哪些 goal(比如 query_order 对应「查订单」)。
  • 维护 goal_status: dict[goal_id, status]。loop 每 turn 末检查是否全 done。
  • 加 fallback:超过 N turn 还没 done 就升级到人工。

不要直接照搬 Codex 的 Rust 代码。goals.rs 假设 coding 场景,「goal 触达」判断基于代码文件被改过。客服场景要重写判断逻辑(基于 tool call 和回复内容)。

源码codex/codex-rs/core/src/goals.rs、参考 第 05 章 Verifier追问:「客服 agent 要不要加 token budget 软退?」可以把较低阈值作为实验起点,并把“用户问题是否已解决”作为提示信号;阈值和提前结束率应由客服任务日志校准。

Q8 · 概念:什么叫「agent harness 的可观测性」?为什么本书单独一章讲?

可观测性指能从外部回答 3 个问题:

  1. 这次 loop 跑了多久、花了多少 token、调了哪些工具?(cost、latency、tool trace)
  2. 这次 loop 在哪一步偏离了预期?(transition reason、verifier 输出、错误堆栈)
  3. 同样的 prompt 上次跑 vs 这次跑差异在哪?(rollout diff、行为漂移检测)

四家都有但实现差异很大:这个 Codex 快照暴露了较多 codex-otelcodex-analytics 事件类型;Hermes 用 trajectory 文件(每步一行 JSONL),OpenClaw 走 plugin(onEvent hook 给外部观察),Claude Code 用 transition 标签加 token budget 日志。这里比较的是源码形状,不是在给可观测性做完整度排名。

单独一章的原因:demo 与长期运行之间,常见差距来自可观测性、恢复和成本控制。具体工作量取决于部署环境;本书第 15 章把这些运行信号拆开,方便你按需实现。

源码:见 第 15 章 观测、成本与日志追问:「一行日志够吗?」不够。最少需要 3 层:step-level(每个 tool call 一条)、turn-level(每次模型调用一条)、session-level(一次完整对话一条)。

Q9 · 选型:什么样的项目根本不应该用本书介绍的”重 harness”路线?

3 类项目用轻路线(直接 OpenAI 或 Anthropic 官方 SDK 加自写 200 行 loop),不沿用重 harness:

  1. POC、hackathon、一次性脚本:如果只需要快速验证一个窄流程,官方 SDK 加一个小 loop 往往足够;先确认失败后是否需要恢复和审计。
  2. 超细分场景且工具 ≤ 3 个:比如 PDF 提取关键字段返回 JSON。不需要 agent loop,单次 prompt 就 OK。
  3. 要求绝对确定性的工作流:比如金融对账,应该是 workflow(每步定死)加 LLM 当其中一个节点,不该是 agent(每步模型决定)。

什么时候开始上重 harness:当恢复、跨会话状态、多用户并发或审计的维护成本已经超过自写 loop,再引入相应模块;不要用固定月份或工具数做门槛。

这些系统的源码规模和演化历史都远超一个小型 POC;具体规模随快照变化,不能用它们推导你的项目工期。

源码:可参考 OpenAI 的 Building Agents with Function Calling、Anthropic 的 Claude Tool Use追问:「langchain 算重还是轻?」中等偏轻。LangChain 的工具协议好,但没有本书讲的 verifier、memory、observability 这些深层东西。适合中等复杂度且团队不想自己写 harness。

Q10 · 开放题:如果让你写第 23 章,你会加什么主题?

3 个最有可能的方向:

  1. Agent-to-agent 通信协议:四家都有 subagent(10 章),但 agent 之间怎么传消息各家协议不一样(Codex 用 agent.send_input,OpenClaw 用 event bus,Hermes 用 trajectory shared file)。对比加抽象出 A2A 协议设计模式,能补足「多 agent 系统」这块空白。

  2. Model swap 工程:本书四家都默认绑模型(Codex bind GPT-5,Hermes bind Claude)。生产里经常需要主任务用 Claude,摘要用便宜模型。怎么在 harness 内做 model routing 加缓存兼容,是热门话题。

  3. Agent UX 模式:14 章讲了多通道入口(CLI、IDE、Slack),但没讲 UX。比如 thinking 怎么 stream、tool call 怎么可视化、cancel 怎么实现。Claude Code 的 ink REPL 加 Codex 的 ratatui TUI 各有一套,值得拆。

只选一个,我会先研究 1,因为四家的 subagent 都暴露了状态隔离、恢复和验收问题;这个判断来自本书样本,不代表所有 Agent 产品的路线。

源码:可关注 AutoGenCrewAI 等多 agent 框架的演化。 追问:「只能再加一章,加哪一章?」现在第 22 章已经补了 execution state surfaces。下一章我会把第 15 章的「成本」部分单独抽出来叫「Agent 经济模型」,讲清四家怎么用 model、cache、tool 和并发策略拼出可控的使用成本。对企业 agent 落地最有用。