📐 Harness 工程 · 中文翻译

13 跨领域的观察与意涵

13.1 架构模式目录

表 11 与表 12 收录在 11 个系统中识别出的 29 个复现设计模式:4 月版的 17 个(成员已更新)加上扩展语料库贡献或结晶的 12 个。

表 11:29 个复现架构模式目录(1/2):4 月版的 17 个,成员更新至 2026 年 7 月。
模式 描述 使用者
事件溯源 动作/观察追加到持久化事件日志 OpenHands、Pi(会话日志即树)、OpenCode(日志即队列;v2 表)
策略即代码 安全规则作为可执行配置 Codex(Starlark,带内联校验示例)、Claude Code(Hook)、Gemini CLI(TOML 模式)、Hermes(配置即策略 + 硬底线)、OpenCode(规则集)、Pi(扩展 Hook)
递归组合 智能体派生子智能体,带分叉/链接的上下文 Claude Code、Codex、OpenHands、OpenClaw;Hermes 中由配置门控,OpenCode 中可选
多态编辑 感知模型的编辑格式/工具集选择 Aider(提示词工厂)、OpenCode(工具注册表)
延迟加载 工具/技能对提示词隐藏,按需发现 Claude Code、Codex(BM25 tool_search)、Hermes(BM25 桥接工具),外加 8 个技能实现
模板方法 基类定义流程;子类覆写解析/格式化 Aider(Coder)、OpenHands(Agent)
协议接口 结构化子类型 / 面向可插拔组件的接口接缝 Mini-SWE-Agent、Pi(逐工具 Operations 远程化接缝)
LLM 摘要 LLM 压缩对话历史 9 个系统(除 Mini-SWE-Agent 外;Aider 为部分实现)
卡死检测 自动检测智能体的重复行为 OpenHands(5 种场景)、Gemini CLI(哈希+LLM 混合)、Hermes(先警告的签名)、OpenCode(死循环询问)、Mini-SWE-Agent(格式错误上限)
反思循环 带 lint/测试反馈的内层自我修正循环 Aider;表亲:Gemini CLI(编辑修复器)、OpenCode(LSP 反馈)
提示词缓存 面向缓存边界的提示词结构,或会话键复用 Claude Code、Codex、OpenHands(缓存层级)、Hermes(前缀规范化)、Pi(断点+TTL)、OpenCode(方言扇出)
上下文分叉 克隆父级状态以隔离子智能体 Claude Code、Codex、Hermes(共享缓存的后台分叉)
中间件管线 与循环体正交的可组合轮次级策略 Mistral Vibe
JIT 仓库上下文 分层 Markdown 上下文文件自动发现 + 按需注入 Claude Code、Codex、Gemini CLI、Mistral Vibe、Hermes、Pi、OpenCode、OpenHands
技能(能力包) 带 YAML frontmatter 的 SKILL.md 目录 9 个系统(除 Aider、Mini-SWE-Agent 外)
条件激活 技能/工具由环境或文件路径门控 Claude Code(paths)、OpenHands(PathTrigger)、OpenClaw(requires)
轮次级检查点 带回退与文件恢复的文件系统快照 Mistral Vibe(每用户消息)、OpenCode(影子 git,每步)、Hermes(影子 git 存储)、Pi(仅对话)
表 12:29 个复现架构模式目录(2/2):7 月语料库新增的 12 个模式。
模式 描述 使用者
智能体自维护记忆 后台子智能体抽取并整合跨会话记忆 Codex(两阶段、git 基线);Gemini CLI 中的人工把关变体(补丁收件箱)
外层验证循环 脚手架级裁判/守卫在轮次循环之外验证完成度 OpenHands(/goal 裁判 + 批评家)、Hermes(停止时校验)
自我改进技能循环 智能体撰写、修补并策展自己的能力包 Hermes;部分实现:Gemini CLI(技能抽取收件箱)
谱系压缩 压缩作为会话轮换,带可检索的祖先链 Hermes
会话树版本控制 头部可移动的只追加条目树;分叉/回退/分支摘要 Pi;OpenHands(对话树)
极简内核 / 扩展宿主 安全、沙箱、子智能体、plan 模式迁移到运行时事件总线 Pi
客户端/服务器 Harness 内嵌 API 服务器;每个 UI(TUI、Web、IDE、CI)都是客户端 OpenCode;OpenHands(智能体-服务器)
模型家族提示词矩阵 按模型家族/代际分派的独立基础提示词 Codex(服务端目录)、OpenCode(9 个提示词)、Hermes(门控块)
缓存方言扇出 同时发出所有供应商的缓存控制方言 OpenCode
语法感知的命令权限控制 命令经解析(tree-sitter),授予按参数元数限定作用域 OpenCode;Mistral Vibe(解析校验)、Hermes(去混淆匹配)
不可信内容定界 工具/网页结果包进污染标记,定界符消毒 Hermes、OpenHands(<UNTRUSTED_CONTENT>)
Harness 模仿 客户端呈现第一方 Harness 的身份(头部、提示词开场、工具名大小写)以骑上其订阅 OAuth 后端 Pi(Anthropic OAuth 上的 Claude Code 身份;ChatGPT 订阅的 Codex 后端)

13.2 双重缺席:没有智能体框架,没有代码 RAG

更广的 LLM 应用文献视为任何生产级智能体之核心的两项技术,在这 11 个系统中竟然全部缺席。888我们本来预期至少会在开源项目里找到一些 LangChain 或其他框架的使用。这种一致性让我们意外;寻找反例的工作(vendored 依赖、动态导入、转译的 TypeScript 构建)跑了好几周我们才接受这个结果。7 月复审对全部 12 棵代码树重复了清单与导入扫描,包括语料库新增的三个系统与元 Harness。 对本研究而言,这些缺席至少与存在同样有信息量。

缺席之一:智能体框架。

我们检查了每一份依赖清单,并在每棵源码树中检索广泛部署的智能体框架的导入:LangChain、LangGraph、LlamaIndex、AutoGen、CrewAI、Pydantic AI、Genkit、Haystack agents、Semantic Kernel、Google 的 ADK,以及若干更小的库(Smolagents、Swarm、Agno)。 在约 400 万行 Python、TypeScript 与 Rust 中,没有任何生产级智能体代码路径导入其中任何一个——这个结果值得从两个方向品味:Gemini CLI 连 Google 自家的框架(Genkit、ADK)都不用,而 Hermes 中仅有的 “LangChain” 字符串位于捆绑技能的文档里,教智能体用户可能会怎么用向量数据库。 两个边界情形值得精确说明。 Aider 随附一个可选的框架相邻扩展:其 /help 命令可以安装 llama-index,对 aider 自己的文档跑 doc-RAG——这是一个可选的功能依赖,不是智能体循环编排。 而 OpenCode 把内层的 LLM/工具管线委托给 Vercel 的 AI SDK——那是一个供应商抽象层,不是智能体编排框架,但它是语料库中第一个内层循环管线是第三方 SDK 的系统(一个自研替代客户端藏在特性开关之后,暗示该依赖是过渡性的)。

每个循环都用宿主语言的原生原语手写:asyncio(OpenHands、Mistral Vibe、Hermes)、阻塞式同步 Python(Aider、Mini-SWE-Agent)、Promise/异步迭代器(Claude Code、Gemini CLI、Pi、OpenCode、OpenClaw)、Tokio(Codex)。 每个工具注册表都围绕 Pydantic、Zod、TypeBox、Effect Schema 或 Rust 枚举定制构建。 每个提示词模板都是朴素的 Markdown、Jinja2 或字符串拼接。

缺席之二:面向代码的检索增强生成。

另一场平行的搜索覆盖向量库依赖(Chroma、Pinecone、Weaviate、Qdrant、Milvus、FAISS、LanceDB、sqlite-vec、向量模式的 Elasticsearch)、嵌入库,以及匹配 embedding、vector_store、vectordb、rag 或 retrieval 的目录或文件。 对代码检索而言,结果不变且如今覆盖 11 个系统:零。 例外都关乎会话记忆,而这里 7 月的图景确实变了:OpenClaw 的默认记忆插件(memory-core)现在跑混合的 sqlite-vec KNN + FTS5/BM25 检索,嵌入默认开启(供应商默认 OpenAI;本地 GGUF 模型可选;4 月时代的 LanceDB 扩展作为可选插件幸存),使 OpenClaw 成为唯一嵌入默认开启的系统——为了聊天召回,从不为了读源码树。 Hermes 在规模上展示了相反的选择:其核心的过往会话检索刻意是词法性的(触发器维护的 SQLite FTS5,BM25 加面向中日韩的三元组分词,“任何地方都没有 LLM 调用”),嵌入只限于可选的记忆插件。

11 个系统在代码检索上用什么取代了 RAG,汇总于表 13。

表 13:各系统使用的代码检索机制,取代基于向量的 RAG(2026 年 7 月)。
系统 用嵌入吗? 代码检索机制
OpenHands 否 GrepTool/GlobTool + 终端;上下文文件摄入(AGENTS.md、.cursorrules);tree-sitter 已不在 SDK 中
Aider 仅可选 /help 扩展(对 aider 自身文档的 doc-RAG) RepoMap:tree-sitter 符号抽取,配 token 预算约束的 PageRank 式排序
Claude Code 否 ripgrep 关键词检索 + BashTool + 按需文件读取;CLAUDE.md 自动发现
Codex 否 Rust 原生文件检索;AGENTS.md 从根到 cwd 的拼接
Gemini CLI 否 捆绑的 ripgrep + glob 工具;GEMINI.md 自动发现;MEMORY.md 项目索引;JIT 子目录上下文
Mistral Vibe 否 ripgrep + tree-sitter(bash 解析)+ 文件系统检索;git status 注入;JIT 嵌套 AGENTS.md
Mini-SWE-Agent 否 经 shell 工具的 grep 检索
Hermes 仅可选记忆插件 ripgrep 支撑的 search_files;对会话历史用 SQLite FTS5(BM25 + 三元组);LSP 仅用于写后诊断;无仓库地图
Pi 否 自动下载 ripgrep + fd 二进制(最新版;优先系统二进制),藏在 grep/find 工具后;祖先遍历上下文文件;会话检索是确定性的线性扫描
OpenCode 否 捆绑的 ripgrep(grep/glob,100 结果上限);∼\sim25 个自动下载的 LSP 服务器供给诊断(无持久索引);嵌套 AGENTS.md 惰性附加
OpenClaw 默认混合记忆检索(sqlite-vec KNN + FTS5/BM25;默认 OpenAI 嵌入器,本地 GGUF 可选),仅用于会话记忆,从不用于代码 代码检索不适用;标准文件系统 API
双重缺席为何重要。

第一个缺席印证了智能体设计者自己的建议。 Schluntz 与 Zhang 的 Building Effective Agents [16] 警告框架“常常制造额外的抽象层,遮蔽底层的提示词与响应,使它们更难调试”,并建议从原始 SDK 调用出发。 那条建议出现在 2024 年 12 月;我们 2026 年在这里跑的源码审计表明,每一家商业供应商都照做了。 值得指出这一点,因为更广的 Python LLM 应用社区在同一时期一直在框架抽象上持续投资。 生产级 SWE 智能体看起来运行在与通用 LLM 应用不同的复杂度预算上。 一旦智能体开始修改真实源码,手写可调试代码就胜过可复用抽象,因为失败模式(静默的提示词损坏、不透明的缓存、版本不兼容的工具 schema)变得昂贵到无法耸肩带过。

第二个缺席与 Rajasekaran 等人 [19](2025 年 9 月)的近期建议一致,他们偏好“即时”(JIT)检索并推荐混合方案:“我们不记忆整个信息语料库,而是引入文件系统、收件箱和书签之类的外部组织与索引系统,按需取回相关信息。” 那篇博文没有断然拒绝预索引检索,但它的实操建议全都指向 JIT 方法。 语料库中每个系统都遵循这一路径,即便面向仓库的代码检索是一个被充分研究过的领域:RepoCoder [60]、RepoBench [61] 与 CrossCodeEval [62] 都为代码构建检索管线,Long Code Arena [64] 提供匹配的长上下文评测。 Wang 等人的 CodeRAG-Bench [63] 恰好提出本节的问题——“检索能否增强代码生成?”——并发现增益跨任务高度可变:对文档查询与库使用场景可观,而对模型已有足够参数知识的任务则边际或为零。这些增益的不一致性,或许有助于解释为什么生产级 SWE 智能体干脆跳过 RAG 层,而不投资于任务依赖的检索路由。 原因是领域特有的。 代码携带稠密的确定性结构元数据——文件路径、语言服务器、tree-sitter 解析、类型信息——语义相似度检索无法复制它们(而 RepoAgent [65] 与 Aider 的 RepoMap 之类的结构感知工具直接利用它们)。 代码每分钟都在变,预索引的嵌入几乎从构造上就是陈旧的。 每个编码环境都已经内置了一个近乎最优的检索系统:ripgrep、find 与 glob。 在典型的 SWE 智能体任务上,RAG 增加运维成本(嵌入计算、向量库维护、漂移管理)却不提供边际价值。

观察 9。更广的 LLM 应用文献视为核心的两项技术,在全部 11 个系统中缺席——这一发现挺过了语料库三倍扩容和为期三个月的复审。没有任何系统在智能体运行时使用通用智能体框架(检查了 LangChain、LangGraph、AutoGen、CrewAI 等十余个;Gemini CLI 连 Google 自家的都不用);每个循环都用宿主语言的异步原语手写,OpenCode 把供应商抽象 SDK 用于内层管线是最接近的边界情形。没有任何系统用向量嵌入 RAG 做代码检索;全部依赖 ripgrep、tree-sitter、glob 与自动发现的 Markdown 上下文文件,而在需要会话规模召回的地方,生产级的答案是词法检索(Hermes 的 SQLite FTS5),或者——恰有一个默认配置(OpenClaw)——对聊天历史的混合嵌入,从不对源码树。生产级 Harness 运行在与通用 LLM 应用不同的复杂度预算上:当失败模式是修改真实代码时,可调试性与提示词透明度压过框架复用。第 14.2 节给这个缺席以历史解答。

观察 10。Anthropic《Effective Agents》工程系列(2024 年 12 月至 2025 年 9 月)描述的架构模式,与四个厂商原生系统(它们独立构建)中观察到的架构高度吻合。这反映的是共享的经验现实、公开指南的影响,还是两者皆有,是一个开放问题。

13.3 智能体间协议:向外采纳,向内留在进程内

双重缺席关乎两项在语料库中根本不出现的技术。 智能体间协议(ACP、A2A)则又是一种不同的模式——而且这是我们两次快照之间变动最大的维度。 ACP 如今作为一等生产依赖或实现出现在 11 个系统中的六个里:Mistral Vibe(agent-client-protocol==0.10.1,经协议暴露会话分叉、工作区信任与回退)、OpenClaw(网关转换器)、OpenCode(opencode acp 经 stdio 服务智能体侧)、Hermes(ACP 适配器与注册表模块)、OpenHands(一个 ACPAgent 类,下文讨论)以及 Gemini CLI(其 A2A 模块是面向网格角色的独立协议)。 语料库之外,xAI 的 Grok Build 发布第一天就带成文的 ACP 服务器模式(第 3.7 节;厂商文档记载,未经源码验证)。 语料库中的采纳没有一个是实验性的。

有趣的是位置——ACP 如今占据三种截然不同的架构角色:

  1. 1.

    编辑器 ↔\leftrightarrow 智能体(向外服务器)。这是 ACP [41] 的 LSP 角色:Zed、JetBrains 及其他 IDE 像驱动语言服务器那样驱动本地智能体。Mistral Vibe、OpenCode、Hermes、OpenClaw 与 Grok Build 都服务这一边界。

  2. 2.

    智能体即后端(向内宿主)。4 月时无人担任的角色:OpenHands 的 ACPAgent 把它的 step() 委托给外部 ACP 服务器,带针对固定的 claude-agent-acp、codex-acp 与 gemini --acp 二进制的供应商元数据——竞争对手的 Harness 成为 OpenHands 会话里可互换的大脑。第 14.4 节的元 Harness 用同样方式驱动它的 Goose 与 Qwen 适配器(驱动 TUI 的同时接 Kiro 的 ACP 权限流),而 Hermes 把一个 ACP 智能体当作模型传输来消费(GitHub Copilot 的 CLI 作为聊天后端)。为编辑器而建的协议,结果成了托管的接口。

  3. 3.

    跨厂商网格(A2A [42])。语料库中仍是 Gemini CLI 独有:远程编排器把本地 Gemini CLI 当作多厂商拓扑中的一个节点驱动,如今线上还带用量元数据。

表 14 列出每个多智能体系统在主智能体与其自己的子智能体之间使用的通信机制,以及其协议角色。

表 14:主智能体 ↔\leftrightarrow 子智能体通信与协议站位(2026 年 7 月)。
系统 主 ↔\leftrightarrow 子智能体 协议角色 子智能体跨进程?
Claude Code AgentTool 函数调用 + 上下文分叉 + XML 通知 智能体层无(ACP 由单独的适配器二进制服务) 否
Codex 带邮箱阶段的会话输入队列;类型化记录 智能体层无(codex-acp 适配器在外部) 否
Gemini CLI invoke_agent 在本地/远程会话协议之后 A2A 服务器(网格角色) 否(内部)
Mistral Vibe task 工具,进程内 asyncio ACP 服务器(编辑器角色;经协议回退) 否
OpenHands Task/delegate 工具,并发线程 ACP客户端/宿主:竞争对手 Harness 作为 step() 后端 否(自己的子智能体)
Hermes 进程内线程分叉;集群经 SQLite 黑板子进程 ACP 服务器(编辑器)以及 客户端(Copilot CLI 作为模型后端) 集群:是(数据库,非协议)
Pi 扩展派生操作系统进程,stdio 上的 JSONL 专有 JSONL RPC(∼\sim30 个命令)用于嵌入;ACP/A2A/MCP 按设计缺席 是(扩展;JSONL,非 ACP)
OpenCode task 工具,进程内子会话 ACP 服务器(智能体侧,stdio ndjson) 否
OpenClaw ACP 会话派生 经 RPC(子进程) 同一个 ACP 向内与向外 是

4 月版的“向内/向外”二分以精炼的形式幸存。 为协调自己的子智能体,九个多智能体系统中的八个仍使用进程内原语,或跨进程时使用标准协议之外的东西:Pi 的扩展派生说纯 JSONL 的操作系统进程,Hermes 的集群经一块 SQLite 黑板协调。 变了的是对整个 Harness 的向内消费:把竞争对手的智能体作为可换的后端托管——OpenHands 的 ACP 托管、Hermes 的 ACP 即模型传输、元 Harness 的适配器舰队——是 4 月尚不存在的生产模式,而 ACP 是它的通用语。 Pi 添了最后一个细节:它拒绝标准协议,却为同样的嵌入角色发明了一个专有的向外 RPC——证明即便标准被拒,面向外部的协议压力也是真实的。

观察 11。智能体间协议的站位已从两角色故事(向外:编辑器集成与网格;向内:无)演化为三角色故事。ACP 出现在 11 个系统中的 6 个,如今服务 (1) 其设计的编辑器↔\leftrightarrow智能体边界,(2) 协议设计简报之外的一个角色——Harness 托管,其中 OpenHands 把 Claude Code、Codex 或 Gemini CLI 作为可互换的 step 后端运行,Hermes 把一个 ACP 智能体当模型传输消费——以及 (3) 经 A2A(仍只在 Gemini CLI)的跨厂商网格。对一个 Harness 自己的子智能体,九个多智能体系统中的八个仍用进程内原语,或跨进程时用标准协议之外的东西(Pi 的 JSONL 扩展、Hermes 的 SQLite 黑板集群);OpenClaw 的 ACP 派生是唯一把子智能体协调路由到标准协议上的案例。实践者建议因此变得锋利:构建一个 ACP 服务器(它现在一次买来编辑器、宿主与元编排者);把自己的子智能体留在进程内;把 A2A 当作对跨厂商网格的押注——其规模化需求尚未被证明。

13.4 权衡框架

我们形式化五条根本的权衡轴:

轴 1:简单性 vs. 能力。

Mini-SWE-Agent 的极简脚手架据报道在 SWE-Bench Verified 上达到 74%+,而 Codex 大得多的代码库报告 69.1%。 这些数字不可直接比较(底层模型不同、评测运行不同、部署配置不同:Mini-SWE-Agent 无沙箱而 Codex 有沙箱),我们不从中得出正面对比的结论。 但这一差距在性质上说明:Codex 的额外代码并未投在原始的任务完成逻辑上;相当大的份额进了安全(跨平台沙箱)、用户体验(TUI、流式)、可扩展性(MCP、插件)与稳健性。 在生产级脚手架是否能在同等条件下的同一基准上产生可测量的改进,是本研究不回答的开放问题(效度威胁见第 15 节)。

轴 2:安全 vs. 自主性。

安全基础设施更多的系统(Codex、Claude Code)给智能体动作施加更多摩擦。 安全更少的系统(Mini-SWE-Agent、Aider)执行更快,但若无额外保障则不适合企业部署。

轴 3:供应商耦合 vs. 供应商无关。

Claude Code 与 Codex 利用供应商专属特性(提示词缓存、扩展思考、模型专属提示词),代价是厂商锁定。 基于 LiteLLM 的系统以供应商灵活性换掉这些优化。

轴 4:单体 vs. 模块化。

Codex 的 126-crate、百万行 Rust 工作区为类型安全与性能优化。 Mini-SWE-Agent 的单文件智能体最大化可理解性。 Pi 把整条轴搬进运行时组合:极简内核加扩展事件总线。 OpenClaw 的插件 SDK 与 OpenCode 的客户端/服务器拆分分别服务于可扩展性与可嵌入性。 光谱上的每个点服务不同的用户群体。

轴 5:脚手架复杂度 vs. 模型能力。

这是哲学上最有意思的一条轴。 Mini-SWE-Agent 有竞争力的基准表现证明,当前模型已足够强大,可以用极简脚手架成功。 生产级系统投资脚手架,不是因为模型完成任务需要它,而是因为用户需要它带来的安全、可靠性与工作流集成。