Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Claude Code VS OpenCode

架构、设计与未来

深度分析和对比三大 AI 编码智能体系统——OpenCode(开源基座)、Oh-My-OpenCode(多智能体编排层)和 Claude Code(Anthropic 商业级智能体)——从共性架构到独特创新,最终提炼出智能体设计的最佳实践。


语言切换: English Edition


三大系统

系统定位哲学
OpenCode开源基座模型无关、多界面、可编程
Oh-My-OpenCode编排层(OpenCode 插件)多智能体、极致自主、“人为干预即失败信号”
Claude Code商业标杆(Anthropic)安全优先、企业就绪、深度模型-工具协同优化

本书内容

  • 第一部分 — 从代码补全到自主智能体的进化史
  • 第二部分 — 共性架构:ReAct 循环、工具、会话、LLM 抽象、MCP、配置
  • 第三部分 — 每个系统的独特创新
  • 第四部分 — 深度剖析:Oh-My-OpenCode 如何作为 OpenCode 插件构建 13 万行编排层
  • 第五部分 — 哲学、工具、编排、可扩展性、安全的全面对比
  • 第六部分 — 从三个系统中提炼的智能体设计最佳实践
  • 第七部分 — 编码智能体的未来,以及思想实验:设计“Oh-My-Claude-Code“

适合谁读

对 AI 智能体架构感兴趣的资深工程师——无论你在构建自己的编码智能体、为团队评估工具,还是想深入了解这些系统底层的运作方式。


本书在 AI 辅助下生成。源码分析来自 OpenCode、Oh-My-OpenCode 和 Claude Code 代码库。

模型: gpt-5.4 (openai/gpt-5.4)
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第1章 — 编码智能体的进化史
Token消耗: 约3,100(估算)

1.1 从代码补全到自主智能体

如果把过去几年 AI 编程工具的发展压缩成一条主线,那么最重要的变化并不是“模型越来越会写代码”,而是“系统越来越能把代码工作闭环做完”。从 2021 年到 2026 年,编码智能体大致经历了三个时代:代码补全时代、对话副驾驶时代,以及自主编码时代。三者的差异,不只体现在模型能力上,更体现在系统是否能感知环境、调用工具、处理反馈,以及持续推进任务。

第一个时代是代码补全,时间大约集中在 2021—2022 年,以 GitHub Copilot、Tabnine 为代表。这一阶段的核心机制是“下一 Token 预测”。所谓 Token,可以把它理解为模型处理文本时的最小离散片段,它可能是一个汉字、一个单词的一部分,也可能是一段符号。模型根据光标附近的上下文,预测接下来最可能出现的代码片段。因此,这一代产品最擅长的是补完函数体、续写样板代码、生成重复性逻辑。它们像一个极强的自动输入法:速度快、侵入低、回报直接,但几乎没有自主性。它不会主动读项目,不会运行测试,也不会验证自己写出的代码是否真的成立。它的自主性几乎为零。

第二个时代是对话副驾驶,主要发生在 2023—2024 年,以 ChatGPT、Cursor Chat 为代表。这个阶段的重要变化,是交互粒度从“行级补全”提升到了“任务级问答”。开发者不再只是在光标处接受建议,而是直接用自然语言提需求,例如“给这个接口补测试”“解释这段并发逻辑”“把这个模块改成策略模式”。模型从续写器变成了指令跟随器。它能够理解意图,生成多段代码,解释错误栈,甚至跨文件提出修改方案。但这一阶段的系统仍然主要依赖人类推进工作流:用户自己复制代码、打开文件、运行命令、发现失败、再把错误贴回去。也就是说,它具备较强的语言理解与生成能力,却仍然缺少持续执行任务的能力,因此只能算低自主。

第三个时代是自主编码,时间大致从 2024 年延续到 2026 年,典型代表包括 Devin、Claude Code、OpenHands,以及本书重点讨论的 OpenCode 与 Oh-My-OpenCode 这一技术路线。在这个阶段,系统不再把“回答问题”视为终点,而是把“完成任务”视为目标。用户给出的不是一个局部指令,而是一个可验证的工程目标,例如“修掉这个仓库里的失败测试”“实现一个命令行参数解析器”“把登录流程改成基于会话的认证”。智能体随后进入一个循环:先理解目标,再读取代码、搜索符号、编辑文件、运行测试、分析报错、继续修复,直到停止条件满足。这里的关键变化是,模型被嵌入到了一个可执行的任务闭环里。

这一转折常被概括为“Devin 时刻”。它的意义并不在于某一个产品发布,而在于整个行业第一次把“AI 是否能像工程师一样独立推进真实软件任务”作为核心问题。一个很有代表性的观察指标是 SWE-bench。对非专业读者来说,可以把 SWE-bench 理解为软件工程领域的标准化考试题库:它从真实开源仓库中抽取历史问题,要求系统在既有代码库内完成修复,最后通过测试来验证答案是否正确。它不像普通代码生成基准那样只考一段函数,而是考查系统能否在真实仓库、真实依赖和真实约束中工作。短短两年间,公开系统在这一基准上的成绩从 13.86% 一路提升到 79.6%,这种跨越说明:行业竞争的重点已经从“谁更会补代码”转向“谁更会完成工程闭环”。

理解这一跃迁,就必须解释 ReAct。ReAct 不是传统计算机科学教材里的标准术语,它来自 Yao 等人在 2022 年提出的一种智能体范式,名字由 Reasoning 与 Acting 组合而成。可以把它翻译为“推理—行动协同框架”。它的核心思想是:LLM 不应只在脑中推理,也不应只机械调用工具,而应在循环中交替地产生推理轨迹与外部动作。比如,模型先判断“需要确认某函数在哪里定义”,然后调用搜索或跳转工具;拿到结果后,再推理“问题可能出在参数校验逻辑”,接着执行编辑或测试。这样一来,LLM 不再是一次性吐出答案的文本机器,而是系统中的决策引擎。它负责在每一步根据当前证据更新策略。

从系统设计角度看,ReAct 的价值在于把“不确定任务”拆解成“可观测、可纠正、可继续”的链式过程。传统单轮生成一旦出错,往往整段结果都要报废;而 ReAct 循环允许系统在每次工具返回后重新判断。它天然适合软件工程,因为编程不是一次性写作,而是持续试错、验证、收敛的过程。读文件是观察,写补丁是行动,跑测试是验证,读报错是再观察,这与工程师的真实工作流高度一致。

因此,所谓“从代码补全到自主智能体”的进化,本质上不是模型参数规模的线性增长,而是执行架构的范式转移。第一代系统只预测局部文本;第二代系统理解并回应指令;第三代系统则在工具、上下文、权限与反馈机制的支撑下,开始对真实软件任务负责。也正因为如此,本书后续比较 OpenCode、Oh-My-OpenCode 与 Claude Code 时,不会只比较谁接入了哪个模型,而会重点比较:谁的循环更稳,谁的工具更全,谁的上下文管理更强,谁更接近真正可用的自主编码系统。

模型: gpt-5.4 (openai/gpt-5.4)
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第1章 — 编码智能体的进化史
Token消耗: 约2,900(估算)

1.2 市场格局与技术分野

如果说上一节讨论的是技术演化,那么这一节讨论的就是产业定型。到 2025 年前后,AI 编码助手已经不再是单一产品类别,而是一个横跨补全、对话、半自主执行与全自主执行的多层市场。市场研究机构给出的口径虽有差异,但主流判断已经较为一致:2025 年全球 AI 代码工具市场规模约为 47 亿美元,预计到 2033 年增长至 146.2 亿美元。这个增长不是简单来自“更多人愿意买代码补全”,而是因为工具开始向软件工程流程的更高价值环节渗透,包括调试、重构、测试、代码审查、任务编排与团队协作。

当前市场中最具代表性的产品大致如下:

产品机构形态代表特征商业状态
GitHub CopilotGitHub / MicrosoftIDE 扩展、平台级服务自动补全起家,生态覆盖最广,ARR 约 8 亿美元商业化成熟
CursorAnysphere编辑器一体化对话、内联编辑、Agent 体验强,收入已超 1 亿美元高速增长
Claude CodeAnthropic终端与工程工作流工具强调安全、权限、企业可用性商业产品
DevinCognition自主编码系统以任务闭环和自主执行为卖点商业产品
OpenCode开源社区开源编码智能体基座多模型、多界面、可扩展开源
Aider开源社区CLI 协作工具Git 工作流友好,轻量直接开源
OpenHands开源社区自主软件工程平台面向任务执行与实验验证开源

仅从产品名录看,市场似乎已经足够拥挤;但如果从技术分野看,它仍处于快速分层阶段。最明显的一条分界线,是商业产品与开源产品之间的路线差异。

商业路线的优势首先是体验整合。以 Copilot、Cursor、Claude Code、Devin 为代表的产品,通常拥有更精致的交互设计、更稳定的云端服务、更统一的权限与计费体系,也更容易打磨端到端体验。它们可以把模型调用、上下文构建、索引、缓存、遥测、权限决策、协作能力全部封装在产品内部,让用户获得更低摩擦的使用感受。但它们的代价也很明确:更强的模型锁定、更强的平台依赖,以及更弱的源码可见性。开发者可以使用它们,却很难真正验证其内部如何决策、如何筛选上下文、如何处理失败恢复。

开源路线则走向另一端。OpenCode、Aider、OpenHands 的共同价值,不只是“免费”或者“可自行部署”,而是模型无关、源码可及、可按需改造。所谓模型无关,是指系统并不把自己绑定在某一家模型厂商之上,而是提供抽象层,让用户在不同模型、不同供应商之间切换。这对于今天的 AI 基础设施尤为关键,因为模型能力、价格、上下文长度、速率限制都在快速变化。所谓源码可及,则意味着系统的真实能力边界、失败模式与安全逻辑都可以被阅读、调试、替换。对资深工程师来说,这种透明性本身就是核心价值。

但“商业对开源”的划分仍然不够。更有解释力的,是自主性光谱。今天几乎所有编码产品都可以放在如下连续谱上:自动补全 → 对话 → 引导式 → 半自主 → 全自主。自动补全只处理局部续写;对话模式能理解任务但基本不执行;引导式系统可以根据用户命令调用部分工具,但关键步骤仍由人确认;半自主系统能在限定边界内持续执行多步操作;全自主系统则追求在较少人工干预下自行完成任务闭环。这并不是非黑即白的分类,而是工程设计中的连续变量。一个产品可以在文件编辑上是半自主,在网络操作上保持低自主;也可以在本地仓库中接近全自主,却在生产权限上严格收缩。

这个光谱解释了为什么“同样都叫 AI 编码助手”,实际产品体验却差异极大。Copilot 的强项是高频、低延迟、低心智负担;Cursor 擅长把对话、编辑与上下文整合在同一界面;Claude Code 强调在高能力执行与安全约束之间取得平衡;Devin 强调完整任务执行;而 OpenCode、OpenHands 则更像开源世界对自主编码操作系统的一次次逼近。

从投资和企业采购的角度看,下一阶段市场不会只奖励“模型最强”的产品,而会奖励“在某一自主性层级上最可靠”的产品。因为企业买的不是一次漂亮演示,而是可重复、可审计、可接入现有流程的工程能力。一个能稳定完成 60% 真实任务的半自主系统,往往比一个偶尔惊艳但经常失控的全自主系统更有商业价值。

因此,市场格局的真正分野,不在于谁先接入了最新模型,而在于谁定义了更合理的系统边界:谁决定何时自动执行、何时请求确认;谁把上下文做成稳定资产;谁把工具抽象做得足够清晰;谁能在体验、可控性与扩展性之间找到可持续平衡。本书后续的比较,也将沿着这条主线展开:在同一市场中,OpenCode、Oh-My-OpenCode 与 Claude Code 并不是简单的同类竞品,而是代表了三种不同的技术与产品组织方式。

模型: gpt-5.4 (openai/gpt-5.4)
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第1章 — 编码智能体的进化史
Token消耗: 约2,500(估算)

1.3 脚手架比模型更重要

过去两年,行业里最容易让人误判的一件事,是把编码智能体的进步简单归因于底层模型升级。模型当然重要,但如果只盯着模型,就会错过真正决定系统上限的部分:脚手架。Morph LLM 曾给出一个很有代表性的观察:同一个模型,放进不同的 Agent 脚手架后,在真实软件任务上的解决率可以相差 17 个问题。这个差距已经大到无法用“提示词写得更好”轻轻带过,它说明决定系统成败的,不只是大脑本身,而是大脑如何接入环境、组织记忆、调用工具以及从失败中恢复。

这里的“脚手架”并不是传统计算机科学教材中的标准术语,更接近工程界对智能体系统外层结构的通俗命名。为了避免误解,我们可以给出一个工作性定义:脚手架是围绕 LLM 搭建的整个执行系统,包括工具接口、上下文管理、权限模型、系统提示、状态持久化、任务分解机制、重试策略、错误恢复路径,以及人与系统之间的交互约束。换句话说,模型负责生成下一步决策,而脚手架决定模型能看到什么、能做什么、何时停下、出错后怎么办。

这个定义一旦成立,很多现象就不难理解。为什么同样使用顶级模型,有些产品只能做高质量问答,有些却能稳定完成跨文件修改?因为前者把模型当作会写代码的聊天机器人,后者则给模型配上了文件系统、搜索、测试、补丁、版本控制、会话恢复和权限决策等一整套执行设施。为什么有些系统越做越“聪明”,有些系统一遇到复杂仓库就迅速失真?因为真正的瓶颈并不总在语言能力,而常常在上下文选择错误、工具粒度失衡、反馈链路断裂、失败后无法收敛。

脚手架的重要性还体现在“能力放大”而不是“能力替代”上。一个强模型放进劣质脚手架,会因为工具缺失和状态管理混乱而浪费大量推理能力;一个中上水平的模型放进高质量脚手架,则可能通过更好的检索、约束和反馈,展现出接近更强模型的任务表现。这正是编码智能体区别于纯聊天产品的关键:聊天产品主要比较模型回答质量,编码智能体比较的是系统在真实环境中的闭环执行效率。

因此,本书会主动重定义比较框架。我们比较 OpenCode、Oh-My-OpenCode 与 Claude Code 时,比较的不是“谁接了更强的模型”,而是“谁构建了更强的系统”。更具体地说,我们会比较五类脚手架能力。

第一,工具系统。工具是否覆盖读、写、搜、跳转、执行、诊断、网络访问与外部集成?工具的输入输出是否对模型友好?一个坏工具即使功能存在,也可能因为返回噪声过大而让模型无法使用。

第二,上下文系统。系统是否知道该把哪些文件、哪些错误、哪些历史步骤送进上下文窗口?所谓上下文工程,已经逐渐替代早期的提示工程,成为编码智能体最核心的基础设施之一。

第三,控制系统。权限是否细粒度?哪些操作自动执行,哪些必须确认?有没有沙箱、快照、回滚与审计?自主性越高,控制系统越重要。

第四,恢复系统。一次编辑失败后,系统能否继续追踪错误、修正策略、减少重复试错?没有恢复能力,Agent 只是在不断重试同一种错误。

第五,编排系统。单 Agent 是否足够,还是需要多 Agent 分工?如何让探索、检索、实现、验证这些角色协同工作?这已经不是单一模型能力能解释的问题,而是系统架构问题。

这也是为什么“架构现在是首要差异化因素”并不是一句营销口号,而是一条工程事实。在模型快速趋同、接口快速标准化的背景下,单纯依赖模型领先建立护城河会越来越难;真正能形成持续差异的,是对脚手架的设计深度。谁更懂任务分解,谁更懂工具抽象,谁更懂上下文压缩与记忆保留,谁就更可能做出可靠的编码智能体。

从这个视角回看整个行业,很多争论就会变得清晰:我们今天讨论的核心已不再是“哪个模型最会写代码”,而是“什么样的系统最能把模型变成可工作的工程代理”。这也是本书的基本立场。模型是发动机,但脚手架决定这台机器最终是一辆可跑长途的汽车,还是一台只能原地轰鸣的试验机。

模型: gpt-5.4 (openai/gpt-5.4)
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第1章 — 编码智能体的进化史
Token消耗: 约3,000(估算)

1.4 本书研究对象

本书并不试图对所有 AI 编码产品做一份宽泛罗列式综述,而是聚焦三个具有代表性的研究对象:OpenCode、Oh-My-OpenCode 与 Claude Code。选择这三者,并不是因为它们覆盖了全部市场,而是因为它们恰好代表了三种极具解释力的技术路线:开源基座路线、基于基座的编排增强路线,以及独立商业产品路线。把它们放在一起,既能看到编码智能体的共同骨架,也能看到系统分化最明显的地方。

首先是 OpenCode。它可以被视为一个开源编码智能体基座,而不是单纯的命令行聊天工具。其技术栈以 TypeScript 与 Bun 为主,强调现代运行时、统一工程组织与较低的开发摩擦。在模型接入层,OpenCode 通过 Vercel AI SDK 打通了 20 个以上提供者,这意味着它天然具备较强的模型无关性。今天的开发者可以选择 Anthropic、OpenAI、Google,也可以根据成本、延迟、上下文长度与合规要求切换到其他供应商。从界面形态看,OpenCode 也不是“只有 CLI”那么简单,它同时延展出 CLI、TUI、Web、Desktop 等多种入口。这种多界面能力的意义,不只是覆盖更多用户,而是说明它从一开始就被设计成一个可复用平台,而非单点产品。

更关键的是,OpenCode 的开放性使其适合作为架构研究对象。研究者不仅可以使用它,还可以直接阅读它如何组织会话、抽象工具、管理权限、适配多模型、支持插件与协议扩展。对于一本讨论“编码智能体如何设计最好”的书来说,这种可审计性非常重要,因为我们需要比较的不是宣传材料,而是系统真实的结构与边界。

第二个研究对象是 Oh-My-OpenCode,以下简称 OMO。它不是一个从零开始重写的独立宿主,而是构建在 OpenCode 之上的插件化编排层。按照本书所采用的项目统计口径,OMO 拥有 1134 个 TypeScript 文件、约 12.9 万行代码,并组织出 11 个智能体、41 个钩子。这几个数字的意义并不只是“规模很大”,而在于它表明:在不推翻宿主系统的情况下,编码智能体的行为仍然可以通过编排层被大幅重塑。

OMO 的一个核心思想是“人为干预即失败信号”。这句话值得特别解释。它不是说人类不应参与,而是说如果系统在本应自主闭环的任务中频繁要求用户补步骤、补搜索、补判断,那么这说明编排层没有把任务真正接住。于是,OMO 把大量工作放在多智能体分工、背景任务、持续推进、钩子拦截、技能加载与上下文注入上,试图把 OpenCode 从“强大的开源基座”进一步推进为“更积极、更持续、更接近自主工程协作”的系统。就研究价值而言,OMO 让我们能观察一个非常重要的问题:在宿主能力基本不变的前提下,单靠编排设计到底能把系统性能推高多少。

第三个研究对象是 Claude Code。它代表的不是开源社区的可塑性,而是商业产品在安全、稳定性与企业落地方面的系统性工程。Claude Code 同样采用 TypeScript 与 Bun 技术栈,但它的设计目标与开源基座明显不同:它不是首先追求“可二次开发”,而是追求“可大规模可靠交付”。公开资料与代码分析显示,它引入了 ML 权限分类器来减少用户在高频操作中的确认负担,同时维持风险控制;它内置 61 个工具、100 个以上命令,并针对企业使用场景强化了可配置性、审计性与就绪度。所谓企业就绪,并不是营销词,而是指系统已经考虑身份边界、权限策略、成本控制、团队协作、插件治理与长期维护这些大规模部署必须面对的问题。

Claude Code 的研究价值,在于它展示了商业路线如何把“高能力”与“高可控”捆绑起来。开源系统通常更灵活,商业系统通常更收敛;开源强调可见性,商业强调稳定交付。理解这条路线,有助于我们避免用单一价值标准评判所有系统。

三者关系可以概括为:OpenCode 是基座,OMO 是基于基座搭建的编排层,Claude Code 则是一条独立演进的商业路线。OpenCode 提供开放宿主、协议适配、多模型与多界面能力;OMO 把重点放在多智能体编排、钩子系统与自主推进机制;Claude Code 则从商业产品出发,把权限、安全、命令系统、上下文控制与企业可用性打磨到极高完成度。

这种三角关系,正适合构成本书的比较框架。我们既可以观察共同点,例如它们都采用工具调用、会话管理、上下文构建与 ReAct 式循环;也可以观察差异点,例如 OpenCode 的开放宿主能力、OMO 的插件式增强路径、Claude Code 的安全与企业化体系。更重要的是,这三者共同提供了一个极佳的研究切面:如果把编码智能体看成一种新型软件系统,那么“基座如何设计”“编排如何增强”“商业化如何收敛”正是决定其未来形态的三个关键问题。

后续章节将围绕这一框架展开:我们先分析它们共享的系统骨架,再进入各自的独特设计,最后总结出面向未来的编码智能体最佳实践。换言之,本书研究的并不是三个产品的表面差异,而是三条路线背后对“什么是好智能体系统”的不同回答。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第2章 — 三大系统概览
Token用量: 约 10,800 input + 2,600 output

2.1 OpenCode:开源基座

如果把 AI 编码智能体看成一台“软件工程机器”,那么 OpenCode 更像一套可拆解、可替换、可二次装配的底盘。它不是先从“某个神级模型”出发,而是先把运行时、会话、工具、权限、界面、协议和扩展点做成一组可以组合的工程构件。也正因此,它在三套系统中最像“基础设施”,而不是“成品应用”。

从代码库看,OpenCode 位于 https://github.com/anomalyco/opencode/tree/main,采用 TypeScript 5.8 与 Bun 1.3.10 作为主运行时,顶层以 Turbo 驱动 monorepo。这里的 monorepo 并不只是“把包放在一起”,而是把不同交付面共享在同一类型系统与依赖图内:packages/opencode 是核心引擎,packages/app 是 Web 前端,packages/desktop 是 Tauri 桌面封装,packages/sdk/js 提供 JS SDK,packages/plugin 则暴露插件开发接口。换言之,OpenCode 的关键价值不是某一个包,而是这些包围绕同一内核形成的“多界面单内核”架构。

它的技术选型非常说明问题。模型层使用 Vercel AI SDK,即 ai 与一组 @ai-sdk/* provider 适配器,把 20+ 提供者收敛到统一流式接口。这个抽象的意义不只是少写适配代码,更重要的是把“模型切换”从产品级能力降格为配置级能力。服务层使用 Hono:packages/opencode/src/server/server.ts 中直接以 new Hono() 组装 HTTP 服务、SSE、认证与 OpenAPI 路由。持久化层使用 Drizzle ORM + Bun SQLite,src/storage/db.ts 清楚展示了 bun:sqlitedrizzle-orm/bun-sqlite 的组合,数据库文件默认落到全局数据目录中的 opencode.db。验证层几乎被 Zod 贯穿:智能体定义、事件定义、消息结构、工具参数、MCP 状态,都先是 schema,再是实现。UI 层则统一押注 Solid.js,终端 TUI、Web App、桌面壳共享相近的响应式心智模型。

这套技术栈带来的第一个架构亮点,是基于实例的上下文管理。src/project/instance.tsInstance.provide() 和按目录缓存的 state,把“当前项目目录、worktree、project 元信息”绑定为一个运行时实例。这里的 instance 不是传统面向对象里的单例,而更像按工作目录分片的执行上下文。对于编码智能体而言,这意味着多项目、多工作树、重载与销毁都能成为一等公民,而不是临时拼接的全局变量。

第二个亮点是命名空间组织模式。OpenCode 广泛采用 export namespace X { ... } 组织复杂模块,把 schema、类型、状态、行为收拢到同一语义容器中,例如 AgentMCPMessageV2Database。这不是教科书里最常见的模块风格,但对大型 TypeScript 代码库很有效:读者进入单文件后,能同时看到领域对象的“数据定义+生命周期+查询入口”。这类模式可理解为“语义邻接”,即让同一概念的所有工程切面物理上靠近,以降低认知跳转成本。

第三个亮点是类型安全事件总线。src/bus/bus-event.ts 通过 Zod 定义事件 payload,再动态组装 discriminated union。事件在这里不是字符串约定,而是可校验、可推导、可生成 schema 的协议对象。对于智能体系统,这很关键,因为消息、工具执行、MCP 状态变化、UI 通知往往跨越多个子系统;如果没有类型化事件,总线很快就会退化成不可维护的“字符串广播器”。

第四个亮点是 Zod schema 的全链路渗透。OpenCode 的工具定义、Agent 信息、MCP 资源、HTTP 接口、消息 parts 都先被 schema 化,再进入运行时。这种做法本质上是把“弱约束提示工程”尽量转回“强约束软件工程”。对于 AI 系统而言,这是一种重要设计哲学:LLM 可以是不确定的,但系统边界最好是确定的。

在交付界面上,OpenCode 并不满足于单一 CLI。它同时提供 CLI、Solid.js TUI、基于 Solid.js + Tailwind + Vite 的 Web 应用、基于 Tauri + Rust 的桌面版,以及基于 Hono 的 HTTP API。很多项目会把多界面当作“包装层”,但 OpenCode 把它们做成并列的一组入口。这直接提升了平台适配能力:本地终端用户、浏览器用户、桌面用户、外部编程调用者,都能共享同一会话与工具底座。

Agent 层面,OpenCode 内置 4 个主要智能体:build 是默认执行者,plan 是只读规划模式,general 负责一般性子任务,explore 则是快速探索型子智能体。src/agent/agent.ts 中可以看到它们的权限规则直接由 PermissionNext 组合而成,例如 plan 禁止编辑工具,而 explore 只允许搜索、读取、web 获取等探索型能力。这种“Agent = prompt + permission profile + model override”的设计非常干净:智能体首先是能力配置,而不是人格扮演。

工具系统同样体现了 OpenCode 的工程理性。src/tool/registry.ts 中可见其核心工具集大约 20 个,包括 bashreadglobgrepeditwritetasktodowebfetchwebsearchcodesearchskillapply_patchlsp 等。每个工具都带 Zod 参数 schema,工具暴露给模型前还可经过插件层的 tool.definition 改写。这里的“上下文丰富”指的不是大段自然语言,而是目录、worktree、sessionID、权限上下文、模型信息等结构化执行语境。工具不只是函数,更是受权限系统和项目实例系统约束的能力对象。

会话持久化方面,OpenCode 采用 SQLite + Drizzle 持久化 session/message/part/todo/permission 等表。更值得注意的是 MessageV2:它不是单块文本,而是多部分结构,可拆成 textreasoningfileagentsnapshotpatchsubtaskstep-startstep-finish 等 part。所谓“多部分消息结构”,可以理解为把一次 agent 交互分解成一串有类型的原子事件,而不是把所有内容糊成一段聊天记录。这为重放、压缩、审计、可视化和局部恢复都提供了基础。

协议支持则进一步说明 OpenCode 的平台野心。MCP 客户端实现相当完整,src/mcp/index.ts 明确支持 stdio、SSE、Streamable HTTP 三种传输,并整合 OAuth 流程。与此同时,OpenCode 还引入 ACP,即 Agent Client Protocol,并在 src/acp/* 下实现与 Zed 编辑器的集成。这意味着它不仅能“调用外部工具”,还能被外部开发环境作为 agent 内核来接入。

最后是插件系统。packages/plugin/src/index.ts 暴露了一组非常关键的钩子:autheventtoolchat.messagechat.paramschat.headerstool.execute.beforetool.execute.afterexperimental.chat.messages.transform 等。特别值得注意的是,它允许插件以异步函数方式返回钩子处理逻辑,等于把宿主生命周期切开,交给外部扩展逐段介入。OpenCode 因而不是“可配置软件”,而是“可编排宿主”。这正是它能成为 Oh-My-OpenCode 基座的根本原因。

简言之,OpenCode 的核心竞争力不是某个炫目的 agent prompt,而是把运行时、协议、工具、权限、会话与多端 UI 稳定地焊接在一起。它像 Linux 内核而不像整机产品:学习门槛更高,但一旦掌握,就能承载远比单体 CLI 更复杂的 agent 系统。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第2章 — 三大系统概览
Token用量: 约 11,600 input + 2,900 output

2.2 Oh-My-OpenCode:编排层革命

OpenCode 给出了一个优秀的开源基座,但真正把“单智能体编码工具”推进到“团队式软件生产系统”的,是构建在其插件接口之上的 Oh-My-OpenCode。它位于 https://github.com/code-yeongyu/oh-my-openagent/tree/main,并不是对宿主的大规模 fork,而是沿着插件、钩子、配置与自定义工具四条路径,把一个宿主改造成一层几乎完整的编排操作系统。

从体量上看,它已经不是“小插件”。按当前任务给定版本,它约有 1,134 个 TypeScript 文件、129,754 行代码;而从本地代码树实际观察,规模也确实处于 10 万行以上量级。这种量级意味着它不再是点状增强,而是一套平行于宿主核心的中层系统。更关键的是,这个中层系统仍坚持“插件化寄生”,不直接侵入 OpenCode 内核。这一点具有很强的方法论价值:如果扩展面足够强,复杂编排完全可以后置到生态层实现。

Oh-My-OpenCode 的哲学高度集中在 Ultrawork 宣言中。它的核心观点可以概括为两句:其一,人为干预越频繁,越说明系统没有真正自主;其二,AI 生成代码的目标不是“能跑”,而是“不可区分于高水平工程师写出的代码”。这里的“不可区分”不是文学修辞,而是一个极强的工程约束:不允许中途躺平,不接受半成品解释,不鼓励通过堆注释、堆套话、堆自我汇报来掩盖任务未完成。换句话说,Oh-My-OpenCode 不把 agent 当聊天助手,而把它当交付负责人。

这一哲学最终落在三层编排结构上。第一层是规划层,由 Prometheus、Metis、Momus 组成。Prometheus 负责通过访谈式交互抽取真实意图;Metis 负责在写计划前做漏洞分析,专门找隐藏假设、模糊边界和 AI 容易失败的点;Momus 则是计划审核者,对高准确性任务执行“不过审不准开工”的回路。第二层是执行层,由 Atlas 充当总调度器。它不直接承担所有一线工作,而是负责把计划拆成可执行单元、选择子智能体、检查回收结果、维持验证标准。第三层是工作者层,即一组专业化智能体,承担真正的编码、检索、顾问、搜索、视觉等任务。这个结构本质上对应软件组织中的“方案设计—项目经理—执行团队”。

从智能体编制看,Oh-My-OpenCode 已经形成一个带角色分工的“agent staff”。src/agents/builtin-agents.ts 可见其内置名册包括 Sisyphus、Hephaestus、Oracle、Librarian、Explore、Multimodal-Looker、Metis、Momus、Atlas 等;再结合文档与配置,还包含 Prometheus 及面向分类任务的 Sisyphus-Junior,整体可视为 11 个专业化智能体体系。Sisyphus 是主编排器,文档明确推荐 anthropic/claude-opus-4-6;Hephaestus 是深度执行者,定位为“Legitimate Craftsman”,推荐 openai/gpt-5.3-codex;Oracle 是高智商只读顾问,常用于设计、调试与战略判断;Librarian 偏外部知识与开源实现检索,文档给出 GLM-4.7 路线;Explore 则强调高速代码勘探。这里最值得注意的不是名字,而是“职责隔离”。模型不再一股脑承载所有工作,而是被拆配到不同认知任务上。

更进一步,Oh-My-OpenCode 引入了语义类别系统。类别不是“指定用哪个模型”的硬编码,而是“描述任务意图”的抽象层。也就是说,用户或上层 agent 说的是“这个任务属于 visual-engineering、research、orchestration 之类的语义类别”,系统再根据类别映射到合适的 agent、prompt 片段、工具集合和模型偏好。这种设计比直接指定模型高级,因为它把“任务语义”与“模型资源”解耦。类别描述的是问题本质,模型只是当前实现手段;模型会变,类别不会轻易变。

钩子系统是 Oh-My-OpenCode 最具工程爆发力的部分之一。项目文档明确强调其 41 个钩子、5 个层级的设计;而 src/hooks/index.ts 导出的 hook 工厂也显示出极强的横切覆盖力:Todo continuation enforcer、context window monitor、Ralph Loop、thinking block validator、rules injector、comment checker、background notification、interactive bash session、preemptive compaction、write guard、hashline read enhancer 等等。所谓“5 个层级”,可以理解为从会话入口、消息变换、工具前后、压缩前后到环境/状态维护的多层介入面。它让 OMO 不只是能加工具,而是能改行为、改节奏、改默认策略。

其中几项创新尤其值得单独指出。第一是 Ultrawork 模式:只要用户给出 ultraworkulw,系统就进入激进的自主工作范式,自动并行探索、长链执行、减少主上下文污染。第二是 Ralph Loop。它本质上是一种“失败后续推”与“中断后续滚”的机制:如果代理提前停止、没做完、被压缩打断,系统会构造 continuation prompt 把它重新推回工作态。第三是 Todo 强制完成。这里的 todo 不只是 UI 便利功能,而是工作协议;未完成 todo 会触发继续执行,而不是允许 agent 用一段貌似合理的总结逃逸。第四是智慧积累。Atlas 与相关管理器会把阶段性发现、计划、外部资料、子任务结论转化为更高层可复用的上下文资产,减少每次从零开始的损耗。第五是 Tmux 可视化多智能体。开启 tmux.enabled 后,后台子智能体不再是黑箱线程,而会在独立 pane 中可视化运行,形成一种“终端里的并行开发战情室”。

需要特别解释一个非标准术语:这里常说的“编排层”,并不是传统微服务里的 workflow engine。它更像“认知编排器”,负责调度不同 agent 的思考成本、上下文预算、权限边界与验证顺序。普通 workflow 主要协调 API 调用次序;而认知编排层协调的是推理、检索、执行与回收之间的智力分工。

因此,Oh-My-OpenCode 的真正革命性,不只是“agent 更多”或“模型更多”,而是把宿主从单线程智能体升级为一个可规划、可委派、可追责、可恢复的多角色系统。它证明了一件事:下一代编码智能体的分水岭,不在更大模型,而在更强编排。模型是大脑,编排才是组织。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第2章 — 三大系统概览
Token用量: 约 11,200 input + 2,700 output

2.3 Claude Code:商业标杆

如果说 OpenCode 是开源底座,Oh-My-OpenCode 是激进编排层,那么 Claude Code 则代表了商业产品化路径的上限样板。它位于 https://github.com/anthropics/claude-code/tree/main,是 Anthropic 官方推出的 CLI 编码智能体。与前两者相比,它最大的特点不是“更开放”,而是把安全、性能、上下文压缩、团队治理、远程控制与用户体验打磨到一个高度工业化的水平。

首先看 UI。外界常把 Claude Code 简化成“终端里的一个聊天框”,但源码显示它远不止是对 Ink 的薄封装。src/ink/* 下是一套相当深入的自定义终端渲染层,包含 renderer、reconciler、layout、termio、事件系统、组件集等,递归统计可见约 100 个文件级构件;若只看其核心自定义 Ink 实现,可概括为一个规模在数十文件级别的终端 React 子系统。与此同时,src/components 及其子目录又构成大量业务组件树,本地递归能观察到 52 个组件子目录,而整个界面层组织极为细密。这里所谓“终端 React”,指的是把终端当作一块可布局、可重绘、可交互的 UI 画布,而不是简单 stdout 文本流。这也是 Claude Code 在交互流畅性、状态过渡和复杂对话界面上的重要基础。

在工具层,Claude Code 的覆盖面非常夸张。src/tools.ts 汇总了 AgentTool、BashTool、FileReadTool、FileEditTool、FileWriteTool、NotebookEditTool、WebFetchTool、WebSearchTool、TodoWriteTool、LSPTool、MCP 资源工具、任务工具、团队工具、消息工具、REPL 工具、Workflow 工具等一整套工具谱系。按产品说明常被概括为 61 个内置工具;源码也显示它已超出传统“读写搜改跑”五件套,而进入工作流、协作、远程、计划、任务管理和浏览器交互层面。商业产品在这里的优势很明显:它不靠用户手动拼生态,而是默认给出一套高覆盖率工具面。

这些工具并非裸奔。Claude Code 有一套非常成熟的权限系统。src/types/permissions.ts 中可以看到对外暴露的模式包括 defaultacceptEditsbypassPermissionsdontAskplan,再加上内部的 autobubble 等运行态。用户视角通常可归纳为 4 类主模式:默认审慎、接受编辑、计划模式、近似跳过提示;系统内部再用自动分类与沙箱态细化执行策略。更重要的是,它把 ML 分类器引入权限决策链,permissionSetup 一带可以看到“pending classifier check”这类机制。也就是说,Claude Code 并不满足于静态规则,而尝试用模型或分类器判断“这次 Bash/Agent 调用是否可自动批准”。这是一种典型商业化优化:减少打断,但不直接牺牲安全。

会话持久化方面,Claude Code 使用 JSONL 存储转录。src/utils/sessionStorage.tsgetTranscriptPath() 和大量 transcript 读写逻辑表明,每个 session 本质上都被持久化为增量 JSONL 日志,而不是关系型数据库。JSONL 的优势是追加写便宜、恢复简单、便于流式处理,也更适合超长对话日志。围绕这一层,Claude Code 还构建了多策略上下文压缩:src/services/compact/compact.ts 不只是“摘要一下”这么简单,而是包含图片剥离、附件重注入、token 预算控制、部分恢复、文件再注入、技能再注入等复杂策略。这里的“上下文压缩”可以衍生解释为:当历史上下文过长时,系统不是粗暴删除,而是把不再需要逐字保留的信息变成更稀疏但仍可恢复的表示。这属于 context engineering,而非传统 prompt engineering。

成本治理是 Claude Code 的另一个商业级特征。src/cost-tracker.ts 中可见其原生维护 totalCostUSD、model usage、input/output/cache token、web search 次数、工具耗时、API 耗时、lines added/removed 等数据,并支持 session 恢复时继续累计。注意这里追踪的是 USD,而不是单纯 token。这一点很重要:在企业与团队环境里,token 只是底层计量单位,真正影响预算与治理的是货币成本。Claude Code 直接把经济性做成一等公民,而不是留给用户自己算账。

记忆系统也体现了产品成熟度。源码中有 memdirSessionMemoryteamMemPathsteamMemPrompts 等模块,表明它不仅有项目级记忆,还有团队级与会话级的组织方式。可以把它粗略理解为四类记忆:即时会话记忆、项目配置记忆、团队共享记忆、压缩后长期记忆。这里的“记忆”并不神秘,它本质上是把过去交互中高价值、可复用、与未来决策相关的信息,转化为结构化可回收上下文。

企业特性则是 Claude Code 与开源系统拉开距离的关键。源码中存在 remote、bridge、policy、managed settings、team memory 等模块,说明它支持远程管理设置、团队记忆、策略限制、远程控制与组织级能力开关。这意味着它不仅服务个人黑客,还服务有合规边界、审计需求、统一配置诉求的组织用户。很多开源 agent 在“个人体验”上很强,但一到企业环境就会遇到配置漂移、权限不一致、审计缺失的问题;Claude Code 明显从一开始就在解决这类问题。

在多智能体方向,Claude Code 也早已不是单 agent。AgentTool 负责生成子智能体,DreamTask 负责后台记忆整理类任务,SendMessageTool 则提供 agent 间消息通信。也就是说,它已经拥有“创建—运行—通信—回收”这一套多智能体基本设施,只是表达方式相对克制,没有像 OMO 那样把编排哲学推到台前。这种差异很典型:商业产品更重稳定接口与默认体验,社区系统更愿意显性暴露复杂编排能力。

最后是安全工程。Claude Code 使用 @anthropic-ai/sandbox-runtime,在 src/utils/sandbox/sandbox-adapter.ts 中把 Claude 的权限规则映射到 OS 级沙箱约束。结合 Linux 下 bubblewrap 痕迹、跨平台 sandbox adapter、策略写保护等实现,可以看到它把“权限提示”与“系统隔离”结合了起来。用户给出的“通过 bubblewrap/Seatbelt 等 OS 级沙箱减少 84% 权限提示”这一结论,正揭示了它的核心思路:最好的权限体验不是更聪明地弹窗,而是从根上减少需要弹窗的危险面。

因此,Claude Code 之所以成为商业标杆,不是因为它“模型最好”,而是因为它把工具、权限、压缩、记忆、成本、远程、企业治理、沙箱与 UI 统一成了一套产品工程。它证明了另一个方向:编码智能体要想进入主流生产环境,必须从“会写代码”升级为“会被管理、会被预算、会被信任”。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第2章 — 三大系统概览
Token用量: 约 9,900 input + 2,100 output

2.4 速览对比表

下面给出三套系统的高密度速览。需要注意的是,表中“智能体数”“工具数”“钩子数”等指标都带有版本性:它们不是永恒常数,而是特定代码快照下的工程观察值。因此,读表时更应关注其设计倾向,而不是把每个数字当作不可变真理。

维度OpenCodeOh-My-OpenCodeClaude Code
核心语言TypeScriptTypeScriptTypeScript + React/Ink
运行时Bun 1.3.10BunBun
架构类型开源 agent 宿主/基座基于 OpenCode 插件的多智能体编排层Anthropic 官方商业 CLI
代码库路径https://github.com/anomalyco/opencodehttps://github.com/code-yeongyu/oh-my-openagenthttps://github.com/anthropics/claude-code
模型支持通过 Vercel AI SDK 接 20+ provider多模型混编,按角色分配模型以 Anthropic 生态为核心,兼顾多模型与企业能力
智能体数内置 4 个主力:build、plan、general、explore约 11 个专业化智能体体系单主体验为主,但有 AgentTool、DreamTask、SendMessageTool 等多智能体设施
工具数约 20 个核心工具在 OpenCode 之上继续扩展,含任务、LSP、AST、tmux、session 等增强工具约 61 个内置工具
钩子系统插件钩子完整,含 config、tool、event、chat、tool before/after 等41 个钩子,5 个层级,强行为注入有 hooks、policy、settings、sandbox 等,但外部扩展面更受控
UICLI、Solid.js TUI、Web、Desktop、HTTP API复用 OpenCode UI,并增加 tmux 可视多 agent自定义 Ink 终端 UI,组件层极深
存储SQLite + Drizzle ORM继承宿主会话,并增加任务/恢复/智慧状态层JSONL transcript + 多层记忆/压缩机制
权限模型规则驱动,Agent 绑定权限画像在宿主权限上叠加更强流程纪律多模式权限 + ML 自动批准 + 沙箱协同
MCP 支持完整客户端;stdio/SSE/HTTP;OAuth继承并扩展,且整合 skill-embedded MCP强支持 MCP,并纳入产品化工具体系
上下文管理Instance 上下文、MessageV2 多 part、可压缩多 agent 分流 + Ralph Loop + Todo 延续 + 智慧积累JSONL 持久化 + 多策略 compaction + 记忆系统
成本追踪有消息 token/cost part,但不以产品特性突出更关注任务完成与编排效率原生 USD 成本追踪、按模型统计
可扩展性极强:插件、SDK、协议、工具定义极强:在不 fork 宿主的情况下重构行为层中等偏强:有插件/agents/hooks/MCP,但边界更可控
部署方式本地 CLI、桌面、Web、Server 模式作为 OpenCode 插件安装与运行官方 CLI,本地/远程/团队模式
许可证MITSUL-1.0商业/官方产品分发逻辑
主要优势开放、模块化、协议齐全、可二次开发高自主性、高编排强度、任务不轻易中断安全、稳定、企业化、成本与权限治理成熟
主要短板默认编排深度不如 OMO,产品化治理不如 Claude Code复杂度高,学习曲线陡,系统行为更激进开放性弱于开源体系,深度定制受限

从优势分布看,OpenCode 最强的是“开放性”。它像一个面向 agent 时代的操作系统内核:协议全、扩展面大、技术栈现代、架构整洁,适合作为研究、二开、定制产品的母体。Oh-My-OpenCode 最强的是“自主性”。它不是简单增强,而是把编排、恢复、强制完成、角色分工、上下文分流做成系统默认行为,极适合追求高吞吐和长任务闭环的重度用户。Claude Code 最强的是“安全性与工业成熟度”。它把权限、压缩、成本、远程、团队治理、沙箱和 UI 工程打磨到可进入企业日常流程的级别。

但三者也都带有各自局限。OpenCode 的问题不是弱,而是“太像底座”,因此默认体验更依赖使用者自己建塔。Oh-My-OpenCode 的问题不是能力不足,而是能力过强后带来的复杂度上升:当系统拥有太多代理、钩子和自恢复机制时,调试与心智负担会同步上升。Claude Code 的问题则是典型商业权衡:为了安全、品牌一致性和组织可控,必须牺牲部分底层开放面。

这三者实际上构成了一个很清晰的基本权衡三角:开放性、安全性、自主性。OpenCode 把重心放在开放性,Claude Code 把重心放在安全性,Oh-My-OpenCode 则把重心推向自主性。三者都不是“全都要”,而是在不同目标函数下作出不同最优解。对资深工程师而言,最重要的启示并非选边站,而是看清这一点:下一代 AI 编码智能体的真正竞争,不会只发生在模型排行榜,而会发生在这三个顶点之间的系统设计取舍上。

从本书后续章节的角度看,OpenCode 代表“可塑底盘”,Oh-My-OpenCode 代表“认知编排”,Claude Code 代表“工业产品化”。把这三者合起来看,才可能逼近一个更理想的答案:既开放到可扩展,又安全到可托付,还自主到足以独立完成复杂工程任务。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第3章 — 核心循环:ReAct范式
Token用量: 约 18,000 input + 2,400 output

3.1 思考-行动-观察循环

三套系统虽然产品形态不同,但其执行内核都可归结为 ReAct:先 Reason,再 Act,再根据结果 Observe,然后继续下一轮。这里的关键不在于“模型会不会思考”,而在于系统把一次回答拆成一个可中断、可追加、可恢复的循环。用户输入进入系统后,首先会触发 system prompt assembly,也就是把默认系统提示、工具清单、权限规则、项目上下文、记忆与附加约束拼成可发送给 LLM 的运行态提示。随后 LLM 开始生成流:可能包含普通文本、reasoning/thinking 片段、以及 tool call。工具执行后,结果不会直接“显示完就结束”,而是会被结构化追加回上下文,成为下一轮推理的观察材料。于是,一个回答实际上是一串小回合,而不是一次性吐完的长文本。

把这个过程抽象后,可以写成如下伪代码:

user_input
   ↓
assemble_system_prompt()
   ↓
while not stop_condition:
    stream = llm.generate(messages, tools, thinking)
    for chunk in stream:
        render_text_or_reasoning(chunk)
        if chunk contains tool_call:
            result = execute_tool(chunk.tool_call)
            append(tool_result_message(result))
            continue loop
    append(assistant_text_message)
    if no tool_call:
        break
return final_response

OpenCode 的实现最“教科书化”。session/processor.tsSessionProcessor.create().process()while (true) 驱动主循环,再通过 LLM.stream(streamInput) 订阅 stream.fullStream。流里被拆成 reasoning-startreasoning-deltatext-deltatool-calltool-resultfinish-step 等事件,分别写回 MessageV2 的不同 part。也就是说,OpenCode 并不把一次 assistant 输出看成一段字符串,而是看成一组带类型的事件片段。其好处是 UI、持久化、审计、重放都能对齐同一个结构。尤其在 tool-call 之后,工具结果进入消息 parts,再由返回值决定是 continuecompact 还是 stop,这正是一个标准 ReAct 状态机。

Claude Code 的写法更工业化。QueryEngine.ts 负责回合生命周期与上下文装配,query.ts 则承载超长的主循环逻辑。这里最关键的是对 tool_use / tool_result block 的处理:模型流式产出 tool_use 块,系统将其缓存到 toolUseBlocks,并用 ToolUseContext 维护权限、消息、abort、agent 身份、UI 状态与后续附件注入所需的执行上下文。随后 runTools()StreamingToolExecutor 执行工具,再把 tool_result 重新规范化为下一轮 user-side message。Claude Code 的特点不是“也有 ReAct”,而是把 ReAct 做成了可恢复、可预算、可并发、可 hook 的生产级循环。

OMO 在这一层并没有重写 OpenCode 内核,而是选择“寄生式增强”。它继承 OpenCode 的处理器与消息模型,但通过 tool.execute.beforetool.execute.afterchat.messageexperimental.chat.messages.transform 等钩子,在循环的关键边界插入自己的逻辑。tool.execute.before 可以改写任务委托参数、启动 Ralph Loop;tool.execute.after 可以截断输出、注入恢复信息、监控上下文;experimental.chat.messages.transform 则在真正发往模型前补充上下文并校验 thinking block。换句话说,OMO 不是换了一个新循环,而是在宿主循环的“关节点”上装了更多齿轮。

这里还要解释一个非标准 CS 术语:Extended Thinking。它不是传统教材中的算法术语,而是近两年大模型系统中的工程概念。可把它理解为“模型在正式输出前,系统显式保留一段更长的中间推理轨迹,并允许这段轨迹与工具调用形成连续状态”。它不像编译原理中的 IR,也不像经典 AI 里的显式搜索树;更接近一种“被流式暴露的内部工作记忆”。因此,Extended Thinking 的价值不只是“想得更久”,而是让系统有机会校验 thinking block、在 tool use 前后保持推理连续性,并把原本黑盒的一次生成,改造成可控制的长链条执行。

还要看到一个很容易被忽略的差别:三者虽然都在做 ReAct,但“循环的拥有者”并不相同。OpenCode 的循环主要由 session runtime 持有,因此更像宿主内核;Claude Code 的循环则由 query engine、budget、hooks、tool orchestration 共同持有,因此更像一个分层控制系统;OMO 则把“是否继续”部分外移到 hook 与 continuation 机制,使循环从“单一控制器”演化为“宿主循环 + 外围续接器”的双层结构。对于未来 agent 设计,这意味着一个关键原则:真正可扩展的 ReAct,不应把循环写死在模型调用函数里,而要把推理、工具、上下文追加、停止决策拆成可插拔的边界。

从架构哲学上看,三者共享同一个答案:AI 编码智能体并不是“会回答问题的聊天机器人”,而是“围绕 LLM 建立的循环式执行机”。OpenCode 给出最清晰的最小实现,Claude Code 把它推向产品级稳态,OMO 则证明:只要宿主暴露足够好的 hook,ReAct 循环本身就能成为二次编排的平台。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第3章 — 核心循环:ReAct范式
Token用量: 约 18,300 input + 2,300 output

3.2 流式处理架构

ReAct 循环要想在产品里成立,前提不是“模型能调工具”,而是系统必须能把 LLM→运行时→UI 的数据流稳定地搬运出去。也因此,流式处理 architecture 是三套系统的第二层共同骨架。所谓“流式”,并不只是逐字显示文本,而是把 reasoning、text、tool_use、tool_result、progress、attachment、error 等异质事件在时间上连续送达,并在尚未结束时允许系统作出反应。真正困难的地方不在首屏速度,而在于这条流里混有可执行事件、部分结果、并发子流和中途中断。

OpenCode 的流式路径相对直接。session/processor.ts 调用 LLM 流接口后,按事件类型逐个消费 fullStream,然后把 reasoningtexttoolstep 片段更新到 MessageV2。这种设计的优点是“单流单账本”:模型给出什么,处理器就把什么落到结构化 part 中,UI 与存储读同一份状态。借助 Vercel AI SDK,OpenCode 天然获得统一的 streaming event 语义,因此文本增量、reasoning 增量和 tool call 可以走同一个分发器。它的优势是清晰;代价是复杂并发场景大多留给上层扩展去处理。

Claude Code 则显著更复杂。query.ts 里一边消费模型流,一边维护 assistantMessagestoolUseBlockstoolResultspendingToolUseSummary 等多个缓冲区;当 tool_use 产生时,可以选择传统的回合后工具执行,也可以启用 StreamingToolExecutor 边收边跑。后者的意义在于:模型还没完全结束输出,工具已经可以排队、并发、安全地启动。与此同时,它仍然要求结果按接收顺序回灌,避免 UI 与 transcript 出现错序。这里其实涉及一个经典系统问题:背压(backpressure)。背压不是教材里只属于网络协议的概念,在 agent 系统里,它指“上游 LLM 产出 tool_use 太快,而下游工具执行、权限确认、UI 渲染来不及消费”时,系统如何避免内存膨胀、顺序错乱与状态丢失。Claude Code 通过队列、并发上限、context modifier、abort controller 和 synthetic tool_result 共同吸收这类压力。

另一个挑战是 部分工具结果。很多工具不是瞬时返回,而是会先产生 progress,再给出最终结果;或者在 streaming fallback、用户中断、权限拒绝时留下“半拉子状态”。OpenCode 的做法偏保守:工具 part 从 pending→running→completed/error,状态机相对紧凑。Claude Code 则更强调“不留悬空块”:即使流中断,也会通过 yieldMissingToolResultBlocks()StreamingToolExecutor.getRemainingResults() 合成缺失的 tool_result,确保每个 tool_use 都有可追踪的闭环。这不是 UI 小修小补,而是协议一致性要求;否则后续 API 调用会因 thinking/tool block 不匹配而崩坏。

OMO 面对的新增难题是 多智能体并发流。它自己并不重写底层 streaming parser,但在 OpenCode 之上又叠加了后台子 agent、continuation、task notification 和 hook 注入。于是,从 UI 角度看,用户并不是只接收一个 assistant 的单线流,而是可能接收主线程输出、后台任务完成通知、Ralph Loop 续接提示、todo continuation 倒计时触发后的再注入消息。此时“流”不再只是字节序列,而是多来源事件总线。OMO 的工程重点因此变成:怎样在不破坏 OpenCode 主流的前提下,把额外的事件插到正确时机,比如在 tool.execute.after 后监控上下文,在 experimental.chat.messages.transform 前修补 thinking block,在 session.idle 事件上决定是否再续一轮。

还有一个常被低估的问题是 UI 一致性。文本 token 可以天然逐步显示,但 tool result、attachment、后台通知并不总是适合“边来边画”。OpenCode 因为 part 结构比较整齐,UI 可以按类型稳定渲染;Claude Code 则需要同时处理 tombstone、summary、interruption message、hook attachment 等更多中间态,因此它更强调 transcript 与 UI 双重一致——既要让用户看得懂,也要让后续恢复与重放不失真;OMO 再往上叠加多智能体通知后,UI 的职责进一步从“渲染内容”升级为“表达系统状态”。这说明流式架构的终点不是更炫的界面,而是让用户始终知道:现在是谁在输出、哪个工具正在运行、哪一段结果是暂态、哪一段已经成为历史事实。

如果说 OpenCode 的 streaming 更像“模型流解析器”,Claude Code 更像“带流控的多阶段执行管线”,那么 OMO 则更接近“附着在主流上的事件编排层”。三者共同说明了一点:流式架构的本质不是前端动画,而是 状态传播。谁拥有更清晰的状态边界,谁就更能处理异常、并发与恢复。

从智能体设计角度看,未来更好的方案应当同时满足四点:第一,事件类型统一,文本、thinking、tool、attachment 都能进入同一抽象;第二,工具执行必须支持顺序与并发混合调度;第三,任何中断都要能补全协议闭环,不能留下 orphaned tool call;第四,多智能体事件必须与主会话流隔离但可桥接。只有做到这一点,流式传输才不只是“看起来更快”,而是真正成为 agent runtime 的主动脉。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第3章 — 核心循环:ReAct范式
Token用量: 约 18,600 input + 2,500 output

3.3 停止条件与循环控制

一个 agent 是否优秀,往往不体现在它“能循环多久”,而体现在它“知道什么时候该停,什么时候不该停”。ReAct 的最后一层因此不是推理,也不是工具,而是 loop control。正常完成时,模型在没有进一步 tool_use 的情况下结束,系统输出最终文本并收束本轮;遇到上下文溢出时,可能先 compact 再继续;命中 maxTurns、token budget、task budget、用户中断或不可恢复错误时,循环则必须终止。停止条件本质上是对三种资源的治理:上下文窗口、金钱/算力预算、以及用户注意力。

OpenCode 的停止逻辑最简洁,也最能看出 ReAct 的原型形态。session/processor.tswhile (true) 中处理一轮流后,最终只返回三类结果:continuecompactstop。如果 SessionCompaction.isOverflow() 判断超窗,则进入 compact;如果工具被拒绝且配置要求中断,或消息本身记录了 error,则 stop;否则继续下一轮。它还有一个很有代表性的保护:对连续三次完全相同的 tool call 做 doom_loop 检测。这里的 doom loop 也不是经典 CS 术语,而是 agent 工程里的经验概念,指模型反复调用同一工具、带着同样输入、却没有取得新信息的“自陷循环”。

Claude Code 把停止条件扩展成完整的控制面。query.ts 不仅有 maxTurns,还有 blocking limit、reactive compact、MAX_OUTPUT_TOKENS_RECOVERY_LIMIT、stop hooks、token budget continuation 与用户 abort。tokenBudget.ts 甚至明确区分“还可以继续”与“虽然没完成但已经收益递减”,即所谓 diminishing returns。这里很重要的一点是:Claude Code 不是只问“能不能继续”,还问“继续是否值得”。因此它同时处理两类失败:一类是 agent 想停但不该停,例如输出被 max_output_tokens 截断,于是系统自动注入“直接继续,不要道歉”的恢复消息;另一类是 agent 不停但该停,例如 stop hook 明确返回 preventContinuation,或 token budget 已进入收益递减区间。这种双向控制,使 Claude Code 更像一个带刹车与离合的循环控制器,而不是单纯的 while-loop。

OMO 的问题则更有研究价值,因为它展示了“增强控制”如何滑向“过度控制”。Ralph Loop 通过 session.idle 事件检测完成承诺 completion_promise;若未完成,就自动注入 continuation prompt,并在达到 max_iterations 前不断续接。从执行力角度看,这很强,因为它把“别中途停下”编码成了系统机制。但它也带来一个明显反模式:Ralph Loop 可能覆盖正常停止。也就是说,主循环本来已经在一个合理局部点停下,准备把控制权还给用户;而外层 continuation 机制却把“还能继续”误判成“必须继续”。类似地,todo-continuation-enforcer 在 session.idle 后检查未完成 Todo,只要条件满足就启动倒计时并再次注入。这种设计解决了 agent 过早收工的问题,但也可能把“阶段性完成”与“任务未完结”混为一谈。

于是,第一个经典失衡是“智能体想停但不该停”。典型场景包括:输出因 token 截断、中间工具结果尚未回灌、用户原目标尚未完成却只产出阶段性总结。对这种情况,继续机制是必要的。第二个失衡则是“智能体不停但该停”。典型场景包括:重复调用同一工具、为了满足 Todo 形式而机械续写、Ralph Loop 在用户并不需要更多动作时仍持续注入。前者损害完成率,后者损害可控性与成本。很多 2025—2026 年的 agent 产品,实际上都在这两个极端之间反复摆动:太容易停,用户觉得“它半途而废”;太不容易停,用户又会觉得“它开始自我表演”。

这也是为什么“停止”不能只被实现成一个 finish reason。更准确地说,它应该是一张原因表:模型自然结束、工具链未闭环、预算耗尽、窗口溢出待压缩、用户显式中断、hook 禁止继续、外层 orchestration 强制续接、或错误恢复中止。只有当这些原因在系统内部被区分开,产品层才能进一步决定:是提示用户、自动恢复、进入 compact、还是彻底结束。Claude Code 在这方面最成熟,因为它已经把中断消息、max turns attachment、stop hook summary、budget continuation 等都显式化;OpenCode 则提供了简洁但清楚的 continue/compact/stop 三岔口;OMO 的经验价值在于提醒开发者,外层 continuation 必须认识宿主循环的停止语义,否则就会把“协助完成”变成“强制不停”。

从更好的 agent 设计看,停止策略应遵循四条原则。第一,终止必须分层:模型层停止、工具层停止、会话层停止、外层编排停止不能混成一个布尔值。第二,停止要可解释:是 budget、max turns、permission denial 还是 hook 阻止,系统应显式记录。第三,继续要有证据:只有存在未闭环工具、明确未完成任务、或恢复消息时才自动续接,而不是因为“还有 Todo”就一律继续。第四,用户优先于编排器:任何外层 loop 都不能长期压过用户中断与显式完成。

因此,循环控制的最高原则不是“让 agent 永不放弃”,而是“让 agent 在正确的边界上坚持”。OpenCode 提供最朴素的循环出口,Claude Code 展示生产级多重刹车系统,OMO 则提醒我们:自治增强一旦缺乏停止层级,就会从可靠性优化转化为控制权侵蚀。这正是构建下一代编码智能体时最值得吸取的教训之一。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第4章 — 工具系统设计
Token用量: 约 13,500 input + 2,200 output

4.1 工具定义范式

工具系统本质上是 Agent 的“外设总线”。模型本身只会生成 token,真正让它接触文件系统、Shell、网络与子任务的,是 tool abstraction。三套系统都承认这一点,但其定义范式并不相同。

OpenCode 采用 Tool.define() 工厂函数,核心位于 packages/opencode/src/tool/tool.ts。它要求每个工具显式声明 iddescriptionparametersexecute,其中 parameters 基于 Zod。Zod 可以理解为一类 TypeScript runtime schema validation library:TypeScript 只在编译期检查类型,运行时类型会被擦除,而 Zod 则把“类型描述”保留下来,在程序真正执行时继续验证参数是否合法。因此,OpenCode 的工具不是“相信模型会传对参数”,而是“先定义结构,再在运行时验收结构”。这是一种典型的 schema-first tool design。

Claude Code 的核心是 buildTool(),位于 src/Tool.ts。它的思路更偏产品化:先定义 ToolDef 接口,再由 buildTool() 补齐默认能力,例如 isReadOnlyisDestructivecheckPermissionsuserFacingName。在 schema 层,它既支持 Zod,也支持 JSON Schema。JSON Schema 是 IETF 标准化的数据结构描述规范,可以把它理解为“面向跨语言交换的类型契约”。如果说 Zod 更适合 TypeScript 内部开发体验,那么 JSON Schema 更适合跨进程、跨服务、跨协议场景,尤其适合 Claude Code 这样要兼容 MCP、远程工具与更大生态的系统。

Oh-My-OpenCode(OMO)没有重新发明底层工具协议,而是包装 OpenCode SDK 的工具定义能力,在 src/plugin/tool-registry.tssrc/create-tools.tssrc/tools/* 中注册自己的工具集合。它的关键不是换掉 definition primitive,而是在 execute 前后插入一层 orchestration wrapper:工具创建时仍沿用 OpenCode 风格,但在执行链路上增加 hooks、metadata store、background task 管理、skill/MCP 注入等机制。换言之,OMO 的创新点不在“工具是什么”,而在“工具怎样被编排、拦截、约束和放大”。

这里可以引入 Anthropic 提出的 ACI(Agent-Computer Interface) 原则。传统 HCI(Human-Computer Interface)研究的是人机界面,而 ACI 研究的是“模型如何最小歧义地调用计算机能力”。它强调几个方向:第一,工具接口要清晰、强约束、低歧义;第二,参数名与描述要让模型容易推断;第三,返回结果要结构化,便于后续推理;第四,工具数量不宜无限膨胀,否则会提高模型的选择成本。OpenCode 的 Tool.define()、Claude Code 的 buildTool(),以及 OMO 的包装层,本质上都是 ACI 的工程化体现。

三者因此形成了三个层次。OpenCode 代表“开源基座式范式”:用 Tool.define() + Zod 建立简洁、统一、强验证的工具定义语言。Claude Code 代表“产品平台式范式”:用 buildTool() + JSON Schema/Zod + 默认权限语义,把工具定义扩展成一套可治理的产品接口。OMO 则代表“编排增强式范式”:在不破坏 OpenCode 基座的前提下,为工具定义附加多智能体、技能、会话与钩子系统。

因此,第4章讨论工具系统时,不能只把工具看作函数调用。更准确地说,工具定义范式决定了 Agent 能力边界的表达方式:它既是调用协议,也是安全边界,还是推理成本控制器。谁把这个层设计得更清晰,谁就更可能做出稳定、可扩展、可治理的编码智能体。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第4章 — 工具系统设计
Token用量: 约 13,500 input + 2,300 output

4.2 共有工具清单

尽管 OpenCode、Claude Code 与 OMO 的定位不同,但三者已经收敛出一套相当稳定的 common tool surface。它们都围绕六类能力展开:文件操作、搜索、执行、网络、组合、交互。这个共性非常重要,因为它说明 2026 年的 coding agent 已经出现了一套事实上的“最小充分工具集”。

第一类是 文件操作。OpenCode 提供 readwriteeditmultiedit;Claude Code 对应 FileReadToolFileWriteToolFileEditToolNotebookEditTool;OMO 一方面沿用宿主能力,另一方面补充 hashline-edit 之类更精细的编辑工具。其核心目标一致:让模型能以受控方式读取局部内容、修改目标片段、写入新文件。这里的关键不是“能写文件”,而是“能在最小上下文成本下写对文件”。

第二类是 搜索。OpenCode 有 grepglobcodesearch;Claude Code 有 GrepToolGlobToolLSPToolToolSearchTool;OMO 则扩展出 ast_grep_searchast_grep_replace、会话搜索与 session search。grep/glob 解决的是文本与路径层面的定位,codesearch 和 AST-Grep 则进一步进入 syntax-aware 或 repository-aware 搜索。所谓 AST(Abstract Syntax Tree,抽象语法树),可以简单理解为“把源码从字符序列提升为语法结构树”,因此 AST 搜索比普通字符串搜索更接近“程序结构理解”。

第三类是 执行。OpenCode 的代表是 bashbatch;Claude Code 有 BashToolPowerShellToolREPLTool;OMO 除常规执行外,还引入 interactive-bash,借助 PTY/Tmux 管理长生命周期交互命令。PTY(Pseudo-Terminal,伪终端)可理解为“给程序模拟一个真实终端会话”,因此它适用于 vimhtop、交互式 REPL 这类一次命令无法完成的场景。

第四类是 网络。OpenCode 提供 webfetchwebsearch;Claude Code 对应 WebFetchToolWebSearchTool、浏览器或 MCP 网络能力;OMO 则在此基础上增加 google_searchwebsearch_web_search_exa 等封装。这里的 common pattern 是:一个工具负责定向抓取 URL,另一个工具负责开放式搜索,再由模型决定何时直接读网页、何时先搜再抓。

第五类是 组合。OpenCode 用 taskskilltodoplan_enter/exit 形成基本编排;Claude Code 用 AgentTool、任务工具族、TodoWriteTool、skill 体系形成更产品化的 orchestration layer;OMO 则把这一层推到极致,加入 call_omo_agent、background task、session manager、skill-MCP、slash command 等工具。它说明多智能体系统真正强大的地方,往往不是单个工具,而是工具之间能不能彼此调用、彼此分工。

第六类是 交互。OpenCode 有 question,Claude Code 有 AskUserQuestionTool 与消息类工具,OMO 也保留提问、通知、状态汇报相关能力。其意义在于,Agent 不是全自动脚本,而是需要在不确定性高时把控制权还给用户。

下面给出一个简化映射表:

能力类别OpenCodeClaude CodeOMO
文件读取readFileReadToolread / 封装读取
文件写入writeFileWriteToolwrite / 守卫增强
文件编辑edit / multieditFileEditTool / NotebookEditToolhashline-edit + 宿主编辑
路径搜索globGlobToolglob
文本搜索grepGrepToolgrep
代码/结构搜索codesearch / lspLSPTool / ToolSearchToolast_grep_search / LSP工具
命令执行bash / batchBashTool / PowerShellTool / REPLToolbash / interactive-bash
网页抓取webfetchWebFetchToolwebfetch / 网络扩展
网络搜索websearchWebSearchToolgoogle_search / Exa 封装
子任务/子代理taskAgentTool / Task toolscall_omo_agent / background task
技能skillSkillTool / skill discoveryskill / skill_mcp
用户提问questionAskUserQuestionToolquestion / 相关交互工具

从这张表可以看出,三者并不是“工具完全不同”,而是共享一套核心骨架,再在搜索深度、编排能力、交互复杂度上分化。OpenCode 给出了干净的最小集,Claude Code 给出了工业级高覆盖实现,OMO 则在这个共同骨架之上发展出更激进的 orchestration superstructure。这一共享清单,本身就是当代 Agent 设计共识的缩影。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第4章 — 工具系统设计
Token用量: 约 13,500 input + 2,400 output

4.3 工具权限与安全

工具系统一旦连接文件系统、Shell 与网络,安全问题就不再是附属议题,而是主架构的一部分。OpenCode、Claude Code 与 OMO 在这一点上采取了三条不同路线:规则匹配、模式治理、执行链守卫。

OpenCode 的权限系统位于 packages/opencode/src/permission/next.ts,核心是 allow / deny / ask 三态模型。它并不追求复杂的智能判断,而是采用 pattern matching rule engine:一条规则由 permissionpatternaction 组成,执行时对 permission 与目标模式同时做 wildcard match,并采用“最后匹配优先”。这意味着 OpenCode 把安全问题建模成“能力名 × 资源模式”的笛卡尔积判断,例如 read + /path/*bash + npm install *。这种设计非常工程化,也非常透明:用户能读懂规则,系统也容易解释自己为什么询问或拒绝。

尤其在 Bash 权限上,OpenCode 还通过命令前缀提取来缩小授权粒度。它不是简单地把整条 Shell 命令当成一个黑盒,而是解析出关键 command prefix,再判断例如 git checkoutnpm installdocker run 这样的模式是否被允许。这背后的思想是 capability narrowing:尽量只授予完成当前任务所需的最小能力,而不是一次性放开整个 Shell。

Claude Code 的安全架构则更接近商业产品。它在 src/types/permissions.tssrc/utils/permissions/* 中构建出一个 4+1 模式系统:对用户而言,通常可理解为 defaultplanacceptEditsbypassPermissions 四种主模式;代码里还存在 dontAsk 与内部 auto 模式。default 倾向于逐项确认,plan 先规划后执行,acceptEdits 自动接受一定范围内的编辑,bypassPermissions 则接近全面放行。真正有意思的是它没有止步于静态规则,而是接入了 ML classifier,对 Bash/PowerShell 等高风险操作进行自动分类。

这里的 classifier 可以理解为一种“权限路由模型”:它不直接帮用户写代码,而是判断某次工具调用是否足够安全,能否跳过人工确认。按照 Anthropic 对外材料中的总结,这套机制配合 sandboxing 能显著减少权限提示,常被概括为约 84% 的 permission reduction。这个数字背后不是单一算法奇迹,而是多层机制叠加:安全工具白名单、工作区内编辑快速放行、危险脚本模式识别、连续拒绝后的降级回退,以及 OS 级 sandbox。也就是说,Claude Code 的关键创新不是“少弹窗”,而是“让多数低风险操作从一开始就不需要弹窗”。

OMO 的路径又不同。它继承 OpenCode 的底层权限框架,但在 src/plugin/tool-execute-before.tssrc/plugin/tool-execute-after.tssrc/plugin/hooks/create-tool-guard-hooks.ts 中加入大量守卫钩子。最值得注意的是 file guard 一类钩子,例如写入已有文件保护、question label truncation、规则注入、注释检查、任务响应校验等。也就是说,OMO 不是只在“要不要执行”这一层做决策,而是在执行前后持续加工工具调用,把安全控制分散到 pipeline 的多个节点。

这种 hook-based safety 很像编译器中的 pass pipeline。所谓 hook,在这里可以衍生解释为“附着在主执行流上的可插拔拦截点”:主流程不必重写,只需在关键节点插入额外检查、修正或审计逻辑。其好处是组合性强,坏处是系统会更复杂,调试链路也更长。

综合来看,OpenCode 代表“显式规则安全”,Claude Code 代表“模式+分类器+沙箱安全”,OMO 代表“规则基座之上的编排式安全”。前者透明,后者省心,第三者灵活。三种路线都在回答同一个问题:如何在不摧毁自动化体验的前提下,把 Agent 的真实世界操作约束在可接受的风险半径之内。这也是为什么现代编码智能体的安全设计,已经不只是 permissions UI,而是 tool architecture 本身。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第4章 — 工具系统设计
Token用量: 约 13,500 input + 2,200 output

4.4 工具输出处理

对 Agent 而言,工具调用的难点不只是“能不能执行”,更是“执行结果怎么喂回模型”。如果输出过长,context window 会被迅速吃空;如果输出过散,模型会抓不住重点;如果输出完全非结构化,后续推理会变得昂贵而脆弱。因此,tool output handling 是工具系统设计中的第二战场。

OpenCode 在 packages/opencode/src/tool/truncation.ts 中实现了非常典型的截断策略:默认上限约为 2000 行或 50KB,超过后把完整结果写入外部文件,并把摘要提示返回给模型,同时在 metadata 中标记 truncatedoutputPath。这是一种很朴素但非常有效的做法:让模型只消费“当前需要看的局部”,而不是每次把海量日志全部塞回上下文。更重要的是,OpenCode 会在提示中建议使用 Read 的 offset/limit 或 Grep 做二次定位,这相当于把长输出重新转化为可导航的数据源。

Claude Code 的做法更产品化。在很多工具中都可以看到 maxResultSizeChars 这一显式上限;超过阈值时,完整内容被保存到本地 tool-output 存储,模型收到的是 preview + path,而不是全量正文。与此同时,Claude Code 还要求工具把结果映射成 ToolResultBlockParam 之类的结构化块,支持 text、image、document 等多种 content type,并可附带 MCP metadata 或 structured content。换言之,Claude Code 的输出处理不是单纯“截断文本”,而是把结果对象化、分块化、可渲染化。这样做的直接收益是:同一份工具结果既能被模型继续消费,也能被 UI 层友好展示。

OMO 在这方面采取了“宿主机制 + 钩子增强”的策略。它既复用 OpenCode 的基本输出模型,又在 src/hooks/tool-output-truncator.ts 中按工具类型施加不同的截断预算,例如对 webfetch 给出更紧的限制,对搜索与诊断类工具做动态压缩。同时,它通过 metadata store 在前后钩子之间传递标题、上下文与额外信息。也就是说,OMO 的输出处理不是一个固定函数,而是一个可编排 pipeline:原始输出先生成,再格式化,再截断,再注入额外元数据,最后返回给模型。

这里牵涉一个很重要但常被忽略的概念:认知带宽(cognitive bandwidth)。这不是标准 CS 教材里的经典术语,但在 Agent 设计里非常实用。它指的是模型在单轮推理中真正能高质量吸收和利用的信息量。context window 是硬上限,认知带宽则更像软上限:即使窗口还能装下更多 token,模型也未必能高效利用一大坨无结构日志。因此,优秀的工具输出处理并不是追求“少丢信息”,而是追求“把信息压缩成最适合继续思考的形式”。

可以把三者对比为下表:

维度OpenCodeClaude CodeOMO
截断策略行数/字节双阈值字符数阈值 + 预览宿主截断 + 工具特定钩子
完整输出保存是,写入文件是,写入 tool-output是,结合宿主与扩展逻辑
元数据truncatedoutputPath结构化 result block、MCP metametadata store + hook 注入
内容类型以文本为主text/image/document 多模态以文本为主,支持增强格式化
设计重点简洁、可导航产品化、对象化、可渲染可编排、可干预、可扩展

归根结底,工具输出处理决定了 Agent 是在“消化结果”,还是在“淹没于结果”。OpenCode 通过统一截断建立最小可用秩序,Claude Code 通过结构化结果提升消费质量,OMO 则通过 hook pipeline 把输出处理纳入编排系统。三者共同说明:工具不是调完就结束,真正的设计功夫,往往体现在结果返回给模型的那一瞬间。

模型: gpt-5.4 (openai/gpt-5.4) 生成日期: 2026-04-01 书名: Claude Code VS OpenCode:架构、设计与未来 章节: 第5章 — 会话与上下文管理 Token消耗: 约 18,000 input + 3,800 output(估算)

5.1 会话持久化

会话持久化,指的是智能体把“已经发生过的对话、工具调用、编辑痕迹与任务状态”可靠保存下来,使系统在下一次启动、压缩、切换终端甚至异常中断之后,还能接着干活。它不是传统教材中的标准章节名,更接近工程界对“长期运行状态保存”的通俗说法。对编码智能体而言,持久化不是附属功能,而是把一次性聊天变成连续软件工作的前提。

OpenCode 的选择是 SQLite + Drizzle ORM。从 /packages/opencode/src/session/session.sql.ts 可以看到,它把 sessionmessageparttodo 分成多张表:会话是顶层对象,消息是中层记录,part 则把一条消息拆成 text、reasoning、tool、snapshot、patch 等更细颗粒。这个设计明显带有关系型思维:先定义实体,再定义关系,再通过索引和 schema 保证一致性。它的优点是结构清晰、查询精确、适合做归档、过滤、统计和局部更新;缺点是实现复杂度更高,迁移和版本兼容也更重。

Claude Code 的路径几乎相反。src/utils/sessionStorage.ts 表明它把会话落到 *.jsonl 文件中。JSONL 可理解为“每行一个 JSON 对象的日志文件格式”:不是把整个会话改写成一个大对象,而是像记流水账一样不断 append。它代表的是一种日志型存储思维——先保证顺序追加和恢复,再在读取时重建链路。其优点是实现直接、写入快、对崩溃更友好,也天然适合流式输出;代价则是读取时要做更多“回放”和“重建”,例如依靠 parentUuidcompact_boundary、元数据记录来恢复真正有效的对话链。

如果说 OpenCode 更像“数据库里的会话系统”,Claude Code 更像“事件溯源式的会话账本”。前者强调规范化建模,后者强调 append-only 日志。两者没有绝对高下,而是优化目标不同。OpenCode 更适合开放平台和插件生态,因为第三方能力需要稳定 schema;Claude Code 更适合产品级高频交互,因为日志写入路径短、失败面小、对实时 UI 更自然。

Oh-My-OpenCode 并没有推翻 OpenCode,而是在其上继续加状态层。它继承宿主的 SQLite/消息模型,同时补上持续执行所需的状态追踪。最典型的是 boulder-statesrc/features/boulder-state/storage.ts 会把当前 active plan、started_at、session_ids、plan_name 以及可选 agent 写入 .sisyphus/boulder.json。这意味着 OMO 不仅记住“聊到了哪里”,还记住“这块石头已经滚到哪一步”。对多轮长任务来说,这比单纯保存聊天记录更重要。

因此,三者的权衡可以概括为三句话。OpenCode 追求结构化可查询性,所以选关系型;Claude Code 追求高吞吐可恢复性,所以选 JSONL 日志;OMO 追求不中断的任务连续性,所以在关系型宿主之上再叠加工作状态。前两者在回答“历史怎么存”,OMO 额外回答“进度怎么续”。

从 Agent 设计角度看,理想方案往往不是二选一,而是分层:底层用日志保证不丢事件,中层用结构化索引支持查询,上层再维护任务状态与恢复指针。换句话说,会话持久化最好拆成三层:事件层、结构层、进度层。只做第一层,能恢复聊天;做到第三层,才能恢复工作。

模型: gpt-5.4 (openai/gpt-5.4) 生成日期: 2026-04-01 书名: Claude Code VS OpenCode:架构、设计与未来 章节: 第5章 — 会话与上下文管理 Token消耗: 约 18,000 input + 4,000 output(估算)

5.2 消息结构

消息结构决定了智能体“如何理解自己说过什么、做过什么、还剩什么”。很多人把消息想成一串文本,但在编码智能体里,消息其实更像带类型的操作记录。它不仅包含自然语言,还包含推理片段、工具调用、文件附件、快照、补丁以及压缩标记。消息结构越精细,系统越容易恢复上下文、做差量处理和追踪执行历史。

OpenCode 的代表实现是 MessageV2。从 /packages/opencode/src/session/message-v2.ts 可见,它把一条消息拆成多个 part,常见类型包括 textreasoningtoolfilesnapshotpatch,还包括 compactionsubtaskstep-startstep-finish 等。这里体现的是一种多部分消息模型:用户和助手只是外层容器,真正重要的是内部 part。这样设计的好处是,系统可以单独压缩旧工具输出、保留 patch 哈希、记录某次 step 的 token/cost,也可以在恢复时精准知道“这段是推理,那段是文件,那次是工具结果”。

Claude Code 的中心类型则是 TranscriptMessage。在 src/types/logs.ts 中,它本质上是 SerializedMessage 再加上 parentUuidlogicalParentUuidisSidechain 等恢复字段。也就是说,Claude Code 的重点不是把“消息内部零件”拆得极细,而是把“消息之间的链路”保存得很强。它像一串可追溯的链表:一条消息接上一条消息,再叠加 compact boundary、title、tag、worktree-state 等外围记录,形成完整 transcript。

这也带来两种不同的工程哲学。OpenCode 更像“语义块导向”,先问一条消息由哪些部分组成;Claude Code 更像“日志回放导向”,先问一条记录在链路中的位置是什么。前者适合插件在 message transform、tool prune、summary 注入等位置做细粒度改写;后者适合大规模追加写入与会话回放。

用户要求解释的“扩展思维”,可以理解为 Anthropic 体系里常说的 extended thinking。它不是教科书中的经典名词,更像产品化推理暴露层:模型在正式输出前,会产生 thinkingredacted_thinking 这类内容块,系统还会用 budget_tokens 控制它能花多少推理预算。通俗地说,扩展思维就是“允许模型先在内部写草稿,再给用户答案”的运行模式。OpenCode 把这类内容明确存成 reasoning part;Claude Code 则更多以消息内容块和 API 预算参数来承接。

另一个需要解释的术语是 JSONL。JSONL 不是数据库,也不是单个 JSON 文档,而是 JSON Lines:一行一个 JSON 记录,天然适合追加。它像财务流水,而不是一份总账快照。Claude Code 采用它,意味着任何 user、assistant、summary、compact boundary、tag 都能作为独立事件写入磁盘;恢复时再把这些事件重新拼成可继续运行的会话状态。

OMO 在消息结构上基本继承 OpenCode,但它更强调“消息之外的工作协议”。比如 todo、任务同步、恢复提示、钩子注入,本质上都在给消息结构补充“执行约束”。因此,Agent 设计的关键经验是:不要只设计消息内容,还要设计消息可被恢复、压缩、审计和续接的形状。聊天系统用字符串够了,工作系统不够。

模型: gpt-5.4 (openai/gpt-5.4) 生成日期: 2026-04-01 书名: Claude Code VS OpenCode:架构、设计与未来 章节: 第5章 — 会话与上下文管理 Token消耗: 约 19,000 input + 4,200 output(估算)

5.3 上下文压缩

上下文压缩解决的是一个越来越现实的问题:会话越长,模型越贵、越慢、越容易失真。这里可以引入一个非标准但很形象的术语——上下文腐烂。它不是教材里的正式概念,而是工程界对“上下文一长,旧信息变噪声,新信息被淹没,模型开始忘重点、重复搜索、误判状态”的统称。其底层原因之一,正是 Transformer 注意力计算随序列增长而急剧变贵,常被粗略概括为 O(n²) 级别压力。

OpenCode 的策略比较直接:当上下文接近上限时,触发 session/compaction.ts,调用专门的 compaction agent 生成继续工作所需的摘要;同时还能 prune 旧工具输出,把早期但价值较低的长结果标记为已 compacted。也就是说,OpenCode 的压缩不是简单截断,而是“摘要 + 清理旧结果”的双动作。它试图保留任务连续性,同时把无关的工具噪声扔掉。

Claude Code 的上下文管理更像一套五层防线。第一层是阈值预警,autoCompact.ts 会根据模型窗口和 buffer 计算 warning / blocking 状态;第二层是 microCompact,优先清掉可再生的旧工具结果,用 [Old tool result content cleared] 这类桩文本换回 token;第三层是 sessionMemoryCompact,优先利用已提炼的会话记忆来构造更轻的后压缩上下文;第四层是完整 compaction,生成 summary 并写入 compact_boundary;第五层是 reactiveCompact 一类兜底机制,在 prompt-too-long 已经发生时再做补救。所谓“五层防御”,本质上就是从“轻量去噪”到“重度重写”的分级治理。

这种设计非常像缓存体系:能局部替换就不整页重写,能复用旧摘要就不重新总结,实在不行再做整段压缩。它的优势是用户感知更平滑,不必每次都经历一次重型总结;缺点则是系统实现明显更复杂,边界条件很多,例如 resume 后 boundary 如何重建、哪些内容该保留以维持 prompt cache、哪些 tool/result 不能拆开等。

OMO 在 OpenCode 基础上又往前推了一步:它不仅会压缩,还会抢先式压缩src/hooks/preemptive-compaction.ts 显示,系统在工具执行后根据 token cache 判断使用率,Anthropic 1M 上下文下默认在 78% 左右就先触发 summarize,而不是等真正撞线。这个思路很重要:优秀 Agent 不该等错误发生后再解释,而应在错误还没发生时就重排上下文。

更关键的是,OMO 发现压缩最容易伤到的不是“聊天内容”,而是“工作协议”。因此它专门加了 compaction-todo-preserver:压缩前抓取 todo 快照,session.compacted 后再检查并恢复。其意义在于,很多系统压缩后还能记得任务目标,却忘了任务清单;还能记得讨论主题,却丢了执行状态。OMO 要保护的正是这条最脆弱的工作链。

因此,上下文压缩的最佳实践并不是“把旧内容变短”这么简单,而是三件事同时成立:先去噪、再总结、最后保护任务状态。如果只能总结而不能保护工作进度,压缩就会把智能体从“持续施工”打回“重新开工”。这正是会话系统与任务系统的根本差别。

模型: gpt-5.4 (openai/gpt-5.4) 生成日期: 2026-04-01 书名: Claude Code VS OpenCode:架构、设计与未来 章节: 第5章 — 会话与上下文管理 Token消耗: 约 18,500 input + 4,100 output(估算)

5.4 会话恢复与续接

会话恢复回答“怎么把过去找回来”,会话续接回答“找回来以后怎么继续做”。二者看似接近,其实不同。恢复更像读档,续接更像读档后无缝继续施工。对编码智能体而言,真正困难的不是把历史文件重新加载,而是避免上下文重置后丢掉任务动量。这里可以把这个难题称为续接问题:上下文被压缩、进程被打断、窗口被清空之后,系统如何仍然知道自己做到哪、下一步该做什么、哪些承诺还未完成。

OpenCode 已经具备比较完整的恢复基座。session/index.ts 里可以看到 time_archived 字段与 setArchived(),说明会话可归档;消息和 part 作为结构化记录被保存在 SQLite 中,因此恢复时不是读一份模糊文本,而是重建可查询状态。再结合 summary.tsrevert.ts、snapshot diff 等机制,OpenCode 的恢复逻辑更像“数据库级恢复”:会话、摘要、差异、回滚点都在同一套模型内。

Claude Code 则把恢复体验做成显式命令。用户熟悉的 /resumeclaude --resume,底层会走 loadConversationForResume(),再从 JSONL transcript 中恢复消息、fileHistory、content replacements、context collapse 状态、worktree 状态、agent setting、tag 等元数据。sessionStorage.ts 还专门处理 compact_boundary,确保 resume 时不会把压缩前的大段旧历史重新整包装回去。也就是说,Claude Code 的恢复不是简单“打开旧文件”,而是一次带剪枝和重建的日志回放。

OMO 进一步把“恢复”升级为“继续干活”。一方面,它通过 Claude Code 兼容钩子与 continuation hooks,在会话中断、压缩、停止后注入恢复信息;另一方面,boulder-state 会把当前活跃计划写进 .sisyphus/boulder.json,记录 active_plan、started_at、session_ids、plan_name,必要时还记录应使用的 agent。这个文件的重要性在于:它把“正在推哪块石头”从聊天历史里剥离出来,单独变成恢复锚点。

另外,OMO 的 loop-session-recovery.ts 维护了短窗口恢复状态,Ralph Loop 与 todo continuation 机制则在更高层保证“没做完就继续”。这背后体现的不是单纯的 session management,而是一种任务连续性设计。传统 CLI 认为中断后重新输入命令即可;智能体系统若也这么设计,就会频繁丢失执行承诺。

因此,解决续接问题至少需要四类锚点:第一,历史锚点,知道说过什么;第二,结构锚点,知道压缩边界和父子链;第三,进度锚点,知道 todo 或计划完成到哪;第四,环境锚点,知道 worktree、cwd、agent、权限状态是否变化。OpenCode 强在前两类,Claude Code 强在日志回放与边界恢复,OMO 则把第三类——进度锚点——补得最狠。

从理想 Agent 设计看,恢复系统不该只恢复“记忆”,还必须恢复“意图、进度与责任”。如果下一次启动只能告诉模型“我们之前聊过什么”,却不能告诉它“还欠哪些事没做完”,那恢复了一半,工作却断了。真正优秀的续接机制,应该让用户感觉这不是一个新会话,而是同一个工程师从短暂离席后回到了工位。

模型: openai/gpt-5.4 生成日期: 2026-04-01 书名: Claude Code VS OpenCode:架构、设计与未来 章节: 第6章 — LLM提供者抽象 Token消耗: 当前运行环境未暴露精确统计值,无法精确填报

6.1 多模型支持架构

LLM提供者抽象,本质上是在“模型世界的碎片化现实”和“工程系统想要稳定接口”之间搭桥。这里的“提供者抽象”不是传统教材中的标准术语,可以把它理解成一层“翻译兼配电中枢”:上游接不同云厂商、不同认证方式、不同参数命名;下游向会话循环、工具系统、流式输出暴露尽量一致的调用面。没有这层,编码智能体会被每家模型厂商的接口细节撕裂。

OpenCode在这一章里最有代表性的设计,是基于 Vercel AI SDK 来统一多家模型。Vercel AI SDK也不是标准CS教材里的经典概念,它更像一个“多厂商LLM适配总线”:在TypeScript里,把 Anthropic、OpenAI、Google、Bedrock、Vertex、Groq、Mistral、OpenRouter、GitHub Copilot 等二十多个提供者包装成相似的模型对象与流式接口。OpenCode 的 provider.ts 直接导入一长串 createXxx 工厂,再结合 models.dev 获取提供者和模型元数据,因此它天然偏向“模型无关”架构:应用层只要描述“我要哪个 provider/model”,而不是为每家SDK单独写分支。这种方式的好处是可移植、可扩展、便于社区接入;代价是最低公分母问题突出,很多厂商特性只能通过附加映射去保留。

Claude Code的取向则更偏“模型专用优化”。从 src/utils/model/providers.tsmodel.tsconfigs.ts 可以看到,它的主路径明显围绕 Anthropic 第一方接口展开;当环境变量打开时,再切到 Bedrock、Vertex、Foundry 等第三方承载层。也就是说,它不是先追求“任何模型都能平权接入”,而是先确保 Claude 家族在默认路径上获得最好体验,再为企业环境提供落地后备。这种设计更像“主航道+分流渠”:主航道深挖 Anthropic 能力,分流渠解决合规、区域部署和企业采购问题。

OMO 的贡献不在底层SDK统一,而在“语义层选模”。category-resolver.tsmodel-requirements.ts 显示,它把任务先分到 visual-engineeringultrabrainquickwriting 等语义类别,再为每类配置最佳模型与回退链。例如 visual-engineering 默认优先 Gemini 3 Pro,因为系统作者认为它更适合前端、设计、视觉任务。这里出现了另一种抽象:不是“用户自己挑模型”,而是“系统按任务语义挑模型”。这使智能体更像一位技术经理,而不是单纯的API调用器。

因此,三者构成了三种层次:OpenCode 解决“怎么统一接多家模型”,Claude Code 解决“怎么把一家模型用到极致并兼容企业后备”,OMO 解决“什么任务该让什么模型上场”。

这背后对应一个长期张力:模型无关 vs 模型专用。模型无关强调 portability,像插头标准化,换电器方便;模型专用强调 optimization,像为特定发动机单独调校。前者适合开源生态、插件生态、快速扩容;后者适合深度利用 reasoning、长上下文、流式工具调用、专有安全能力。理想设计通常不是二选一,而是分层:底层保持统一调用协议,中层做能力探测与参数映射,上层允许语义路由与模型特化。真正优秀的 Agent,不应只会“接很多模型”,也不应只会“绑死一个模型”,而应在统一骨架上,保留对顶级模型特性的定向利用能力。

模型: openai/gpt-5.4 生成日期: 2026-04-01 书名: Claude Code VS OpenCode:架构、设计与未来 章节: 第6章 — LLM提供者抽象 Token消耗: 当前运行环境未暴露精确统计值,无法精确填报

6.2 模型能力检测

如果说提供者抽象解决的是“能不能连上模型”,那么模型能力检测解决的就是“连上以后,究竟能安全地让它做什么”。这可以视为一种运行时能力协商:系统在真正发请求前,先判断当前模型支持哪些输入模态、哪些采样参数、是否有推理模式、上下文窗口有多大、工具调用是否稳定。它像机场塔台分配跑道——不是所有飞机都能在同一条跑道上、用同一套程序起降。

OpenCode在这方面做得相当系统。models.ts 从 models.dev 读取模型元数据,字段里直接包含 reasoningtemperaturetool_callmodalitieslimit.contextlimit.output 等信息;transform.ts 再把这些能力落实到消息归一化与参数转换上。比如,若模型不支持图片或 PDF 输入,系统不会盲目发送二进制内容,而会把它改写成错误提示文本;若模型是 Anthropic、Mistral 或 Copilot,还会针对消息格式、toolCallId、reasoning 字段做专门变换。这说明“能力检测”并不是一个布尔判断,而是“元数据 + 转换器 + 防错规则”的组合体。

Claude Code则采取“专属模型知识 + 动态刷新”的策略。modelCapabilities.ts 会从 Anthropic 的模型列表拉取 max_input_tokensmax_tokens 并缓存到本地;model.tsconfigs.tsproviders.ts 再结合 first-party、Bedrock、Vertex 的差异,决定默认模型、1M 上下文、不同提供者下的 canonical model id。这里的重点不是支持尽可能多的外部模型,而是精确理解 Claude 家族在不同承载环境中的行为差别。比如同样是 Sonnet,新版在第一方可能已是默认,但在第三方云上可能尚未完全可用,于是默认策略必须回退到较早稳定版本。

参数协商是这一节最容易被低估的部分。温度(temperature)可以理解为“输出随机度旋钮”;TopP 则像“只从概率最高的一小团候选词里抽样”;MaxTokens 则是“本轮回答可用的最大字数预算”。这些概念在教材里常见,但一旦落到多提供者场景,就会出现命名、默认值、支持范围都不一致的问题。有的模型支持 temperature 但不支持 top_p;有的支持 reasoning effort,但以 reasoning_detailsreasoning_content 或别的私有字段表达;有的模型虽能接收参数,却会静默忽略。于是 Agent 侧必须做“提供者特定参数转换”,把上层统一意图翻译成下层可接受格式。

OMO 把能力检测继续向上推了一层:它不仅问“模型能不能做”,还问“这个任务值不值得让该模型做”。visual-engineering 走 Gemini,deep 偏向 GPT-5.3-codex,quick 则选 Claude Haiku,本质上是一种“任务-能力匹配表”。这种语义级协商能减少用户手工调参负担,但前提是底层已经有稳定的模型元信息和回退链。

上下文窗口差异也必须被严肃对待。上下文窗口可以衍生解释为“模型当前短期记忆的容量上限”;不同模型从几十K到一百万token不等,超限后要么报错,要么截断,要么触发压缩。Agent 设计里,窗口大小不是性能细节,而是架构约束:它决定系统是否需要激进压缩、是否能携带大仓库摘要、是否允许多轮工具输出原样回灌。优秀的提供者抽象,不只是把 API 打平,更要把能力边界显式化,让上层调度器知道哪里能冲,哪里必须收。

模型: openai/gpt-5.4 生成日期: 2026-04-01 书名: Claude Code VS OpenCode:架构、设计与未来 章节: 第6章 — LLM提供者抽象 Token消耗: 当前运行环境未暴露精确统计值,无法精确填报

6.3 认证与密钥管理

LLM系统一旦进入真实生产环境,最先暴露复杂性的往往不是提示词,而是认证。因为“调用哪个模型”只是功能问题,“凭什么允许你调用”则是安全与商业问题。对编码智能体来说,认证层至少要处理四类对象:API 密钥、OAuth 令牌、远程发现端点,以及企业组织级身份。

OpenCode在这方面体现出很强的开放平台倾向。provider/auth.ts 把提供者登录方式抽象为 apioauth 两类;前者适合直接保存 API key,后者适合走浏览器授权、回调换取 access/refresh token。更有意思的是,它还支持 .well-known/opencode 发现机制:config.ts 会从远端组织地址抓取配置,cli/cmd/providers.ts 则能读取 well-known 文档中的认证命令与环境变量,把远端组织默认配置、远端登录方式、令牌注入串起来。这里的“well-known端点发现”不是教科书里常见名词,可以把它看成“服务自报家门的固定门牌号”:客户端只要知道域名,就能在约定路径找到配置与认证说明。

OpenCode 对 GitHub Copilot 也做了特殊兼容。provider.ts 中不仅有 github-copilot,还派生出 github-copilot-enterprise;认证检查时,两者还会互相兜底。其含义很现实:有些提供者表面上像标准 OpenAI 兼容接口,实际认证生命周期、模型命名、返回字段都很特殊,因此统一抽象层必须保留“特殊通道”。否则你会得到一个看似统一、实则到处漏水的接口。

Claude Code则展现出更成熟的企业认证体系。其 OAuth 服务实现了标准 authorization code flow with PKCE:本地启动临时回调服务,浏览器完成授权,CLI 捕获 code,再换取 access token 与 refresh token。constants/oauth.ts 里还能看到 prod、staging、local 三套 OAuth 配置,以及对 CLAUDE_CODE_CUSTOM_OAUTH_URL 的白名单限制,防止凭证被发送到任意恶意地址。更进一步,Claude Code 既支持 OAuth,也支持 API key;bootstrap.ts 甚至优先使用具备 user:profile scope 的 OAuth,缺失时再回退到 API key。说明在它的设计里,认证不仅是登录动作,更与功能开关、计费层级、团队能力同步绑定。

企业级认证的关键,不只是“能登录”,而是“能把身份、组织、权限和模型访问策略捆在一起”。Claude Code 的账户信息里包含 subscription、organization、roles、scopes 等维度;这意味着同一个 CLI,在个人开发者手里是工具,在企业管理员眼里则是合规入口。OpenCode更开放,强调自托管与外部组织接入;Claude Code更垂直,强调官方账户体系、组织路由和受控部署。

从 Agent 设计角度看,认证与密钥管理至少应满足五条原则:第一,密钥存储与模型调用解耦;第二,OAuth 与 API key 共存;第三,刷新逻辑自动化,避免每次401都把问题抛给用户;第四,允许 well-known 或元数据文档做端点发现,减少手工配置;第五,企业环境必须支持白名单、作用域、组织级隔离。未来最好的编码智能体,不会把认证当成附属脚本,而会把它当成“能力开启系统”的一部分:谁能用什么模型、在哪个组织下、以何种合规方式调用,都应在这一层被明确表达。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第7章 — MCP:AI的USB-C
Token用量: 约 11,000 input + 2,100 output(估算)

7.1 为什么MCP改变了一切

2024 年 11 月,Anthropic 以 MIT license 发布 MCP(Model Context Protocol)。表面上看,它只是一个 open standard,用来让 AI 系统连接 tools、data 与 prompts;但从架构史的角度看,它更像是一次接口层的大一统。把 MCP 称作“AI 的 USB-C”,并不是一句轻飘飘的类比,而是点中了它真正改变生态的原因:它把原本高度碎片化的“能力接入层”标准化了。

为什么是 USB-C,而不是别的比喻?因为 USB-C 的价值不在于“线”,而在于“统一接口 + 能力协商”。在 USB-C 出现之前,设备厂商经常各做各的接口、充电协议与数据传输方式,导致用户和开发者都要承担兼容成本。AI Agent 世界在 MCP 之前也是如此:每个 host、每个 framework、每个 tool vendor 都可能定义自己的 tool schema、调用格式、认证方式和 transport。结果就是:同样一个搜索服务,要为多个 Agent 产品重复适配;同样一个 Agent runtime,也要为多个外部能力重复接线。

MCP 试图解决的,正是这个“接口碎片化”问题。

它的核心架构可以概括为:

Host → MCP Client ←→ JSON-RPC 2.0 ←→ MCP Server

这里的 Host 指用户直接使用的 AI 应用或 Agent runtime,比如 Claude Desktop、Cursor、VS Code、Zed、ChatGPT,也包括 OpenCode 这样的 agent shell。Host 内部包含 MCP Client,由它来负责协议通信。另一端是 MCP Server,它暴露三类核心能力:

  • Tools:可执行动作,例如搜索、读写数据、调用 API、浏览器操作
  • Resources:可读取的数据对象,例如文档、配置、记忆、结果文件
  • Prompts:由 server 提供的可复用 prompt 模板

这三分法非常关键。很多早期系统喜欢把一切都压扁成 tool,但 MCP 更细分:有些东西是“动作”,有些是“数据”,有些是“提示模板”。这种划分让 host 能更清楚地理解能力边界,也让 server 的设计更清晰。例如一个 docs server 既可以暴露“搜索文档”的 tool,也可以暴露“某篇文档内容”的 resource,还可以提供“将 API 迁移步骤整理成说明”的 prompt。

MCP 在消息层通常建立在 JSON-RPC 2.0 之上。这里有必要稍微解释一下,因为 RPC(Remote Procedure Call) 这个概念虽然在分布式系统课程里出现过,但 JSON-RPC 这种具体协议并不是传统 CS 教科书里最常见的重点术语。可以把它理解成:你要调用“远端”的一个函数,但不是直接在本地进程里调用,而是把“方法名、参数、请求 id、返回结果或错误”打包成 JSON 消息发送出去。JSON-RPC 2.0 就是把这套调用约定标准化了。它的好处是:格式统一、容易调试、与具体 transport 解耦。

也正因为如此,MCP 的 transport 可以灵活变化。它常见支持三种路径:

  • stdio:本地模式。Host 启动一个本地进程,通过 stdin/stdout 与其通信。
  • HTTP + SSE:远程模式。客户端通过 HTTP 发起请求,通过 SSE(Server-Sent Events) 获取流式返回。SSE 是浏览器与后端常见的一种单向流式推送机制,传统教材通常会讲 HTTP 和 WebSocket,但不一定会系统展开 SSE。
  • WebSocket:Web 场景下常见的双向长连接 transport。

这个 transport flexibility 不是“锦上添花”,而是 MCP 能快速落地的关键。因为 AI 工具的部署环境天然多样:有些能力适合本地进程,有些是远程 SaaS,有些运行在浏览器或 IDE extension 里。如果协议把 transport 写死,生态就会卡住;而 MCP 把 transport 与 capability declaration 分开,host 与 server 才能在不同环境下复用同一套能力语义。

MCP 最经典的价值表达,是所谓的 N+M advantage。在没有统一协议时,假设你有 N 个 Agent framework,以及 M 个 tool provider,那么总共往往需要 N×M 个定制集成:每个 host 都要单独接每个工具。标准化之后,情况变成:每个 host 只要实现一次 MCP,每个 tool provider 也只要实现一次 MCP,总代价逼近 N+M。这就是标准的网络效应:它不只是“优雅”,更是把生态的边际集成成本从乘法关系降成加法关系。

正因为成本曲线改变了,MCP 才会迅速扩散。到 2026 年,MCP 已经不只是 Anthropic 自家协议。除了 Claude Desktop 这个最早的重要宿主,它还被 Cursor、VS Code、Zed、ChatGPT 等广泛吸收,同时催生了 1000+ community servers。这些 servers 的能力覆盖非常广:GitHub search、web search、browser automation、docs retrieval、database access、design tools、Slack、memory systems、enterprise connectors 等等。真正重要的不是“数量”,而是“形态”——MCP 开始成为“Agent 外部能力”的默认封装方式。

这会带来一个更深的变化:分工方式改变了。在 MCP 之前,一个 Agent 产品如果想更强,往往得自己同时承担模型调用层、tool 定义层、外部数据接入层、认证层、错误处理层。也就是说,产品团队既要做 agent runtime,又要做 integration platform。MCP 出现后,这些职责可以拆开:host 专注于 reasoning、UX、permission、orchestration;server 专注于某个领域能力本身。这种分工会极大释放生态活力。

例如,一个搜索公司可以只做 search MCP server;一个 docs 公司可以只做 documentation MCP server;一个 design vendor 可以只做 Figma 或 design system MCP server;而 Agent runtime 则在更上层竞争:谁的 context engineering 更强、tool selection 更稳、权限模型更安全、用户体验更好。换言之,MCP 让 Agent 世界从“封闭的一体化产品竞争”,逐渐转向“模块化生态竞争”。

还有一个容易被忽视但很重要的点:MCP 强迫系统设计者重新整理概念边界。很多 Agent 系统容易把“模型推理”“工具调用”“外部数据访问”“提示模板”“UI 交互”混成一团,最后 runtime 变成大泥球。MCP 把这些层次拆得更干净:Client 负责面向模型的能力调度;Server 负责暴露 capability;JSON-RPC 负责消息框架;transport 负责传输。边界一旦清楚,可测试性、可替换性、安全性和可维护性都会提升。

当然,MCP 不是万能的。它不能自动解决权限问题,不能自动防止危险工具被滥用,也不能消灭超长输出、错误 schema、或者误导性结果。标准只能统一接口,不能替你做产品治理。但这并不影响它的革命性。历史上真正改变生态的标准,往往也不是“解决一切”的标准,而是“解决那个最阻碍生态扩张的接口问题”的标准。HTTP、JSON、OAuth、USB 都是如此,MCP 也是如此。

所以,MCP 改变一切,不是因为它让模型更聪明,而是因为它让 Agent 能力交换 这件事第一次有了稳定公共语言。模型会迭代,context window 会继续膨胀,agent orchestration 也会继续演化;但 MCP 提供的是更底层、更持久的东西:一个共享的 capability substrate。对于 AI Coding Agent 来说,这意味着工具接入不再是产品私有技巧,而开始变成整个生态的公共基础设施。这就是它真正改变一切的原因。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第7章 — MCP:AI的USB-C
Token用量: 约 12,500 input + 2,200 output(估算)

7.2 MCP实现对比

如果说 7.1 讨论的是 MCP 在理念层面为什么重要,那么这一节关心的是另一个问题:三套系统到底“怎么把它做出来”。OpenCode、Claude Code、Oh-My-OpenCode(OMO)都把 MCP 视为关键能力层,但它们的实现风格并不相同。读源码后可以很明确地看到三种取向:OpenCode 强在 breadth,即协议覆盖面广、开放基座完整;Claude Code 强在 depth,即把 MCP 做成了深度产品子系统;OMO 则强在 creativity,把 MCP 与技能系统、兼容层、内建远程服务做了高度创造性的组合。

OpenCode:完整而开阔的 MCP client 基座

OpenCode 的 MCP 实现主要位于 packages/opencode/src/mcp/。核心文件是 index.ts,配套还有 auth.tsoauth-provider.tsoauth-callback.ts。从架构角度看,它最重要的特征是:它不是“象征性支持 MCP”,而是真正把自己做成了一个 full MCP client

首先,在 transport 层,它直接使用官方 SDK 提供的多种客户端 transport:

  • StdioClientTransport:连接本地 subprocess 型 MCP server
  • SSEClientTransport:连接基于 SSE 的远程 server
  • StreamableHTTPClientTransport:连接 streamable HTTP server

这意味着 OpenCode 从一开始就覆盖了本地与远程两大主要 MCP 部署场景。对一个开源 Agent runtime 来说,这个覆盖面已经非常重要,因为它决定了生态接入上限。

其次,OpenCode 不只是“连上 server”,而是把 MCP tool 真正转成自身 runtime 能消费的 tool abstraction。在 mcp/index.ts 里,convertMcpTool() 会把 MCP server 返回的 tool definition 转换成 AI SDK 的 dynamicTool。这里的关键点在于 schema normalization:MCP tool 通常以 JSON Schema 描述参数,OpenCode 需要把它整理成内部一致的 tool interface,再交给模型与执行层使用。也就是说,它做了一个非常典型的 adapter:把外部协议对象,转成内部原生工具对象。

这一步很关键。因为如果 host 只是“把 MCP 当外部黑盒”,那 MCP 很难真正融入 agent 推理链路;而 OpenCode 的做法是让 MCP tool 在宿主内部变成“一等工具公民”。这样,模型调用 MCP tool 时,体验上更像是在调用 host 自带工具,而不是在跨一个怪异子系统。

第三,OpenCode 认真处理了 MCP 的三类能力,而不只关注 tool。源码里可以看到它会 listPrompts()listResources(),并分别管理 prompt 与 resource 的信息缓存。同时它还注册 tool list changed notification,在 server 工具集发生变化时通过 bus 发事件。这说明它理解 MCP 不是“tool-only protocol”,而是一个更丰富的 capability protocol。

第四,OpenCode 实现了相当完整的 OAuth supportauth.ts 中定义了 token、client info、code verifier、oauth state 等结构,并把认证信息持久化到 mcp-auth.jsonoauth-provider.ts 实现 OAuth client provider,oauth-callback.ts 负责本地 callback server、state 验证与超时处理。这套实现当然还不像大型商业产品那样庞大,但对开源宿主来说,已经足以支撑真实远程 MCP server 的接入,而不只是 demo 级玩具。

综合来看,OpenCode 的 MCP 设计核心是:覆盖面广、结构干净、足够通用。它把 tools、resources、prompts、stdio/SSE/HTTP transport、OAuth、动态工具转换这些关键部件都铺好了,非常像一个面向生态的基础设施层。

Claude Code:把 MCP 做成产品操作系统的一部分

Claude Code 的情况明显不同。它的中心文件 src/services/mcp/client.ts 长达 3,348 行。这个体量本身就说明,它不是在“支持一个协议”,而是在构建一个完整的 MCP product subsystem。

第一层差异,是 transport depth。Claude Code 在 types.ts 中支持 stdiossehttpwssdk,还包括内部特殊类型如 claudeai-proxy。此外,它还有 InProcessTransport,用于同进程内 client/server 通信;以及 SdkControlTransport,用于 CLI 进程与 SDK 进程之间桥接 MCP 消息。换句话说,Claude Code 不只是把 MCP 用来连接“外部 server”,它还把 MCP 当作内部系统边界来使用。

第二层差异,是 auth complexity。Claude Code 的 MCP auth 不是简单的 access token 存取,而是覆盖 OAuth discovery、token refresh、token revocation、callback port 管理、auth cache、claude.ai auth 协同,甚至还有 XAA 等更复杂配置。为什么会这样?因为一旦 MCP 进入 commercial product,认证就不再是“能连上就行”的问题,而是“长期运行下各种失败路径怎么收敛”的问题。token 会过期、metadata 会不规范、用户会中途取消、server 会返回 401,产品必须提供恢复路径。

第三层差异,是 product UX integration。Claude Code 实现了 elicitation 处理。所谓 elicitation,可以理解为 MCP server 主动向客户端请求更多用户输入或确认信息的一种交互机制。这类术语不常见于传统 CS 教材,更像 AI 产品化过程里长出来的 interaction protocol。elicitationHandler.ts 中可以看到,Claude Code 会注册 request handler,把 elicitation 事件挂到 AppState 队列里、等待用户响应、记录 analytics,并处理 completion notification。这说明 Claude Code 已经把 MCP 视为 UI 可交互的一部分,而不只是后台能力调用。

第四层差异,是 policy and permissions。Claude Code 针对某些 MCP server,尤其 channel 类 server,做了额外的 allowlist、org policy、channel permission gating。channelNotification.tschannelPermissions.ts 等文件表明:在 Claude Code 里,并不是所有 MCP server 都被同等对待。有些 server 被看作通信通道,因此必须满足 claude.ai OAuth、组织级启用策略、session allowlist 等条件。这个设计非常“商业化”:协议支持只是起点,真正落地还要考虑信任边界和产品治理。

第五层差异,是 ecosystem curationofficialRegistry.ts 会从 Anthropic 的 registry endpoint 拉取官方 MCP URL 列表并缓存,提供 isOfficialMcpUrl() 判断。这个能力看似小,但含义很深:Claude Code 不只是支持开放生态,它还尝试对生态做“官方发现与信任锚定”。当生态扩张到一定规模后,discoverability 与 trust 本身就是产品功能。

第六层差异,是 Claude.ai integration。Claude Code 能获取符合条件的 claude.ai MCP configs,把它们映射成 claudeai-proxy 类型 server;同时还能通过 SdkControlClientTransport 桥接 SDK 内部运行的 MCP server。这代表它把 MCP 同时用于外部集成、内部组件、云端连接器和产品平台整合。

因此,Claude Code 的 MCP 关键词不是 breadth,而是 depth。它把协议、产品、权限、云端服务、内部 SDK、交互 UX 织成了一张密网。MCP 在 Claude Code 里,已经不像一个“插件接口”,更像是其 product operating environment 的一部分。

OMO:把 MCP 做成技能与生态迁移的组合件

OMO 的路线又不同。它没有试图重造一套比 Claude Code 更深的 MCP client 栈,而是利用 OpenCode 基座,走出了一条很有想象力的组合式道路。

首先,OMO 在 src/mcp/ 内置了 三个 remote MCP

  • websearch:通过 Exa 或 Tavily 提供 web search
  • context7:提供官方文档检索
  • grep_app:提供 GitHub 代码搜索

这三个 MCP 的配置实现很短,但选择非常精准。它们恰好覆盖了自主 Agent 最常见的研究三件套:网页发现、官方文档、真实代码样本。也就是说,OMO 不是追求“默认塞进一大堆 MCP”,而是优先把最能提升 agent 推理质量的三类能力固化成内建 substrate。

其次,OMO 做了一个非常实际的东西:Claude Code MCP loader。在 src/features/claude-code-mcp-loader/ 中,它会从多个 scope 读取 .mcp.json,再 transform 成 OMO/OpenCode 可用的格式。这本质上是一个迁移兼容层。它不要求用户重建 MCP 生态,而是允许用户把 Claude Code 的 MCP 配置直接迁过来。对于生态扩展来说,这种兼容性比“重新发明一套新规范”更有吸引力。

第三,也是 OMO 最有原创性的地方:skill-embedded MCPs。在 OMO 里,skill 不只是 prompt/instruction bundle,它还可以携带自己的 MCP 配置。SkillMcpManager 负责管理这些 skill 内嵌 MCP 的连接生命周期:支持 HTTP 与 stdio 两类连接;进行 env expansion;失败时 retry/reconnect;管理 auth provider;按 sessionID + skillName + serverName 做 client caching;空闲一段时间后自动清理连接。这种机制实质上是一种轻量级 connection pooling,也可以理解为“按技能域隔离的 MCP client cache”。

这件事的意义很大。传统系统里,skill 往往只负责“怎么想”,MCP 负责“怎么连工具”;两者分属不同扩展平面。而 OMO 把它们半融合了:一个 skill 可以同时附带行为知识和外部能力。这意味着“专业能力包”不再只是 prompt,而可以成为“prompt + tool substrate”的复合体。

src/tools/skill-mcp/tools.ts 里的 skill_mcp 工具进一步把这个想法落地。它允许当前 agent 去调用某个 skill 所声明的 MCP server 的 tool、resource 或 prompt。换句话说,skill 加载后,不仅指令进入上下文,它自己的外部能力也能立即进入执行面。这是非常漂亮的扩展模式。

总结:breadth、depth 与 creativity

因此,三者的对比可以非常简洁地概括为:

  • OpenCode:breadth —— 完整、开放、通用的 MCP client 基座
  • Claude Code:depth —— 深度产品化的 MCP 平台
  • OMO:creativity —— 将 MCP、skills、兼容层、内建 remote capabilities 组合出新扩展范式

这个对比也提醒我们:所谓“支持 MCP”,其实至少有三层含义:

  1. Protocol coverage:是否覆盖 tools/resources/prompts、是否支持主要 transports、是否有 auth
  2. Product integration:是否与 UI、permission、policy、state recovery、interactive flow 深度集成
  3. Extensibility design:是否能与 plugins、skills、迁移兼容、用户生态结合

OpenCode 在第 1 层尤其强,Claude Code 在第 2 层遥遥领先,而 OMO 在第 3 层最有想象力。也正因如此,MCP 不只是一个技术协议,更是一面镜子:透过它,我们能看出一套 Agent 系统究竟想成为“开放基座”“商业操作系统”,还是“高创造力的编排平台”。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第7章 — MCP:AI的USB-C
Token用量: 约 10,000 input + 1,900 output(估算)

7.3 MCP与A2A

MCP 被广泛接受之后,一个新问题马上出现:如果 MCP 正在标准化 agent 对 tools/data 的访问,那么 agent 之间彼此协作,要靠什么协议?这就是 A2A(Agent-to-Agent Protocol) 的问题空间。很多讨论会把 MCP 和 A2A 当成竞争关系,但这种理解并不准确。它们解决的是两种不同的边界问题。

最短的区分方式是:

  • MCP = agent ↔ tools/data
  • A2A = agent ↔ agent

前者处理的是 vertical integration(纵向集成):一个 agent 如何连接到底层能力层。后者处理的是 horizontal communication(横向通信):一个 agent 如何把任务交给另一个 agent,并协同完成工作。

MCP 面向的是什么问题

MCP 的默认假设是:真正的“主 intelligence”主要在 client/host 这一边。Server 虽然可以很复杂,但从协议视角看,它更像一个 capability provider。Host 负责决定什么时候调用 tool、什么时候读取 resource、什么时候拿 prompt;server 负责把能力声明出来并响应请求。

因此,MCP 的核心交互风格通常是 request-response。哪怕它支持流式进度、notification、甚至 richer interaction,它的本质仍然是:client 在 orchestrate,server 在 expose capabilities。

这也是为什么 MCP 非常适合以下对象:

  • search service
  • docs service
  • filesystem bridge
  • browser automation
  • database access
  • design/data/API connectors

这些东西当然重要,但它们本质上是“能力”而不是“同事”。它们不需要有自己的任务计划,也不需要对外暴露完整的工作生命周期。

另外,MCP 往往是 session-scoped 的。Host 在一个会话里连接 server、列出 tools/resources/prompts、持续调用。Server 也许有状态,但这种状态一般是服务于 host 当前 session 的,而不是一个独立 agent 的长期任务状态机。

A2A 面向的是什么问题

A2A 的出发点完全不同。它假定对面不是一个被动的 capability endpoint,而是另一个具有自主性的 agentic actor。也就是说,对面可能有自己的 model、memory、planning loop、permission policy、execution runtime。这样一来,通信就不能仅仅是“method + params”的问题了。

所以 A2A 更强调 task delegation。一个 agent 把工作提交给另一个 agent;另一个 agent 可以接受、拒绝、请求补充信息、开始工作、回报进度、最后完成。于是协议里必须显式表达 task lifecycle(任务生命周期),最典型的形态就是:

submitted → working → completed

在真实系统里还可能扩展出 failed、blocked、canceled、needs-input 等状态,但关键点在于:A2A 不是单次函数调用,而是一个持续存在的工作实体。

A2A 另一个有代表性的概念是 Agent Cards。可以把它理解成 agent 的机器可读名片:它声明这个 agent 是谁、擅长什么、接受什么输入、遵守什么限制、如何联系。这个术语同样不属于传统 CS 教材里的经典概念,更接近 AI multi-agent 系统中新出现的 service discovery 机制。若说 MCP server 暴露的是 capability list,那么 Agent Card 暴露的是“一个自治工作者的服务画像”。

因此,A2A 更适合以下场景:

  • 把 research 委托给 specialist agent
  • 把 implementation 委托给 coding agent
  • 把 verification 委托给 testing/review agent
  • 在不同组织或不同 vendor 的 agent 之间建立协作
  • 对长任务进行状态跟踪、取消与回收

换句话说,A2A 是为“智能体之间的协同”设计的,而不是为“智能体访问工具”设计的。

最关键的差异:intelligence 在哪里

理解 MCP 与 A2A 的最好方法,是看 intelligence placement

MCP 中,主要 intelligence 在 client。Server 可以内部很复杂,但对协议来说,它仍然是被 host 调度的能力端点。

A2A 中,intelligence 在 双方。发起方要决定委托给谁、何时取消、如何处理部分结果;接收方要决定如何分解任务、如何汇报状态、何时视为完成。

这个差异会影响一整套系统设计。MCP 的返回值通常可以被压扁成 tool output;而 A2A 的返回值往往需要被建模成 task object、status transition、partial result、ownership boundary。信任模型、UI 表达、调度策略都不同。

它们并不是竞争关系,而是互补关系

一旦看清“纵向能力访问”和“横向协同委托”的差别,就会发现 MCP 与 A2A 并不存在真正的替代关系。一个成熟的未来 agent system,大概率两者都需要。

例如,设想一个 2026 年的软件工程 Agent workflow:

  1. 一个 coordinator agent 收到功能需求。
  2. 它通过 A2A 把架构分析交给 architecture agent,把代码库调研交给 explore agent,把测试策略交给 verification agent。
  3. 这些子 agent 在各自工作过程中,再通过 MCP 调用外部能力:docs server、GitHub search、browser tools、filesystem tools、memory system 等。
  4. coordinator 收集各个 A2A task 的结果,再决定后续实施路径。

这个 layered picture 非常自然:

  • MCP 负责 tool access
  • A2A 负责 agent coordination

一个给 agent “手和外设”,另一个给 agent “同事和协作网络”。

对比表

维度MCPA2A
主要关系Agent 到 tool/data serverAgent 到 agent
集成方向纵向(vertical)横向(horizontal)
核心单位Tool / Resource / PromptTask / Delegate / Status
intelligence 主要位置主要在 client双方都有
交互模式请求-响应式能力访问委托-协作式任务流转
状态模型通常附着于 session明确的 task lifecycle
发现机制Server capabilitiesAgent Cards
最适合场景搜索、文档、数据库、浏览器、文件、API研究委托、专家协作、多智能体编排
常见失败类型tool error、auth error、schema mismatch、timeouttask blocked、rejected、canceled、责任边界冲突
未来角色外部能力的标准底座多智能体协同的标准底座

对 coding agent 设计的启示

对于 coding agent 来说,一个非常实际的判断标准是:你现在面对的边界,到底是“能力边界”,还是“自治边界”

如果你做的是单智能体编码助手,首先应该优先把 MCP 做好。因为一个单 agent 的上限,往往取决于它能否标准化访问搜索、文档、代码库、浏览器、数据源和其他工具。MCP 是最小可行的 extensibility substrate。

但一旦系统进入 multi-agent orchestration,例如 background specialist、review agent、verification agent、planner/worker 分工,仅靠 MCP 就不够了。你当然可以把“委托另一个 agent”勉强建模成 tool call,但这会在语义上越来越别扭:tool call 天然缺少 owner、status、partial completion、cancelation 这些任务语义。此时 A2A 就会变得必要。

更深的一层启示是:行业可能正在走向一种 two-protocol architecture。一个协议负责 agent 连接外部世界的能力层,另一个协议负责 agent 之间的协作层。这其实很像分布式系统发展史:资源访问和工作协同,往往最终会演化成不同的协议层。Agent 世界现在也在走向类似分化。

所以,真正正确的问题并不是“该选 MCP 还是 A2A”。正确的问题是:你试图标准化的是哪一种边界?如果是 agent 与 capability provider 的边界,MCP 是对的;如果是一个自治工作者与另一个自治工作者之间的边界,A2A 才是对的。

未来并不会出现一个协议吃掉一切的局面。更可能出现的是分层互操作:MCP 标准化 agent 可调用的世界,A2A 标准化 agent 可协作的世界。两者合起来,才构成真正完整的 agent software stack 控制平面。

模型: openai/gpt-5.4 生成日期: 2026-04-01 书名: Claude Code VS OpenCode:架构、设计与未来 章节: 第8章 — 配置与可定制性 Token消耗: N/A(当前运行环境未暴露按文件统计的Token数量)

8.1 多层配置优先级

配置优先级是一个 AI Coding Agent 从“能跑的工具”走向“可治理系统”的分水岭。表面问题很简单:同一个选项在多个地方都定义了,谁生效?但更深层的问题是:系统到底愿意给用户多少灵活性,以及这种灵活性会带来多大的理解成本。

OpenCode、Claude Code 和 Oh-My-OpenCode(简称 OMO)在这个问题上的答案明显不同。

OpenCode:七层优先级,极强弹性

OpenCode 的配置层级是三者中最丰富的。在 config/config.ts 中,配置加载顺序被明确写成从低到高的七层:

  1. 远程 .well-known/opencode
  2. 全局 ~/.config/opencode/opencode.jsonc
  3. 自定义 OPENCODE_CONFIG 路径
  4. 项目级 opencode.jsonc
  5. .opencode/ 目录配置
  6. 内联 OPENCODE_CONFIG_CONTENT
  7. 企业托管 managed config

这里的“优先级”不是简单的文件覆盖,而是一套治理结构。

最底层的远程 .well-known/opencode 可以理解为组织级默认设置,相当于平台或团队统一下发的基础策略。用户家目录中的全局配置则表达个人偏好。OPENCODE_CONFIG 提供显式的外部覆盖入口,适合脚本、实验环境或容器。项目级 opencode.jsonc 让仓库自身带有约束。.opencode/ 层又进一步把配置扩展到 agents、commands、plugins 等目录化资源。OPENCODE_CONFIG_CONTENT 则是一次性的运行时注入。最后,managed config 作为企业控制面,拥有最高优先级。

也就是说,OpenCode 把配置视为一个“合并图”而不是单文件。对平台工程师、插件作者和高级用户来说,这非常强大,因为它同时支持组织策略、个人习惯、项目规则与运行时覆盖。

config/paths.ts 进一步强化了这一点:它会沿目录树向上查找项目配置文件和 .opencode 目录。这种向上遍历意味着配置不仅与当前目录相关,也与目录层级有关。离当前工作目录越近,配置越具体。

还有一个看似细小、实则重要的实现细节:OpenCode 支持 JSONC、环境变量替换、文件内容替换以及 deep merge。JSONC 可以理解为“带注释和尾逗号的 JSON”。它不是 CS 教科书中的标准术语,但本质上是为了提升人类可维护性:配置不再只是机器格式,也变成了面向开发者的说明载体。

Claude Code:层级更少,认知负担更低

Claude Code 的配置模型明显更收敛。高层心智模型大致可以概括为:

  • 全局 ~/.claude/settings.json
  • 项目 .claude/settings.json
  • 企业托管 managed settings

虽然源码里还有更细的 managed 路径、remote managed settings、local settings 等实现细节,但对用户暴露出来的主模型是相对简单的:一个全局文件、一个项目文件,再叠加组织策略。

这是一种典型的商业产品取向。Claude Code 更强调稳定性、可预测性和可支持性。层数越少,排查时越容易定位:通常不是用户全局设置有问题,就是项目 .claude/settings.json 在起作用,或者组织策略覆盖了它们。

代价也很明确:可组合性弱于 OpenCode。像内联配置注入、替代配置根目录这类高级玩法,在 OpenCode 中更自然,在 Claude Code 中则不是主要设计目标。Claude Code 选择的是“受控的配置表面”,而不是“最大化可塑性”。

OMO:三层插件配置,刻意保持收敛

OMO 在 OpenCode 之上引入了自己的配置系统,但它刻意把这套系统设计得很窄。在 src/plugin-config.ts 中,加载顺序是:

  1. 默认值 defaults
  2. 用户级 ~/.config/opencode/oh-my-opencode.jsonc
  3. 项目级 .opencode/oh-my-opencode.jsonc

只有三层。

这并不代表 OMO 简陋,而是因为它没有试图替代 OpenCode 的宿主配置。OpenCode 仍然负责远程配置、全局配置、项目发现、企业级托管策略等宿主层问题。OMO 只负责表达插件自己的 orchestration(编排)逻辑,比如 agents、categories、hooks、commands、skills、Claude Code 兼容选项和 experimental 功能。

也就是说,OMO 的“层数少”,不代表“表达能力弱”。实际上,src/config/schema/ 下有 22 个 Zod v4 schema 文件。Zod 是 TypeScript 生态里常用的数据校验库;schema 可以理解为“配置结构的可执行类型定义”。这说明 OMO 选择的是:优先级层数少,但每一层内部的结构能力很丰富。

OMO 同样支持 JSONC。对于经常调试多智能体编排的用户来说,这比看上去更重要。因为此类配置往往需要反复试验,注释和尾逗号会显著降低修改成本。

另外,OMO 还有一个很实用的策略:partial fallback。它在配置某一部分校验失败时,可以跳过无效 section,仅加载合法部分。这个术语也不属于经典 CS 教科书固定词汇,它的意思是“部分降级加载”。这种设计明显偏向开发者体验:尽量避免因为一个局部错误让整个插件不可用。

OMO 的三层如何与 OpenCode 的七层共存

理解这件事最好的方式,是把 OMO 看成“嵌套在宿主之上的子配置系统”。

先由 OpenCode 完成宿主层七级优先级解析,建立整体运行环境;然后 OMO 再在这个环境内部加载自己的 oh-my-opencode.jsonc。两者并不在同一个命名空间里竞争,而是位于不同架构层。

这是 OMO 非常漂亮的设计点之一。假如 OMO 也复制一套七层结构,用户就不得不同时理解两条交叠的优先级链,心智负担会迅速失控。OMO 的做法是:宿主级问题交给 OpenCode,编排级问题留给 OMO。

这对 Agent 系统设计是一个普适原则:扩展层不应该无必要地复制宿主的配置层级。否则每个插件都会在宿主内部再造一个“次级操作系统”。

设计哲学:层级越多,越灵活,也越容易迷失

这一节真正要讨论的,不是“谁更好”,而是“谁愿意承受多少复杂度”。

OpenCode 把灵活性推到很高,适合 power user、平台团队和扩展作者。但七层优先级确实很难长期放在脑子里。一旦行为异常,排查配置相互作用本身就会变成一个系统工程问题。

Claude Code 则明显压缩了这一复杂度。它牺牲了一部分弹性,换来更容易教学、支持和审计的配置模型。

OMO 走的是折中路线:它建立在复杂宿主之上,但自己的插件层保持克制。这可能是最可扩展的形态之一:平台本身可以很强大,而每个扩展都尽量自律。

更抽象地说,配置优先级本质上是一种“隐藏控制流”。控制流是教科书里的经典概念,指程序执行路径如何分支、选择、覆盖。配置层越多,用户越需要在脑中模拟这条隐藏路径。只不过这里的分支不是 if/else 写在代码里,而是分散在多个文件和作用域中。

因此,优秀的 Agent 配置系统不应只是不断增加层级,而应让每一层对应真实的所有权边界:组织、用户、项目、运行时、企业策略。只有当层级与社会结构一致时,用户才能真正理解它。否则,灵活性就会迅速变成雾。

模型: openai/gpt-5.4 生成日期: 2026-04-01 书名: Claude Code VS OpenCode:架构、设计与未来 章节: 第8章 — 配置与可定制性 Token消耗: N/A(当前运行环境未暴露按文件统计的Token数量)

8.2 项目记忆系统

配置决定智能体在会话开始前“应该怎样工作”,而记忆系统决定会话结束后“哪些东西应该留下来”。在现代 AI Coding Agent 中,记忆早已不只是聊天历史。它更像是一层持久化知识结构,用来保存协作习惯、项目上下文和非代码层面的长期信息。

本书讨论的三个系统有一个共同起点:它们都把 CLAUDE.mdAGENTS.mdREADME.md 这类 Markdown 文件当作知识载体。这个约定非常关键,因为它同时服务两类读者:人类开发者可以直接维护,Agent 也能直接注入到上下文中。

共同约定:用 Markdown 做可审计知识库

OpenCode、Claude Code 和 OMO 共享的核心模式,是把项目知识外化到纯文本文件里。README.md 首先是写给人的,但它也天然是 Agent 的项目背景材料。CLAUDE.mdAGENTS.md 则更偏向智能体使用,它们承载规则、约束、工作方式和局部约定。

这背后有一个非常重要的架构变化:项目记忆不再完全藏在黑盒数据库里,而是部分转化为可读、可 diff、可 review、可版本化的工件。

Claude Code:类型化记忆模型

Claude Code 在记忆建模上走得最远。在 src/memdir/memoryTypes.ts 中,它把记忆明确分成四类:

  • user
  • feedback
  • project
  • reference

这四类并不是随意命名,而是对“什么值得长期记住”做了边界约束。

user 记录用户的角色、偏好和能力结构。feedback 记录用户或团队对工作方式的反馈,例如“不要这样做”“以后保持这种方式”。project 记录项目中的进行中目标、约束、时间点、事故背景等,它们通常无法仅靠读代码推导出来。reference 则记录外部系统入口,比如 Linear、Grafana、文档站点、Slack 频道等。

更重要的是,Claude Code 还明确规定什么“不应该”写进记忆。比如代码模式、架构结构、文件路径、git 历史,以及已经写在 CLAUDE.md 里的内容,都不应存入 memory。这个边界非常成熟:记忆只保存“不可从当前项目状态直接推导”的信息。

Claude Code 还支持 scope,也就是作用域。它区分 private memory 和 team memory。可以把 scope 理解为“知识的归属边界”:有些记忆只属于某个用户,有些应该对团队共享。源码中的 teamMemPaths.ts 展示了这套路径与校验逻辑。

此外,Claude Code 对记忆陈旧性也有明确处理。memoryAge.ts 会把记忆转化为 “today”“yesterday”“47 days ago” 这样的可读年龄,并在较旧记忆上加 freshness warning。这个设计很有深度,因为 persistent memory 最大的问题不是“忘记”,而是“记错且不自知”。Claude Code 明确承认 memory 是时间切片,而不是实时真相。

OpenCode:更像 instruction memory,而不是 typed memory

OpenCode 的持久化思路不同。它在 session/instruction.ts 中负责发现并加载 AGENTS.mdCLAUDE.md 以及旧的 CONTEXT.md。这些文件既可以来自全局目录,也可以沿项目目录树向上查找;同时还支持配置中声明的 instruction 路径和 URL。

这意味着 OpenCode 更像是在构建一套 instruction management system,而不是 Claude Code 那种强类型 memory store。它假设长期知识最好通过“文档化指令”来表达,而不是拆成大量细粒度记忆条目。

这并不弱,只是取向不同。OpenCode 擅长的是显式、可检查的上下文注入。Agent 进入仓库后,会沿目录树发现 instruction files,把它们纳入 system prompt 组装流程。随着 agent 深入子目录,局部 instruction 也可以逐步生效。

所以,OpenCode 的记忆更偏向“文档即记忆”;Claude Code 的记忆则是“文档 + 类型化持久知识”。

OMO:自动注入上下文,再加工作记忆

OMO 在这个问题上做得非常工程化。

第一,context-injector 会自动把关键项目文档,例如 AGENTS.mdREADME.md,注入到对话上下文里。这意味着主智能体不需要每次都先自己想到去读这些文件。OMO 把项目背景变成默认存在的底层上下文。

第二,rules-injector 会在相关文件被读取或修改时,把 .sisyphus/rules/*.md 中的规则片段注入进来。这是一种按需激活的记忆机制。它不是把所有规则一股脑塞进 prompt,而是在具体工作触发时注入相关规则。若借用系统领域术语,这更像 demand paging,也就是“按需分页”,而不是一次性静态加载。

第三,OMO 很强调目录级知识局部性。它支持分层 AGENTS.md 的使用。Agent 越深入目录树,越可能命中更具体、更局部的 instruction 文件。对于大型 monorepo,这种局部性非常关键,因为不同子系统往往有不同规范。

第四,OMO 还引入了 Atlas notepad 体系,位于 .sisyphus/notepads/。其中会记录 learnings、issues、decisions、problems 等内容。这和 Claude Code 的长期 typed memory 不完全一样。它更接近一种跨多回合、多子任务的 working memory,也就是“工作记忆”。

“工作记忆”不是教科书里典型的 AI coding 术语,但从计算机系统角度看,可以把它理解为外部 scratchpad:它可以跨轮次持久存在,但仍然强绑定于某个计划、某次编排、某个执行过程。

这个区别很重要。长期记忆保存的是关于用户或项目的较稳定事实;notepad 保存的是某个执行计划中逐步积累的操作性知识。

从 Prompt Engineering 走向 Context Engineering

这三套系统真正共同体现的趋势,是从 Prompt Engineering 转向 Context Engineering。

所谓 Prompt Engineering,本质上是想写出一段足够聪明的说明文字,让模型一直表现良好。Context Engineering 则关注另一件事:什么信息应该被放进上下文、何时放进去、以什么作用域存在、过期后如何提醒或更新。

Claude Code 用 typed memory、scope 和 freshness check 实现这一点。OpenCode 用 instruction file 发现、frontmatter 解析和 prompt 组装实现这一点。OMO 则用自动注入、规则钩子、目录级知识和 notepad 体系,把上下文管理做成了编排基础设施。

这是一种非常本质的升级。Prompt 只是字符串;Context System 则是一套信息架构。

设计启示

好的 Agent 记忆系统至少应满足四个条件。

第一,必须区分“可推导事实”和“不可推导事实”。代码里能重新读出来的东西,通常不应该长期存成 memory。

第二,必须承认记忆会陈旧。没有 aging 机制的 memory,长期看会变成累积性的错误来源。

第三,必须支持多作用域:个人、团队、项目、任务局部。这些作用域对应的是现实世界中的所有权边界。

第四,必须让持久化知识可审计。Markdown、notepad、typed memory files 的共同优点,是人类能检查、修订和删除它们。

所以,未来 Agent 的关键并不只是更大的 context window。更大的窗口当然有帮助,但它并不能自动解决知识组织问题。真正困难的是:哪些内容应该进入 durable instructions,哪些应该写入长期记忆,哪些只适合放在临时 scratchpad,哪些则应始终从 live state 重新计算。

这就是从 Prompt Engineering 走向 Context Engineering 的核心:不是写更漂亮的话,而是设计更清晰的记忆边界。

模型: openai/gpt-5.4 生成日期: 2026-04-01 书名: Claude Code VS OpenCode:架构、设计与未来 章节: 第8章 — 配置与可定制性 Token消耗: N/A(当前运行环境未暴露按文件统计的Token数量)

8.3 指令系统

如果说工具系统是 Coding Agent 的“手”,那么指令系统就是它的“神经系统”。今天的 system prompt 已经不再是一段简单的开场白,而是由多种来源共同组装出来的复合结构:基础身份、行为约束、工具描述、项目规则、记忆内容、权限上下文以及运行时环境。

OpenCode、Claude Code 和 OMO 的一个共同模式是:system prompt 不再是单一 prompt,而是一条 prompt assembly pipeline,也就是“提示词组装流水线”。

OpenCode:分层拼装的 Prompt 架构

OpenCode 在 session/prompt.ts 中把这种设计写得非常清楚。它会将 session/system.ts 生成的环境信息,与 session/instruction.ts 发现的 instruction 文档一起拼接,形成更完整的系统提示。

session/system.ts 负责提供模型身份、工作目录、平台、日期、是否处于 git 仓库等环境信息。这些内容看起来像元数据,但对智能体行为影响很大。知道自己是不是在 git repo、运行在哪个操作系统上、当前工作目录是什么,会直接影响它对工具和文件的判断。

session/instruction.ts 则负责收集 AGENTS.mdCLAUDE.md、以及兼容旧格式的 CONTEXT.md。它不仅会从全局目录找,还会沿项目目录向上遍历;同时还支持配置里声明的 instruction 路径与远程 URL。这意味着 OpenCode 的 system prompt 既有静态部分,也有动态发现部分。

之后的 prompt 组装还会叠加 agent prompt、项目上下文、工具 schema、MCP 能力等内容。最终效果是一个分层结构:环境层、规则层、工具层、任务层共同构成模型真正看到的 system prompt。

这是一种非常“系统工程”的做法。它不是写一大段万能模板,而是把 prompt 当成多个子系统拼出来的结果。

Claude Code:多源合成的系统提示

Claude Code 走的是类似路线,但在 memory 和 policy runtime context 上更进一步。

高层来看,Claude Code 的有效 system prompt 通常来自这些来源:

  • CLAUDE.md 及相关规则文件
  • memory 文件和 memory 行为说明
  • MCP prompts / commands
  • tool descriptions
  • permission context 与执行模式
  • 额外 append 的 system prompt 片段

utils/claudemd.ts 很清楚地展示了它的层级:managed memory、user memory、project memory、local memory 会按优先级加载;同时还支持 @include 指令,让一个 memory file 引入其他文件。也就是说,Claude Code 的 instruction layer 不是扁平文本,而是可组合、可模块化的。

QueryEngine.ts 则展示了拼装动作本身:最终 system prompt 可以由默认 prompt 或 custom prompt,再加上 memory mechanics prompt,以及 appendSystemPrompt 一起组成。与此同时,其他模块还会准备 tool descriptions 和 MCP prompt 数据,让模型不仅知道“你是谁”,也知道“你能做什么”。

Claude Code 还有一个非常关键的点:permission context 也会影响提示边界。权限模式不是单纯的 UI 状态,而是智能体行为边界的一部分。一个运行在严格审批模式下的 Agent,和一个运行在更自动化模式下的 Agent,应该做出不同的规划与预判。从这个角度说,permission context 本身就是 system prompt 的一部分,因为它改变了智能体对“自己能做什么”的信念。

这也是商业 Agent 往往更稳的原因之一:它们不是只靠一段 prose identity 来约束行为,而是把运行时策略直接编码进上下文底座里。

OMO:为不同 Agent 定制 Prompt

OMO 则把指令系统继续推进到了“角色定制化”的阶段。在 dynamic-agent-prompt-builder.ts 中,prompt 不是固定文本,而是由多个模块动态拼出来的,例如 tool selection guidance、delegation table、category-and-skill rules、anti-pattern warning、hard block 等。

这一点在 Prometheus、Sisyphus 系列 Agent 上尤其明显。OMO 不会给所有 agent 一个通用人格,然后让它们自己适配;它会为每个角色生成一份量身定制的 prompt。

这些模块通常包括:

  • identity 与角色定位
  • 任务采访或 intake 规则
  • plan generation 规则
  • tool 和 agent selection table
  • delegation guide
  • 成本约束
  • anti-pattern 与 hard blocks

换句话说,OMO 把 prompt 构造得更像在“编译岗位说明书”。它不只是问“模型总体上该成为什么样”,而是问“这个具体 agent 实例需要带着哪些明确约束、工具、分工和禁令”。

这比传统 prompt template 更进一步。本质上,OMO 在做 prompt modularization,也就是“提示模块化”。这里的模块化不是教科书中标准 AI 术语,但它和软件模块化的思想类似:把一类职责封装成可复用、可组合的 prompt 组件。

“System Prompt 即人格”只是对了一半

在 AI 讨论里,人们常说 system prompt 定义了 agent 的 personality。这句话只说对了一半。

更准确地说,system prompt 同时定义三件事。

第一,是 personality,也就是语气、主动性、协作姿态、表达方式。

第二,是 policy,也就是优先级、工作流程、规则解释方式。

第三,是 perimeter,也就是边界:哪些事情不能做、哪些场景必须申请许可、何时应该委派、哪些推理捷径属于禁止项。

OpenCode 更强调环境信息与 instruction 文件的分层拼装。Claude Code 更强调 memory、MCP、tools 和 permission 的多源合成。OMO 更强调每个 agent 的角色化 prompt 定制。

它们不是互斥的,而是在同一条架构光谱上的不同侧重点。

为什么模块化指令系统很重要

随着 Coding Agent 越来越强,指令系统正在成为新的可扩展性瓶颈。单体大 prompt 很难维护、很难排错、也很难局部覆盖。模块化组装可以同时解决几个问题。

第一,它支持 source attribution,也就是行为来源可追踪。一个行为到底来自 AGENTS.md、memory、managed policy,还是某个 agent 专属 section,可以更容易定位。

第二,它支持 selective override,也就是局部覆盖。团队规则可以覆盖个人习惯,项目上下文可以覆盖通用默认值。

第三,它支持 specialization,也就是专业化分工。不同 agent 可以共享基础层,同时在某些 section 上进行受控分叉。

如果借用计算机科学中的类比,单体 prompt 很像一个巨大且难维护的 global variable;而模块化 instruction system 更像 dependency injection:行为由多个有明确所有权边界的组件共同提供。

这个类比很重要,因为 prompt 复杂度已经大到必须用软件工程方法来治理。

未来方向:从单一 Prompt 走向 Prompt Graph

未来最可能的方向,不是继续堆砌一段越来越长的 universal system prompt,而是形成 prompt graph。

这里的 prompt graph 不是传统教材中的固定术语,可以把它理解为“按作用域、角色、工具、任务类型动态激活的提示组件网络”。有些组件总是存在,比如身份和安全边界;有些组件是条件触发的,比如项目规则、memory reminder、MCP prompt、delegation protocol。

OpenCode 通过 layered discovery 与 composition 已经隐约体现了这一点。Claude Code 通过 memory scope、permission-aware context、MCP prompt conversion 进一步逼近。OMO 则最明确,它已经在为不同 agent 生成不同的 prompt 体。

因此,本章最重要的结论是:指令系统不应该再被当作“文案”来写,而应该被当作“基础设施”来设计。

下一代优秀的 Coding Agent,决定性差异未必是那段 base prompt 更会说话,而更可能是它拥有更成熟的 instruction assembly architecture:模块化、可检查、作用域感知、角色感知,并且和工具系统、记忆系统、权限系统紧密耦合。

到那时,system prompt 就不再只是一段文字,而会成为 Agent 的“软件定义人格边界”。

章节: 第9章 — OpenCode的独特贡献 书名: Claude Code VS OpenCode: Architecture, Design and The Road Ahead 模型: openai/gpt-5.4 Token 用量: ~3,000 tokens 生成日期: 2026-04-01

9.1 多界面架构

在本书比较的三个系统中,OpenCode 有一个非常突出的特点:它不是一个“只有命令行”的 coding agent,而是一个“单一核心引擎 + 多个前端界面”的系统。更具体地说,OpenCode 把同一套 agent 核心能力暴露给四类前端:基于 yargs 的 CLI、基于 Solid.js 的 TUI、基于 Solid.js + Tailwind + Vite 的 Web app,以及基于 Tauri + Rust 的 Desktop 应用。这不是表面层的产品包装差异,而是架构层的设计选择。

先看 CLI。packages/opencode/src/index.ts 清楚展示了 OpenCode 的命令行入口:它用 yargs 注册 runservewebacp、TUI 等一系列命令。这里的重点不是“它有很多命令”,而是 CLI 在 OpenCode 里只是一个接入面。也就是说,命令行并不是整个系统的唯一承载方式,它只是核心服务的一种消费方式。很多 coding agent 把 CLI 当成产品本体;而 OpenCode 更像是在把 CLI 视为一个 client。

再看 TUI。TUI 是 Terminal User Interface,中文可理解为“终端用户界面”:它不是简单打印文本,而是在终端里运行一个带状态、可交互、可导航的全屏界面。packages/opencode/src/cli/cmd/tui/app.tsx 里可以看到很深的 Solid.js provider 树:Route、SDK、Sync、Theme、Dialog、PromptHistory、Local state 等上下文层层嵌套。这说明 OpenCode 的 TUI 不是一个薄薄的 ANSI 包装层,而是被当成“真正的应用界面”来构建的。它具备响应式状态管理、路由、主题、弹窗和同步机制,说明终端体验在 OpenCode 中是第一等公民。

Web app 则把同一套能力迁移到浏览器环境。packages/app/package.json 表明它采用了 Solid.js、Vite 和 Tailwind 的组合。这里需要解释一下:Vite 是现代前端构建工具,强调开发期启动快、热更新快;Tailwind 是 utility-first CSS 框架,强调用小粒度样式类组合界面。OpenCode 选择这种栈,并不是为了“追赶前端时髦技术”,而是因为它把 agent 界面视为一个现代 Web 应用,而不是命令行之外的附属页面。只要底层通过 HTTP 和流式协议暴露能力,Web 前端就能成为自然的消费端。

Desktop 层进一步强化了这个方向。packages/desktop/package.jsonpackages/desktop/src-tauri/Cargo.toml 显示,OpenCode Desktop 采用 Tauri 方案:前端仍是 Web 技术,宿主则是 Rust。Tauri 可以理解为一种“轻量桌面壳”,它让 Web UI 在原生桌面容器中运行,同时把系统级能力交给 Rust 处理,例如窗口、文件对话框、通知、deep link、本地存储等。更关键的是,在 packages/desktop/src/index.tsx 中,Desktop 直接复用了 @opencode-ai/app 提供的 AppBaseProvidersAppInterface。这意味着 Desktop 并没有重新造一套应用逻辑,而是在复用共享的 app 层。

那么,多界面之间如何保持同步?关键在 packages/opencode/src/bus/index.ts。这里定义了 Bus 命名空间,提供 publish/subscribe 能力,还支持通配订阅。所谓 event bus,可以译为“事件总线”:它是系统内部的一条消息通道,组件把事件发布到总线上,其他组件按需订阅,从而避免彼此直接强耦合。对于 agent 系统来说,这很重要,因为会话更新、权限变化、实例释放、全局状态变化,都不该靠每个界面自己轮询猜测。事件总线让不同界面可以实时感知状态变化。

packages/opencode/src/server/server.ts 则把这种多界面架构变成真正的服务层。它使用 Hono 构建 HTTP server,暴露 OpenAPI 文档接口,使用 streamSSE 提供 Server-Sent Events 流,使用 WebSocket 处理 PTY 等实时交互。换句话说,OpenCode 的核心不是被某个界面“包住”的,而是通过标准服务接口对外开放。CLI、TUI、Web、Desktop 都可以共享同一个核心引擎与事件体系。

这正是 OpenCode 与 Claude Code、Oh-My-OpenCode 不同的地方。Claude Code 的体验非常成熟,但重心仍然主要在 terminal 产品本身。Oh-My-OpenCode 则是构建在 OpenCode 之上的 orchestration layer,它增强了 agent 编排能力,但并没有自己重新定义一套“多前端宿主平台”。OpenCode 的独特贡献恰恰在于:它把 coding agent 设计成“平台核心 + 多个一等前端”,而不是“一个 CLI,外加一些附属壳”。

从架构设计角度看,这种模式的价值很大。它降低了重复开发:一个核心引擎可以服务多种交互场景;它提高了产品韧性:如果某个前端形态不理想,不必重写底层;它也提升了扩展性:未来新增 IDE 面板、浏览器扩展、云控制台时,成本会更低。

因此,OpenCode 在这一章给出的启示非常明确:真正成熟的 agent,不应该被某一个界面绑定。只要核心能力和表现层被严格分离,新界面就不再是“重做产品”,而只是“再接一个 client”。这是 OpenCode 最容易被低估、但非常关键的创新之一。

章节: 第9章 — OpenCode的独特贡献 书名: Claude Code VS OpenCode: Architecture, Design and The Road Ahead 模型: openai/gpt-5.4 Token 用量: ~2,900 tokens 生成日期: 2026-04-01

9.2 ACP智能体客户端协议

OpenCode 对 ACP(Agent Client Protocol)的支持,是它最有战略意义的设计之一。packages/opencode/src/acp/ 目录下的 agent.tssession.tstypes.ts 清楚表明:OpenCode 不只是一个“用户手动运行的 agent”,它还是一个可以被外部客户端程序驱动的 agent runtime。这个差异很关键,因为它意味着 OpenCode 从“工具”走向了“平台能力”。

ACP 在 OpenCode 中依赖 @agentclientprotocol/sdk 实现。它的基本通信方式可以概括为:JSON-RPC over stdio。这里需要解释两个术语。JSON-RPC 是一种轻量的远程调用协议,通信双方使用 JSON 描述“我要调用什么方法、传什么参数、返回什么结果、出现什么错误”。stdio 则是 standard input / standard output,也就是标准输入输出流,是本地进程之间最简单、最稳定的通信管道。把两者放在一起,本质上就是:外部客户端启动 OpenCode 进程,然后通过结构化 JSON 消息和它通信。

这和 MCP 要分清。MCP(Model Context Protocol)解决的是“agent 如何访问工具和外部资源”的问题;ACP 解决的是“外部客户端如何驱动 agent 本身”的问题。前者是 agent-to-tool,后者是 client-to-agent。它们不是竞争关系,而是不同层级的协议。

acp/types.ts 定义了 ACP 会话最基础的状态结构:session ID、工作目录、挂载的 MCP servers、可选的 model 信息、variant 和 mode ID。acp/session.ts 则把这些状态封装进 ACPSessionManager,提供 create、load、get、setModel、setVariant、setMode 等能力。为什么这很重要?因为 IDE 集成从来不只是“把 prompt 发进去”这么简单。真正可用的 editor integration 必须能恢复会话、切换模型、保留工作目录上下文、同步模式状态。

真正复杂的部分在 acp/agent.ts。这里的 ACP.Agent 类负责承接协议侧连接、持有 OpenCode SDK、管理 ACP session、订阅全局事件、转译权限请求,并把状态更新回推给客户端。换句话说,ACP 在 OpenCode 里不是一个“很薄的适配器”,而是一个真正的中介层。它把 OpenCode 内部运行时和外部客户端的交互协议分开了。

这层设计有几个特别重要的点。第一,ACP 会监听 OpenCode 的事件流,并把使用量、会话进展、权限请求等信息同步给客户端。这样一来,客户端可以实时显示 agent 状态,而不是被动等待文本输出。第二,ACP 显式处理权限。比如 agent 需要执行 edit 操作时,ACP 可以把权限请求抛给外部客户端,由客户端用自己的 UI 来展示确认流程,而不是强依赖终端里的交互提示。这对 IDE 很关键,因为 IDE 希望用原生对话框、侧边栏或 inline 审批,而不是让用户切回 shell。

第三,OpenCode 的 ACP 已经包含了面向具体编辑器的语义。agent.ts 中的 parseUri 明确处理了 zed:// URI,这表明 ACP 并不是停留在抽象层面的“未来标准”,而是已经在为 Zed 这类编辑器集成做准备。

为什么 ACP 重要?因为现在很多 agent 和 IDE 的结合方式都很别扭。要么把整套 agent 逻辑直接塞进 editor plugin 里,导致重复实现、重复维护;要么通过 CLI 做各种不稳定的桥接,靠解析日志、封装自定义命令凑合使用。ACP 提供了第三条路:让 agent 成为一个通过协议暴露能力的本地服务,而编辑器只是它的宿主或客户端。

这种模式带来的好处非常直接。对 IDE 厂商来说,不必为每个 agent 都写一整套定制逻辑。对 agent 开发者来说,也不必为每个编辑器重新发明集成方式。只要双方都实现 ACP,对接成本就会显著下降。更进一步,客户端可以专注在 UX 层——比如如何展示会话、如何审批权限、如何插入上下文;而 agent runtime 则专注在工具执行、上下文管理、模型调用和任务规划。

与 Claude Code 相比,这一点尤其突出。Claude Code 在工程化和体验上很强,但它并不是围绕一个开源可审查的“client-agent protocol”来展开其对外集成能力。Oh-My-OpenCode 虽然极大增强了编排与多智能体,但它更多是在继承和扩展 OpenCode 的宿主能力,而不是重新定义外部客户端协议层。因此,ACP 可以视为 OpenCode 自身非常独特的一项贡献。

更深层地看,ACP 代表的是 agent 生态的“第二波协议化”。第一波协议化主要是工具层,例如 MCP 让 agent 可以标准化访问外部能力。第二波则是运行时托管层:客户端如何启动 agent、附加会话、传入编辑器上下文、处理权限、接收流式更新。ACP 正是在这个方向上的一次早期但重要的尝试。

因此,对未来 agent 设计者而言,教训很明确:不要把 agent 和客户端界面死死绑在一起。应该在它们之间建立一个协议边界。一旦这个边界清晰,terminal、IDE、browser、notebook、自动化系统都可以共享同一个 agent engine。OpenCode 的 ACP 支持,正是在向这个方向迈出关键一步。

章节: 第9章 — OpenCode的独特贡献 书名: Claude Code VS OpenCode: Architecture, Design and The Road Ahead 模型: openai/gpt-5.4 Token 用量: ~2,800 tokens 生成日期: 2026-04-01

9.3 命名空间组织模式

OpenCode 有一个不那么显眼、但非常值得深入讨论的设计选择:它大量使用 TypeScript namespace 来组织核心模块。在今天的 TypeScript 社区里,namespace 往往不算“流行写法”,很多项目更偏好扁平 exports、工具函数文件、或者 class-oriented 结构。但 OpenCode 明显走了另一条路。在它的核心代码中,可以反复看到 AgentToolSessionProviderBus 这样的命名空间,每个命名空间内部又同时承载 schema、type、state、helper 和 operation。

这一点在多个文件里都很明显:agent/agent.tstool/tool.tssession/index.tsprovider/provider.tsbus/index.ts。例如,Tool 命名空间不仅定义了 tool 的核心接口和上下文类型,还包含 define 这样的统一注册入口;Agent 命名空间既定义 agent 的 schema,也维护内置 agent 配置和权限合成逻辑;Session 命名空间则把 session 的数据结构、数据库 row 转换函数、事件定义、生命周期操作都放在一起。也就是说,namespace 在 OpenCode 里并不是语法层的小偏好,而是一种系统性的模块边界表达方式。

为什么这种做法重要?因为在 coding agent 代码库中,最容易失控的往往不是算法,而是概念命名。随着系统变大,会出现大量语义接近却不完全相同的对象:session info、agent info、tool metadata、provider config、message part、event payload、permission rule 等。如果使用完全扁平的导出风格,很容易陷入两种问题:要么名字越来越长,例如 createSessionInfoFromRowproviderDefaultModeltoolDefine;要么名字过于通用,例如到处都是 Infocreategetupdate,最后只能靠 import alias 苦苦维持清晰度。

namespace 恰好缓解了这个问题。因为一旦有了 Session.InfoTool.InfoAgent.Info,内部依然可以保留自然的命名,而不会造成全局污染。Session.createSession.EventSession.fromRow 看起来也很顺手;Tool.defineTool.ContextTool.Info 也非常直观。也就是说,OpenCode 通过命名空间保留了“局部自然命名”和“全局可区分性”这两件常常互相冲突的事情。

除此之外,这种模式还和状态管理结合得很好。OpenCode 经常把 Instance.state(...) 放在 namespace 内部,意味着这个命名空间不只是函数集合,而是该概念的状态容器与生命周期边界。用软件架构语言来说,这是一种以 domain 为中心的模块组织方式。所谓 domain module,可以理解为“围绕业务概念组织的模块”,而不是围绕技术层次(比如 controller、service、util)组织的模块。OpenCode 的 AgentSessionProviderBus 基本都具备这种特征。

这种设计特别适合 agent 系统。因为 agent 平台的复杂度,本质上首先是“概念复杂度”,其次才是“算法复杂度”。难点不在于实现某个高级数据结构,而在于保持工具系统、会话系统、权限系统、模型系统、事件系统、UI 系统之间的边界清晰。如果边界不清晰,几个月后整个代码库就会开始长出大量灰色耦合。OpenCode 通过 namespace 把这些边界直接写进了代码结构里。

把它和 Claude Code 常见的更扁平模块风格相比,就能看出差异。扁平 exports 在小型项目里通常很优雅,也更贴近现代 ES module 习惯。但在复杂系统中,它容易逐渐演化成“大量 helper + wrapper + import alias”的局面。OpenCode 则愿意接受一种更有风格、更偏主观的组织方式,以换取更强的概念内聚性。

当然,这种模式并非没有代价。有些开发者会认为 namespace 不够“现代”;某些工具链或团队规范也更偏好纯 ES module 风格。不过,OpenCode 给出的例子说明,一个模式是否合适,关键不在潮流,而在于它是否降低了长期维护的认知成本。从这个角度看,namespace 在 OpenCode 中是成功的。

更重要的是,这种模式提醒我们:agent 架构的优劣,不只是协议、模型、工具数量这些显性部分决定的,也深受代码组织方式影响。一个系统越强调 extensibility 和长期演化,越需要概念模块化,而不是只靠文件拆分。OpenCode 的 namespace pattern,本质上就是一种“概念级封装”。

因此,这一节的结论很简单:OpenCode 的命名空间组织模式,也许不炫技,但它是相当成熟的工程判断。它让复杂 agent runtime 在概念上更可导航、更少命名冲突、更利于扩展。对正在设计大型 agent 系统的人来说,这是非常值得借鉴的一课。

章节: 第9章 — OpenCode的独特贡献 书名: Claude Code VS OpenCode: Architecture, Design and The Road Ahead 模型: openai/gpt-5.4 Token 用量: ~2,950 tokens 生成日期: 2026-04-01

9.4 SDK与可编程性

OpenCode 最具前瞻性的理念之一,是把 coding agent 视为一种“可编程基础设施”,而不只是一个“人在终端里使用的智能工具”。这种理念主要体现在两个地方:packages/sdk/js/ 下的 JavaScript SDK,以及 packages/opencode/src/server/server.ts 中的 HTTP server。两者合在一起,说明 OpenCode 的目标并不只是做好一个 CLI,而是把 agent 核心做成可被其他软件调用的服务。

先看 SDK。packages/sdk/js/package.json 导出了多个入口,包括 v2 client 和 server 相关入口。更关键的是 packages/sdk/js/script/build.ts。这个脚本会先在 opencode 主包中运行 bun dev generate > openapi.json,然后把生成出的 OpenAPI 规范交给 @hey-api/openapi-ts,自动生成类型化的客户端代码。这里有两个关键词需要解释。OpenAPI 是一种标准 API 描述格式,用机器可读的方式定义接口路径、请求参数、响应结构和 schema。类型化客户端则是指:根据 API 描述自动生成带类型约束的调用代码,避免手写 HTTP 请求和手写数据结构。

这意味着 OpenCode 的 SDK 不是“手写的一套便利封装”,而是建立在服务契约之上的自动生成层。这个差异非常重要。它说明 OpenCode 把 API 视为第一等接口,而不是只给自己的前端随便留一个内部调用口。只要服务端 contract 变化,SDK 就可以重新生成,服务端与客户端的一致性也更容易维持。

server.ts 进一步印证了这一点。OpenCode 使用 Hono 构建 HTTP app,注册了 /project/session/config/provider/mcp/tui/permission 等多个 route group,同时通过 /doc 暴露 OpenAPI 文档。除此之外,它还支持 streamSSE 提供 Server-Sent Events,以及 WebSocket 实时连接。SSE 可以理解为“服务端持续向客户端推送事件的单向流”;WebSocket 则是双向实时通道。它们都不是传统 CLI 世界必须具备的能力,却是平台型 runtime 很典型的能力。

为什么这件事重要?因为“可编程 agent”和“交互式 agent”能支撑的是两类完全不同的场景。交互式 agent 主要服务单个开发者在某个界面里使用;可编程 agent 则可以被 IDE、CI、内部平台、测试系统、自动化工作流、管理后台、多智能体协调器等外部程序集成。一旦 agent 拥有稳定 API,它就不再只是一个人机交互产品,而是一个软件组件。

这直接带来一个重要收益:开发者不必再围绕 CLI 做大量脆弱的 shell glue code。很多团队最早的自动化方式,都是“先调用命令行,再解析输出文本”。这种方式启动快,但非常脆弱,尤其当系统涉及流式响应、会话状态、权限审批、结构化事件、模型切换时,shell 包装就会迅速变得难以维护。OpenCode 通过 HTTP server + SDK 的方式,把这些问题提升到了正确的抽象层次上。

这也解释了为什么 OpenCode 的多界面架构能够成立。Web app 和 Desktop app 之所以能够作为较薄的前端存在,是因为底层本来就已经服务化。也就是说,SDK 与 HTTP server 不是附加品,而是 OpenCode 整体哲学的一部分:核心集中、接口清晰、多个客户端共享同一运行时。

和很多只能“跑 CLI”的 coding agent 相比,OpenCode 这里给出的方向非常明确:未来的 agent 不该只是一个聪明的命令行程序,而应该成为一个可嵌入、可编排、可自动化调用的 service。实际上,这也是 Oh-My-OpenCode 能够建立在 OpenCode 之上的重要原因之一。只有宿主平台本身足够可编程,上层 orchestration layer 才容易长出来。

从更宏观的行业角度看,这代表着一个范式迁移:从“AI assistant as app”走向“AI agent as infrastructure primitive”。在前一种范式里,关键指标是某个主界面的交互体验;而在后一种范式里,关键指标还包括:能否被集成、能否被脚本化、能否被生成 SDK、能否被其他系统稳定复用。OpenCode 显然是在朝后者靠拢。

这并不是说所有团队都应该一开始就做 API 和 SDK。对许多原型型 agent 来说,先把 CLI 做好是合理路径。但 OpenCode 至少指出了一条成熟路线:当 agent 的价值已经被证明,下一步不一定是继续堆命令,而可能是建立服务边界、定义 schema、生成 typed client,让它真正变成平台能力。

所以,这一节最核心的结论是:OpenCode 的独特贡献,不只是“提供了一个 SDK”,而是提出了一种 agent 产品观——coding agent 不只是终端里的工具,它也应该是程序可调用的服务。这种视角在未来只会越来越重要。

章节: 第9章 — OpenCode的独特贡献 书名: Claude Code VS OpenCode: Architecture, Design and The Road Ahead 模型: openai/gpt-5.4 Token 用量: ~2,850 tokens 生成日期: 2026-04-01

9.5 计划模式

OpenCode 的 plan mode(计划模式)看起来很朴素,但它实际上体现了一个非常深刻的 agent 设计理念:规划和执行不应该只是 prompt 里的“语气差别”,而应该是运行时层面的不同模式。相关代码主要在 packages/opencode/src/tool/plan.tspackages/opencode/src/agent/agent.ts 中。OpenCode 并没有把“先规划再执行”当成一句建议,而是把它做成了独立 agent、独立权限集和独立切换流程。

agent.ts 中,内置的 plan agent 和默认的 build agent 被明确分开定义。plan agent 的描述非常直接:Plan mode. Disallows all edit tools. 也就是“计划模式,禁止所有编辑类工具”。继续看权限配置,会发现它对 edit 做了广泛 deny,只为计划文件本身保留了非常窄的允许路径。这一点很关键:计划模式并不是“建议模型尽量不要改文件”,而是“从能力层面限制它不能随便改文件”。

这里可以引入一个稍偏理论的词:capability restriction,即“能力约束”。在系统设计里,一个进程能做什么,不只由它的目标决定,更由它被授予什么能力决定。如果一个 agent 仍然拥有写文件能力,那么“请先规划、不要动手”这种要求就只是软约束;模型在某些情境下仍然可能越界。而 OpenCode 的做法是通过权限系统硬性收窄能力集,让计划阶段真正接近 read-only 模式。这里的 read-only 可以理解为“只读模式”:可以查看、搜索、分析、写计划文档,但不能随意修改业务文件。

这是一种非常值得强调的工程思想。很多 agent 系统把行为控制寄托在 prompt 上,希望模型“听话”。但在真正重要的工作流中,单靠文字约束是不够稳的。能靠权限系统表达的东西,就不该只靠 prompt 暗示。OpenCode 的 plan mode 正是在把这一原则贯彻到底。

tool/plan.ts 展示了计划模式如何退出。PlanExitTool 会在计划完成后询问用户:是否切换到 build agent 并开始执行。若用户批准,系统会创建一条 synthetic user message,把当前 session 的 agent 切换到 build,并告诉它“计划已经批准,现在可以编辑文件并执行计划”。这种设计很优雅,原因有两点。第一,它让“规划阶段”和“执行阶段”在会话历史中显式分离。第二,它形成了一个正式的 handoff,即从分析转向实施的明确交接点。

这个 handoff 的价值其实很大。coding agent 常见的问题之一,是 planning 和 implementation 很容易混在一起:系统一边探索代码,一边顺手改一点;改一点之后又继续推演;最后用户很难知道,到底哪些是结论、哪些是试探、哪些已经对代码产生影响。OpenCode 的计划模式则人为插入了一个检查点:先形成计划,再确认,再执行。它把“行动泄漏”压到了更低。

这种模式特别适合高风险任务,例如大规模重构、迁移、未知根因的复杂 bug、架构调整、多文件联动修改等。在这些任务中,过早动手往往会制造更多噪音。一个只读的 planning agent 可以先做 repo 探索、依赖映射、备选方案比较和实施顺序设计,避免系统在理解不充分时就开始 patch。

和 Claude Code 相比,这一点很有代表性。Claude Code 当然也能进行 planning,但 OpenCode 的不同之处在于:它把 planning 做成了硬边界模式,而不是仅仅依赖模型行为。Oh-My-OpenCode 在此基础上进一步发展出更丰富的 orchestration,但 plan/build 这种基础相位划分,本身就来自 OpenCode。

从更一般的 agent 设计角度看,计划模式还揭示了一个重要原则:不同认知阶段,不应该默认拥有相同的行动权限。研究、规划、执行、审查、总结,本质上是不同工作。若这些阶段都共享同一套工具权限,系统实现上会更简单,但控制上会更脆弱。OpenCode 通过一个很朴素的 plan agent 告诉我们:哪怕是最小可用的 agent 平台,也值得把不同阶段拆成不同能力配置。

这背后其实也映射了成熟工程师的工作方式。真正经验丰富的开发者,很少在问题尚未澄清时大面积动手。更常见的顺序是:先调查,再设计,再实施,再回顾。OpenCode 把这种人类工程流程编码进了 agent runtime。本质上,它是在把“好的工程习惯”变成“可执行的系统约束”。

因此,本节的结论非常明确:如果你真的重视 planning,就不要只在 prompt 里说“先想后做”。应该像 OpenCode 一样,为 planning 提供独立模式、独立权限、独立输出物和明确退出路径。计划模式不算炫目的功能,但它也许是 OpenCode 在 agent 行为治理上最干净、最值得借鉴的设计之一。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第10章 — Oh-My-OpenCode的创新
Token用量: 约 4,200 input + 1,150 output

10.1 三层编排架构

Oh-My-OpenCode 最核心的创新,不是某一个 agent,也不是某一个 hook,而是它把编码工作组织成了一套三层编排架构。换句话说,它不把“写代码”理解为一个模型在长上下文里完成的单线程独白,而是把它理解为一个小型工程组织中的分层协作:先规划,再调度,再执行。

第一层是规划层,核心角色是 Prometheus、Metis、Momus。Prometheus 的作用不是简单生成一个 markdown 计划,而是先像顾问一样“访谈用户”。它通过提问、澄清目标、锁定边界,把含糊请求整理成更清晰的任务定义。这个设计非常重要,因为大量 agent 失败并不是代码能力不够,而是在一开始就误解了真实需求。Prometheus 要解决的正是“问题定义错误”这一前置失败点。

但 OMO 并不完全相信单一规划器。Prometheus 在落计划之前,Metis 会先做一轮预分析。Metis 的职责是找隐藏意图、未说出口的约束、缺失的验收标准、模糊边界,以及 AI 容易忽略的前提假设。用更标准的 CS 语言说,它相当于在“提交计划之前”插入了一个专门的风险分析阶段。也就是说,系统不是假设“第一次想到的计划就够好”,而是先问一句:这个计划漏了什么?

接着是 Momus,即计划批评者。在高准确模式下,Prometheus 不是把计划写完就算,而是必须反复提交给 Momus 审核,直到 Momus 返回通过信号,通常就是字面量的 “OKAY”。这一点非常关键。很多 agent 系统也会在 prompt 里说“请自我检查”,但 OMO 让批评者真正成为一道关卡。只要 Momus 不通过,计划就不能被视为完成。这意味着计划质量不再只是软约束,而是一个带重试闭环的硬约束。

第二层是执行层,核心角色是 Atlas。如果说规划层负责回答“做什么”,那么 Atlas 负责回答“怎么做、谁来做、做到什么程度才算完成”。Atlas 会把计划拆解成可执行单元,识别哪些任务可以并行,把子任务分发给合适的专业 agent,回收结果,做验证,并通过 notepad 机制维护阶段性知识。若用分布式系统的比喻,Atlas 很像调度器加验证器;若用团队组织的比喻,它更像项目经理兼技术负责人。

Atlas 的价值在于弥合“计划”与“落地执行”之间的断层。计划写得好,并不意味着执行一定好。任务是否切得合理,是否分配给正确的人,是否存在并发机会,是否真正验证过结果,这些都不是计划文件本身能自动保证的。Atlas 正是在做这件事:把一张静态计划,变成一个动态执行流程。

第三层是工作者层。这里是实际干活的专业 agent 集合。用户在任务里特别点名的几个角色恰好最能体现 OMO 的设计思想。Sisyphus-Junior 通常绑定 Sonnet 4.5 一类模型,定位是“聚焦执行者”,负责清晰、边界明确的子任务,不承担复杂调度。Oracle 常映射到 GPT-5.2 这类高推理模型,但被严格限定为只读顾问,用于架构评审、调试分析、复杂判断。Librarian 偏外部知识和资料检索,常走 GLM-4.7 路线。Explore 是代码库搜索专员,强调快速 repo 勘探。Hephaestus 则偏向 GPT-5.3 Codex 一类深度工作模型,负责高复杂度、强自主的工程任务。

实际上,OMO 的 roster 不止这些。更完整地看,它包含 Sisyphus、Prometheus、Metis、Momus、Atlas、Oracle、Librarian、Explore、Hephaestus、Multimodal-Looker,以及按 category 生成的 Sisyphus-Junior 变体,整体可以视作一个约 11 个专业角色组成的 agent 体系。这里真正值得注意的不是“数量”,而是角色隔离:规划者负责规划,批评者负责挑错,调度者负责编排,工作者负责执行。

这使得 OMO 与多数单智能体系统有了本质差异。传统系统更像一个“全能型个人”,在同一上下文里交替做需求理解、代码搜索、实现、总结。OMO 则更像一个“有分工的组织”。这样做至少有四个好处。

第一,减少角色冲突。保守的规划行为不必和激进的执行行为挤在同一个 prompt 身份里。第二,支持模型专门化。不同角色可以走不同 fallback chain、不同推理强度。第三,支持并行性。Atlas 可以同时派出多个 worker,而不必把所有步骤塞进一条顺序推理链。第四,增强可归因性。如果任务失败,可以分析是理解错、规划错、执行错,还是验证错。

从方法论上看,这套三层结构其实把经典软件工程中的若干阶段压缩进了 agent runtime:需求澄清、方案评审、执行拆解、实现、QA。也正因为如此,它不是“多几个 agent”这么简单,而是在回答一个更大的问题:复杂编码任务应该如何组织?

OMO 给出的答案是:不要让一个模型扮演所有人,而要让系统像一个组织一样运作。这就是三层编排架构真正的创新性所在。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第10章 — Oh-My-OpenCode的创新
Token用量: 约 4,000 input + 1,050 output

10.2 语义类别系统

OMO 很聪明的一点在于:Category 描述的是任务意图,而不是模型名称。 这件事看似简单,实际上解决了 agent 系统里一个很常见、但经常被忽视的问题——任务语义和后端模型耦合得太死。

在很多系统里,调用方会直接说“这个任务用 GPT-X”“这个任务切到模型 Y”。这种方式短期有效,但长期会带来两个问题:其一,prompt 和工作流里到处塞满具体模型名,导致配置膨胀;其二,任务本质被模型品牌绑架,一旦模型替换、价格变化、可用性波动,整套策略都要重写。OMO 通过 category-resolver.tssubagent-resolver.tscategories.tsmodel-requirements.ts 等文件引入了一个中间抽象层:先说这是什么类型的工作,再由系统决定背后该落到哪个模型和 fallback chain。

具体映射非常有代表性。visual-engineering 会优先走 Gemini 3 Pro 一类视觉/界面能力强的模型;ultrabrain 倾向 GPT-5.3 Codex 高推理档;quick 偏向 Haiku 4.5 或其他低延迟低成本模型;deep 也围绕 GPT-5.3 Codex,但约束更严格;writing 则偏向 K2P5 以及写作友好型备选。也就是说,类别背后其实编码了一套关于任务结构的理解:什么任务更看重速度,什么任务更看重视觉感知,什么任务更看重深度推理,什么任务更看重语言生成质量。

这种设计的直接好处是解耦。用户和上层 agent 说的是“这是视觉工程任务”“这是快修任务”“这是深度工作”,而不是“请使用某某模型”。底层若要换模型、加 fallback、调 variant,调用接口都不用变。从软件设计的角度看,这就是典型的稳定接口包住不稳定实现。

但 OMO 的论点不止于此。它还试图减少一种可以称为模型自我感知偏差的问题。这个词需要稍作解释。很多大模型在 prompt 中会被赋予强角色叙事,比如“你是最擅长创意的模型”“你是最快的搜索模型”。模型有时会根据这种身份叙事改变风格、信心、解释方式,甚至影响错误模式。也就是说,模型不是单纯在执行能力路由,它还在“相信自己被描述成什么”。OMO 试图减少这种依赖。通过 category 解析器和 resolver 代码,它把更多决策放进系统结构,而不是放进模型的自我想象里。

category-resolver.ts 正体现了这一点。它会检查用户自定义 category、默认 category、可用模型集合、硬性要求、override 优先级、prompt append 片段、unstable-agent 标记等。某些 category 甚至可以要求某个模型必须可用,否则直接报错;另一些则会在缺失首选模型时沿 fallback chain 回退。换言之,category 不是装饰性的 tag,而是一组策略打包。

subagent-resolver.ts 则补充了另一个维度:命名 agent 与语义 category 的区分。比如 Oracle、Explore 这种是“谁来做”的问题,而 quick、deep 这种是“这类任务本质上属于什么”的问题。前者是角色路由,后者是工作语义路由。把这两个维度分开,本身就是一个很成熟的设计。

语义类别还有一个很现实的价值:prompt 可移植性更强。高层编排器可以写出很稳定的策略模板,比如:

  • UI 改造一律优先 visual-engineering
  • 小而明确的编辑优先 quick
  • 文档与说明优先 writing
  • 复杂推理型编码优先 ultrabraindeep

这样的模板未来依然有效,即便模型生态已经发生了很大变化。因为真正稳定的是任务语义,而不是模型 SKU。

这套设计比“完全自动黑箱路由”和“完全手动指定模型”都更平衡。完全自动的系统往往太魔法化,用户不容易理解为什么它做了某种选择;完全手动的系统则把太多基础设施细节暴露给用户。OMO 的语义类别系统处在两者中间:既保留了用户可理解、可表达的控制面,又保留了底层模型调度的灵活性。

它还有一个经济学层面的意义。所有任务都默认上最强模型,质量也许高,但成本往往不合理;所有任务都默认上最便宜模型,成本低,但失败率会升高。Category 恰好提供了中间道路:低价值或低复杂度任务走轻模型,高价值高复杂度任务走重模型。这样,模型分配不再是拍脑袋,而更像资源调度。

从长远看,这可能是 OMO 最值得复制的模式之一。真正持久的抽象不是模型名,而是任务意图。模型会不断变,类别描述的工作本质却相对稳定。OMO 把这一点变成了代码层面的 resolver 机制,而不仅仅是文档里的建议。这正是它高明的地方。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第10章 — Oh-My-OpenCode的创新
Token用量: 约 3,900 input + 1,000 output

10.3 Ultrawork模式

在 OMO 的诸多功能里,Ultrawork 模式可能是最鲜明、也最“有态度”的一个。它由关键词触发,常见触发词就是 ultraworkulw,实现位于 hooks/keyword-detector/ultrawork/。一旦触发,系统不再把自己当成普通聊天助手,而是切换到一种更激进、更自主、更强调完工率的工作姿态。

理解 Ultrawork,不能把它看成只是“多插了一段 prompt”。它背后是一套明确的运行哲学:Human intervention = failure signal。也就是“人类频繁介入,本身就是系统失败的信号”。如果用户必须不断提醒 agent:“你先去看代码”“别急着改”“别半成品就停”“你还没验证”,那就说明这个系统离真正自主还很远。Ultrawork 试图把这种不满变成可以执行的工作协议。

它的注入消息极其强硬。系统会要求 agent 在写任何代码之前,先充分理解需求、勘探代码库、解决歧义、形成清晰计划;会强制它优先调用 Explore、Librarian、Oracle、Plan agent 等专业角色;会明确把“简化版本”“以后你可以再扩展”“我做了一些假设”之类的输出视为不可接受。换句话说,Ultrawork 的重点不是“更快”,而是不允许以礼貌措辞掩盖未完成工作

所以关键词触发的意义很大。它等于给用户一个显式开关:当用户输入 ultrawork 时,双方默认进入一种更高自主度的契约。这个契约大致包含五个阶段。

第一,先探索再动手。不要看到第一个疑似相关文件就直接改,而要先摸清架构、约定、边界条件和相邻实现。第二,需要外部知识时先研究最佳实践。第三,端到端实现,而不是只给骨架。第四,验证,包括构建、测试、行为证据。第五,若失败则持续迭代,而不是输出一段看似体面的总结。

这五个环节——探索、研究、实现、验证、继续——构成了 Ultrawork 的真实工作回路。

它之所以重要,是因为它击中了许多 coding agent 的一个隐性弱点:太“会说话”,但不够“会干活”。很多 agent 在对话层面表现得很友好,会解释、会总结、会道歉,但一到执行层面就容易停在 70% 到 80% 的位置。Ultrawork 模式就是在逆着这个倾向设计。用更标准的系统术语说,它在强化一种**活性(liveness)**期望。所谓活性,指的是系统应该持续朝完成状态推进,而不是长时间停在未完成但口头上像完成的状态。

OMO 的做法不是单靠一句“请继续直到完成”。它把 Ultrawork 与 planner、delegate-task、continuation hooks 结合起来。也就是说,Ultrawork 并不是单点功能,而是整个编排系统中的高自主姿态入口。关键词只是触发器,真正让它站得住的,是下游的 Plan agent、Atlas、Ralph Loop、Todo Continuation 等机制。

另外值得注意的是,Ultrawork 不是“一刀切”地对所有 agent 注入同样内容。不同模型、不同 agent 身份可能会走不同版本的 ultrawork message;planner 家族甚至可能被特殊处理。这说明 OMO 知道一件事:自主性不是均匀撒到整个系统里的,它应当按角色做适配。规划者需要的是更严谨的思考约束,执行者需要的是更强的落地压力,搜索者则需要的是并行调研优先。

它还改变了上下文使用方式。传统做法是让主 agent 把所有探索、检索、实现都塞进主对话里,结果就是主上下文越来越脏。Ultrawork 则鼓励通过 Explore 和 Librarian 等后台子 agent 并行收集信息,再让主线程基于结构化结果继续工作。这等于把高自主度变成“编排能力”,而不是“主线程无限啰嗦”。

从用户体验上说,Ultrawork 代表一种相当鲜明的立场:减少不必要的人类确认,降低打断频率,把更多执行负担留给系统。保守系统往往频繁要求确认,因为那样更安全;OMO 则认为,在很多工程任务里,这种高频确认并不是真正好的体验,因为它把工作又推回给了用户。

当然,这种模式也有成本。更高自主度通常意味着更高 token 消耗、更长运行时间,以及在需求理解错误时更大的偏航风险。OMO 的回应不是否认这些代价,而是通过规划、批评、验证和 continuation 机制去托底。

因此,Ultrawork 的价值不在于它有一个酷炫名字,而在于它把一句口号变成了可运行的模式:编码 agent 不应该像聊天机器人那样在“看起来有帮助”时停下,而应该像真正的执行者那样,以完成任务为目标持续推进。这一点,正是 OMO 相比普通 agent 最鲜明的态度差异之一。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第10章 — Oh-My-OpenCode的创新
Token用量: 约 4,100 input + 1,080 output

10.4 Ralph Loop与Todo Continuation

自主执行最难的一点,不是“开始做”,而是“别太早停”。OMO 为了解决这个问题,设计了两套互补机制:hooks/ralph-loop/ 下的 Ralph Loop,以及 hooks/todo-continuation-enforcer/ 下的 Todo Continuation Enforcer。它们共同对准的是 coding agent 最常见的失败之一:任务没做完,但输出已经像做完了一样。

先看 Ralph Loop。它的思想非常直接:如果 agent 没有真正完成任务,系统就不应该接受那次停机,而应该把它推回工作状态。continuation-prompt-builder.ts 里写得很清楚:如果上一次尝试没有输出 completion promise,系统就构造 continuation prompt,要求它回顾进度、从中断点继续、直到真正完成才允许停下。在 ultrawork 模式下,这个 continuation prompt 前面还会自动补上 ultrawork,也就是把“高自主执行姿态”沿着重试链一路传下去。

为什么 OMO 喜欢用 Sisyphus 和“推石头(boulder pushing)”这种比喻?这里需要稍作解释,因为它不是标准 CS 术语。西西弗斯是希腊神话中的人物,被惩罚永远把巨石推上山,石头却不断滚落。OMO 借用了这个意象,用来形容一种设计理念:只要任务没有完成,系统就必须继续把“石头”往上推,不能因为中断、压缩、超时或一次失败就当作结束。把它翻译成更标准的系统语言,就是:一个带持久重试语义的强制续跑机制

而 Todo Continuation Enforcer 则从另一个角度解决同一个问题。它不主要盯 completion promise,而是盯任务状态。如果 todo 还没全部完成,那么 session 就不应被当作正常结束。相关 handler 会监听诸如 session.idlesession.errorsession.deleted 等事件。一旦 session 进入 idle,系统就可以检查是否仍有未完成 todo;如果有,就触发续跑逻辑。

这意味着 OMO 里的 todo 不是 UI 装饰,而是工作协议。很多系统也能生成 todo list,但 todo 往往只是“看起来更有条理”,并不会真正约束 agent 行为。OMO 则试图堵上这个漏洞:只要 todo 还挂着 pending 或 in_progress,就不允许 agent 靠一段漂亮总结溜出流程。换句话说,todo 在 OMO 里是运行时条件,而不是文学排版。

这两套机制配合得很好:

  • Ralph Loop 负责检查“是否发出了明确完成信号”;
  • Todo Continuation 负责检查“从状态上看是否真的已经做完”。

前者是输出导向,后者是状态导向。两个视角同时存在,大幅压缩了 agent 逃逸的空间。

这背后也反映出一个更大的设计判断:单靠 prompt 约束是不够的。 模型可以忘记、忽略、被压缩打断,也可以在语气上制造完成幻觉。OMO 因此把“继续干活”从 soft norm 提升为 runtime control flow。也就是说,它不只是告诉模型“你应该继续”,而是通过 hook 和 event handler 真正让系统在必要时继续。

系统提醒注入也很关键。OMO 会在未完成时插入 system reminder,告诉 agent 还有哪些事情没做、为什么不能停。这类似传统系统中的 watchdog 或 supervisor:一个组件持续监视另一个组件是否达到目标状态,如果没有,就干预其行为。

它还有恢复层面的价值。长任务中断之后,最糟糕的情况不是“暂时停了”,而是恢复时忘了为什么停、忘了还差哪一步,结果输出一段泛泛而谈的收尾。OMO 借助 Ralph Loop 状态和 continuation state,让任务在中断后仍能重新回到未完成点,而不是变成“重新开一题”。

当然,这种激进续跑也有代价。它可能增加运行时长、token 成本,甚至偶尔出现“其实该停了,但系统还想继续”的情况。因此 OMO 还配了 stop-continuation-guard 和显式 stop 命令,给用户留出终止权。但默认倾向非常明确:宁可多续一次,也不要过早停止。

这个倾向其实相当合理。现实中用户抱怨 coding agent,更多是因为它半途而废,而不是因为它略微过于执着。OMO 正是围绕这个主失败模式优化。

从更高层看,Ralph Loop 和 Todo Continuation 共同表达了一种 agent discipline 理念:完成状态不能靠语气、置信度或总结腔判断,必须靠显式信号和状态检查判断。人类很容易被流畅语言骗过去,但一个可靠的编排系统不应该被语言骗过去。

因此,这两个 hook 的意义远大于“续跑补丁”。它们本质上是在把“直到完成才停”变成一种架构性质,而不只是励志口号。这正是 OMO 比普通 prompt-heavy 系统更进一步的地方。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第10章 — Oh-My-OpenCode的创新
Token用量: 约 4,000 input + 1,050 output

10.5 智慧积累系统

OMO 一个非常深、也非常容易被低估的创新,是围绕 .sisyphus/notepads/ 建立起来的智慧积累系统。表面上看,这像是在任务过程中记笔记;但从架构上看,它是在回答一个更本质的问题:多智能体系统里,一个子任务学到的东西,如何变成后续子任务真正可复用的知识,而不是仅仅淹没在原始 transcript 里?

相关机制分散在 prompt、hook 和 Atlas 提示中。系统会要求 agent 把执行中的发现追加到若干结构化 notepad 文件中,例如:

  • learnings.md
  • decisions.md
  • issues.md
  • verification.md
  • problems.md

不同模块强调的清单略有差异,但思想是一致的:执行不只产生代码变更,也产生可积累的判断与经验

这里最关键的概念区分是:transcript 不是 knowledge。对话记录只是原始时间序列记忆,里面有重复讨论、无效分支、表达噪音和历史包袱。notepad 则是蒸馏后的操作性知识:项目约定是什么、做了什么架构决定、踩到了哪些坑、验证了哪些事实、还有哪些问题没有解决。用更标准的 CS 语言说,这是一层派生记忆(derived memory)。它把高熵的对话上下文压缩为低熵、可复用的结构化资产。

Atlas 是这套系统最关键的消费者和分发者。它的 prompt 明确要求在 delegation 之前先读 notepad;verification reminders 也会要求它在回收子 agent 结果后去看 notepad 文件。整个逻辑非常优雅:每个已完成子任务都应该留下“知识残留物”,而后续子任务开始前都应该先消费这些残留物。

这样做至少有几个明显收益。

第一,减少重复踩坑。如果某个 agent 已经发现了本地命名约定、隐藏依赖、工具链特殊规则、常见失败点,后续 agent 不需要再付一次探索成本。第二,提高一致性。已经写入 decisions.md 的架构选择,可以约束后面多个任务的行为。第三,帮助验证。如果某个 worker 已经跑过哪些检查、发现了哪些风险,Atlas 可以更清楚地判断哪些问题已经闭环,哪些仍是未知数。

第四,也是更根本的一点,它把系统从“一个个孤立回合”变成“一个持续累积的工作流”。系统不再只是按顺序回答一串 prompt,而是在构建一个任务级、项目级的局部知识库。

这与 Claude Code 的上下文隔离倾向形成鲜明对比。Claude Code 在会话恢复和 transcript 持久化方面很强,但它整体上更偏向 transcript/replay 型连续性,而不是通过显式 notepad 把知识抽取出来,再系统性地传给后续子 agent。OMO 的立场更激进:每次任务之后,都要把经验提炼出来,并传递给所有后续 subagent。

这背后其实是两种不同哲学。一种认为:每个 subagent 尽量靠本地上下文独立工作,减少耦合。另一种认为:真正有价值的发现必须传播。OMO 选择了后者。

当然,传播知识也意味着传播错误。如果某个错误判断被写进了 decisions.md,后面的 agent 可能会在高置信度下继承它。所以 notepad 质量非常重要,Atlas 和验证步骤最好充当过滤器,而不是盲目信任所有笔记内容。也正因此,智慧积累系统最好与强验证机制一起工作,而不是单独存在。

即便如此,这个设计仍然非常有力量。多智能体系统的一个经典问题可以叫做委派导致的上下文失忆:每个 subagent 都从零开始,很聪明,但对当前项目的特殊性并不了解。OMO 的 notepad 正是在对抗这种失忆。它创建的是局部、任务相关、项目相关、可持续的工作记忆,而不依赖某个单次上下文窗口完整保留一切细节。

更有意思的是,这种方案并不依赖复杂的向量数据库、embedding 检索或大型记忆基础设施。很多时候,简单的纯文本结构文件反而更好:可读、可查、可审计、可手工修正、对开发者透明。它们既是机器可消费的上下文资产,也是人类可检查的知识载体。这提升了信任和可调试性。

所以,OMO 的智慧积累系统真正创新的,不是目录名,不是文件名,而是一个很重要的判断:自主执行留下的成果,不应只有改动后的代码,还应包括执行过程中形成的经验和判断。 编码工作从来不只是改文件,它也包括理解、决策、踩坑和验证。OMO 把这些内容也纳入了“产物”的范围。

对未来 coding agent 而言,这可能是一条非常值得借鉴的路线。多智能体真正变得有用,并不只靠分工本身,还靠每次分工之后能否把智慧留存下来,继续喂给下一轮分工。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第10章 — Oh-My-OpenCode的创新
Token用量: 约 4,300 input + 1,120 output

10.6 41钩子5层体系

OMO 的 hook 系统,是它“为什么不像一个普通插件,而像一个运行时中层系统”的最好证明之一。内部上,OMO 把 41 个 hooks 组织成 5 个层级

  1. Session:19 个
  2. Tool-Guard:9 个
  3. Transform:4 个
  4. Continuation:7 个
  5. Skill:2 个

这些分组可以直接从 create-session-hooks.tscreate-tool-guard-hooks.tscreate-transform-hooks.tscreate-continuation-hooks.tscreate-skill-hooks.ts 中读出来。

为什么这件事重要?因为 OMO 已经不只是“多注册一些工具”“多拼一些 prompt”了,而是在 agent 生命周期的多个阶段写入行为控制。所谓 hook,本质上就是一个拦截点:在某个事件、某个阶段、某类输入输出经过时,系统可以插入额外逻辑。OMO 正是靠这些拦截点,把行为、质量、安全、续跑、技能提醒、上下文变形都变成了可编程策略。

这里有一个非标准术语需要解释:multiplex(复用复接)。在通信和系统领域,multiplex 指的是“多个逻辑通道共用较少的物理通道”。OMO 做的事情与此很像。OpenCode 作为宿主,只暴露了有限的 plugin hook points;但 OMO 却把几十种逻辑行为通过这少数入口复接进去。也就是说,宿主入口不多,但 OMO 在每个入口背后挂了很多逻辑子层。这就是“41 个 hooks 复接到 OpenCode 的 5 个 hook points”这句话真正的含义。

先看 Session 层。它主要处理会话级生命周期与运行状态,例如 context-window monitor、session recovery、think mode、Ralph Loop、delegate-task retry、start-work、notepad 注入、preemptive compaction 等。这一层控制的是 session 的节奏、恢复、推理姿态和长期运行状态。

再看 Tool-Guard 层。这一层守在工具边界上。因为工具边界是 LLM 意图真正接触外部世界的地方,所以这里特别重要。comment-checker、rules-injector、write-existing-file-guard、hashline-read-enhancer、tasks-todowrite-disabler 等都在这一层。它们有的负责防止 AI 风格注释污染代码,有的负责把项目规则自动带入上下文,有的负责限制危险文件写操作,有的则是在工具结果级别做增强与约束。

Transform 层处理的是消息变换,尤其是在模型真正看到消息之前。典型成员包括 keyword-detector、context injection、Claude Code hooks 兼容层、thinking-block validator。这个层级非常强,因为它意味着 OMO 可以在不修改宿主核心的前提下,改变模型的有效输入上下文。

Continuation 层则是 OMO “干活不准半途而废”理念的集中体现。stop-continuation-guard、compaction-context-injector、compaction-todo-preserver、todo-continuation-enforcer、unstable-agent-babysitter、background-notification、atlas hook 都在这里。这个层级直接决定了 OMO 为什么比普通 agent 更像“带监督的执行系统”。

最后是 Skill 层。数量不多,但非常战略化。category-skill-reminder 和 auto-slash-command 让 skill 不再只是静态文档,而是在运行时参与提示、指导和命令触发。

如果看具体 hook,几个例子特别能体现 OMO 的成熟度。

comment-checker 很有意思。它专门防止低价值、AI 味很重的注释污染代码。很多系统默认把注释看成无害输出,但 OMO 认为这其实是质量问题,值得系统性拦截。这个判断很细,但很对。

rules-injector 让仓库级规则自动进入工作上下文。这意味着 agent 更可能遵守本地规范,而不是每次都要用户手工再解释一次。

think-mode 则处理推理强度和 token 预算。它提醒我们:agent 的质量并不只取决于用了哪个模型,也取决于系统在什么时候分配了多少思考预算。某种意义上,think-mode 是在管理“思考成本”。

另一个关键点是:hooks 都可以通过配置启用或停用。如果一个 41-hook 系统不能配置,那几乎一定会失控。OMO 在这一点上是清醒的。它把 hook 体系做成了一个可裁剪的策略图,而不是刚性开关全开。

更高层地看,这套系统说明了一个重要趋势:未来 agent 架构的竞争点,不只在模型,更在生命周期控制面。一旦宿主平台给出了足够强的 hook surface,插件就可以长成一整套 policy engine。它能控制质量、安全、上下文、续跑、技能提醒、消息变形,而这些都远远超出“改改 prompt”所能达到的效果。

也正因此,OMO 看起来越来越像一个操作层,而不是薄扩展。41-hook 体系其实就是它的神经系统:它在监视、拦截、提醒、重试、保护、注入和保留状态。没有这套体系,OMO 仍会有一些有趣 agent;有了它,OMO 才真正成为一个编排运行时。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第10章 — Oh-My-OpenCode的创新
Token用量: 约 3,900 input + 1,020 output

10.7 技能嵌入式MCP

OMO 在扩展性上的一个很有代表性的创新,是技能嵌入式 MCP。相关实现主要位于 src/features/skill-mcp-manager/,并通过 skill_mcp 等工具对外暴露。它的核心思想是:一个 skill 不只是提示词知识包,还可以把自己需要的 MCP 服务一起带过来。

要理解这一点的重要性,先要回顾 MCP 的角色。MCP(Model Context Protocol)本质上是让 agent 以统一协议访问外部工具、资源和 prompt 的方式。通常情况下,MCP server 是全局配置的,或者项目级配置的;而 skill 则只是 instructions、文档和 workflow 提示。OMO 把这两者打通了:skill 可以内嵌自己的 MCP server 定义。

这意味着,一个技能不仅能“告诉 agent 怎么做”,还可以“携带 agent 做这件事所需的外部能力”。

OMO 的 MCP 结构可以看成三层。

第一层是 OMO 自带的 built-in MCPs,例如 Context7、websearch/exa、grep.app 这类远程服务。第二层是 Claude Code 兼容层,它能从 .mcp.json 之类的配置导入 MCP 定义。第三层就是最有特色的一层:skill-embedded MCPs。正是这一层,让 OMO 在扩展体系上明显区别于一般系统。

SkillMcpManager 展示了这套系统的核心职责。它负责连接池、pending connection 跟踪、重连与重试、step-up auth、空闲清理,以及按 session/skill/server 维度管理 client 身份。它同时支持 stdioHTTP 两种传输。

这里的 stdio 也需要解释一下,因为这不是所有读者都熟悉的标准教材术语。stdio 指 standard input / standard output,也就是通过本地进程的输入输出流进行通信。HTTP 则是通过网络服务通信。OMO 让 skill 内嵌的 MCP server 同时支持这两种模式,意味着 skill 既可以带一个本地工具进程,也可以带一个远程服务接口。

这不是一个小便利功能,而是在解决一个打包问题。假设有一个 skill 教 agent 完成某类工作。在弱系统里,用户还得另外安装配置配套工具,再自己保证 prompt 和工具接口对得上。OMO 则允许 skill 把这部分 MCP 声明直接打包带上,从而减少“文档写得很好,但能力没接上”的错位。

换句话说,skill 在 OMO 里不再只是知识片段,而更像一个可执行知识包

这直接带来可移植性提升。团队共享一个 skill 时,不仅共享它的做事说明,也共享它的能力面。这个方向很像现代软件工程里的依赖打包,而不再只是“分享一段 prompt”。它让扩展从静态文案进化成半可执行组件。

从实现上看,SkillMcpManager 也不是浅尝辄止。它用 sessionID、skillName、serverName 组合出 client key;在操作层提供 listTools、listResources、listPrompts、callTool、readResource、getPrompt 等方法;遇到 not connected 之类问题时会主动 forceReconnect;还有 step-up auth 处理。这说明 OMO 并不是把 MCP 配置随便塞进 skill 文件里,而是真的建立了一套足够稳定的生命周期管理能力。

更深一层地说,这体现了 OMO 对扩展形态的理解:扩展不该只是“平台全局安装能力”,也可以是“内容自身携带能力”。也就是说,能力不一定都挂在平台层级,也可以随着具体技能走。这种思路和现代软件世界中“代码、配置、元数据一起交付”的趋势非常一致。

相比 Claude Code 和普通 OpenCode 配置,这一点尤其特别。它们当然也支持 MCP,各自也有 MCP 配置机制;但把 MCP 与可重用 skill 深度绑定,让 skill 成为“说明 + 能力”的统一包,OMO 走得更远。

这套设计当然也会带来复杂度和安全面的问题。如果 skill 可以带可执行能力,那么 skill 的加载、审核、清理,就都变得更敏感。这意味着系统更强大,也意味着供应链风险更高。所以 skill-embedded MCP 的威力,与安全治理必须是同时增长的。

即便如此,这条路线仍然非常值得重视。Skill 若只能“说”,价值有限;MCP 若没有上下文说明,也难用。OMO 的技能嵌入式 MCP 正是在把这两者合并:让技能不只是知识,也带着工具;让工具不只是接口,也带着用法。

对未来 coding agent 而言,这很可能会成为一个重要模式:把 skill 从静态 prompt 文件,升级为包含 instructions、约定和能力面的“能力胶囊”。而 OMO,正是较早把这个方向真正做进系统里的项目之一。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第10章 — Oh-My-OpenCode的创新
Token用量: 约 4,000 input + 1,050 output

10.8 Tmux可视化多智能体

多数多智能体系统有一个共同问题:它们虽然号称“后台并行跑了很多 agent”,但对用户来说仍然像黑箱。你只能看到一个终端、一个 transcript、一条汇总输出,看不见中间到底发生了什么。OMO 在 features/tmux-subagent/ 中做的事情,就是把这种黑箱状态部分打破:让后台子 agent 出现在独立的 tmux pane 里,被实时观察。

这件事的意义,比“终端分屏挺酷”要大得多。一个黑箱系统要求用户在不可观察的前提下交出信任;而 OMO 的 tmux 可视化,则把多智能体编排变成了一个用户可以亲眼观看的过程。

这套功能背后并不只是简单调用一下 tmux split-window。相关代码包括 session-created-handler.tsspawn-action-decider.tsaction-executor.tspolling-manager.ts 等,实际上构成了一个 pane 生命周期管理器。大致过程是:当后台 subagent session 创建后,系统检查是否启用 tmux、是否处于 tmux 环境;查询当前窗口状态;判断是否有足够空间再分 pane,还是应该替换最老 pane;执行 spawn、replace 或 close;等待 session ready;随后轮询 session 状态,并在完成或消失后清理 pane。

也就是说,它至少在做以下几类真正的系统工作:

  • 维护 session 与 pane 的映射关系;
  • 维持主 pane 的尺寸与优先级;
  • 判断窗口容量与是否还能继续分屏;
  • 必要时替换最旧 agent pane,避免布局无限膨胀;
  • 在任务完成后自动回收 pane。

这更像一个可视化调度器,而不是一个装饰性终端小功能。

这个设计最直接带来的收益,是可观察性(observability)。在系统工程里,可观察性指的是:通过外部可见的信号与行为,理解内部状态与过程。OMO 的 tmux 模式把多智能体执行过程直接暴露出来,因此大幅提升了这一点。用户不仅知道“有几个 agent 在跑”,还可以看到它们何时启动、在做什么、是否卡住、何时结束。

这带来几个实际好处。

第一,提升信任。如果系统声称同时派出了三个 Explore 和一个 Librarian,用户真的能看到它们在并行工作。第二,提升调试性。如果某个 pane 明显卡住、频繁报错、或者走错方向,这比最终只看一段汇总容易发现得多。第三,帮助用户形成关于“并发”和“成本”的直觉。多智能体不再只是营销词,而是终端里活生生的工作现场。

它还有一个文化层面的作用。很多 agent 产品喜欢把自主性包装成魔法:用户只看结果,不看过程。OMO 的 tmux 视图恰恰相反,它让自主性看起来像一种真实劳动。你会看到 pane 被拉起、命令在跑、日志在动、session 在轮询。这种体验更健康,因为它鼓励用户把 agent 看成一个编排流程,而不是一个神秘黑盒。

这也进一步强化了 OMO 的核心主张:未来的 coding agent 不是一个模型一个声音,而是一组被协调的工作者。tmux 只是把这个事实可视化了出来,而不是把它藏在最终回复之后。

从 UX 角度看,这个方案也很聪明,因为它利用的是开发者已经熟悉的基础设施。tmux 是终端开发者非常自然的工作环境,尤其在类 Unix 世界里更是如此。OMO 并没有急着造一个全新 GUI 仪表盘,而是借用了开发者原生理解的界面媒介。这降低了学习成本。

当然,它也有边界。tmux 可视化最适合终端型工作流,对非终端用户吸引力有限;同时它也增加了 session 管理、pane 清理、布局决策等复杂性。但作为一次设计探索,它非常有价值。

它其实暗示了一个更大的方向:如果多智能体编排会成为常态,那么用户迟早需要一套观察它的方式。今天这套方式可以是 tmux panes;明天也许会是 timeline、dependency graph、任务看板、实时 dashboard。OMO 的实现,是这种趋势的一个非常具体、非常落地的早期例子。

因此,Tmux 可视化多智能体并不只是一个“体验加分项”。它本质上是在强调一种透明性立场:如果系统声称有很多 agent 在为你并行工作,那么它最好愿意把这些工作展示出来。对于一个经常把最关键 runtime 过程藏在聊天气泡之后的行业来说,这一步是很有意义的。

Book: Claude Code VS OpenCode: Architecture, Design and The Road Ahead 章节: 第11章 — Claude Code的商业设计 Model: openai/gpt-5.4 Generated: 2026-04-01 Token Usage: 当前API环境不可见

11.1 安全架构

Claude Code 的安全设计,最值得注意的地方,不是“它会弹权限框”,而是它把安全做成了一条分层流水线。核心实现集中在 src/utils/permissions/permissionSetup.ts,配套还有 yoloClassifier.tsbashClassifier.tsdangerousPatterns.ts。换句话说,它不是把安全当成某一个确认按钮,而是把安全嵌入了代理执行的整个控制面。

第一层是四种权限模式:default、auto、bypass、plan。default 是传统模式,危险操作仍然要显式确认。auto 模式更激进,它试图自动批准低风险操作,但前提是先通过分类器。bypass 模式则是高信任、高自由度模式,主要面向知道自己在做什么的高级用户。plan 模式恰好相反,它强调先规划、少执行,把代理限制在“思考与分解任务”阶段。商业上,这种四段式设计很重要,因为它把“安全”和“效率”做成了连续光谱,而不是二选一。

其中最关键的机制,是所谓的 ML YOLO classifier。这里的 YOLO 不是“放飞自我”,而是一个模型驱动的自动批准层,用来判断某个待执行动作是否足够安全,是否可以不打断用户直接执行。yoloClassifier.ts 会构建分类提示词、记录分类转录、估算 token,并输出是否应该拦截。实质上,Claude Code 用一个模型判断系统去监督另一个模型代理的行为。这是非常典型的商业工程思路:不是完全信任主模型,而是在关键动作前再套一层可控的“二次裁决”。官方材料中常提到它配合沙箱后可带来 84% 的权限提示减少,这恰好说明其目标:在不放弃控制的前提下,把打断感降到最低。

第二层是 Bash 命令分类器。它不是只看命令长什么样,而是看命令“想做什么”。这就是所谓的语义分析。比如 ls srcpython -c "..." 都是 shell 命令,但风险完全不同。Claude Code 并不满足于简单的字符串匹配,而是试图理解命令的行为语义、参数结构和执行意图。这比传统 allowlist 更接近人工安全审查的思维方式。

第三层是 危险模式检测dangerousPatterns.tspermissionSetup.ts 会识别那些会把自动模式安全边界直接打穿的规则。典型例子包括脚本解释器:pythonnoderubyperlphplua;shell 包装器:bashshzsh;以及包运行器:npxbunxnpm run。此外,像 python:*node** 这类通配规则也会被视为危险。原因很直接:一旦代理可以自由调用解释器,它就等于获得了近乎无限的新行为生成空间;而一旦规则是裸通配符,分类器就会被绕过去。Claude Code 甚至把这个逻辑扩展到了 PowerShell 和子代理创建,因为“无限委派”本身也可能成为安全逃逸通道。

第四层是 操作系统级沙箱。Claude Code 不只依赖提示词和分类器,它还把限制下沉到 OS 边界:Linux 上用 Bubblewrap,macOS 上用 Seatbelt。Bubblewrap 是 Linux 常见的进程级沙箱机制;Seatbelt 是 Apple 的策略型沙箱框架。二者的意义在于:即使上层模型判断失误,底层系统仍然可以约束文件访问、进程能力或网络行为。这就是典型的纵深防御:模型层先拦一遍,操作系统层再兜底一遍。

从商业设计角度看,这套体系真正有价值的地方,不只是“更安全”,而是让 高自治代理可以被卖出去。企业真正购买的不是自治本身,而是“有边界的自治”。Claude Code 的权限模式、语义命令分析、危险规则剔除、以及 OS 级隔离,正是对这种需求的工程回答。OpenCode 与 Oh-My-OpenCode 更强调开放控制面与可插拔能力;Claude Code 则更强调把安全做成内建产品能力。

因此,本节最重要的结论是:优秀的代理安全架构,不是最严格也不是最宽松,而是能够把低风险操作变成无感流程,把高风险或模糊操作升级为显式控制点。Claude Code 在这一点上给出了一个很成熟的商业答案。

Book: Claude Code VS OpenCode: Architecture, Design and The Road Ahead 章节: 第11章 — Claude Code的商业设计 Model: openai/gpt-5.4 Generated: 2026-04-01 Token Usage: 当前API环境不可见

11.2 成本控制

Claude Code 很“商业化”的一个特征,是它没有把成本留在后台账单里,而是把成本做成了产品内的一等公民。核心实现位于 src/cost-tracker.ts,配套有 src/costHook.ts/cost 命令,以及 QueryEngine.ts 中的预算检查。对于企业用户来说,这一点极其关键,因为 AI 编码代理不仅要好用,还要可控、可结算、可约束。

其中心能力是 按会话追踪美元成本。Claude Code 记录的不只是输入 token 与输出 token 总数,它还记录按模型分解的 usage、API 耗时、墙钟时间、增删代码行数、缓存创建 token、缓存读取 token,以及 web search 请求次数。cost-tracker.ts 会将不同模型的 usage 累加、规范化模型名称,并最终输出总费用与分模型费用。这说明 Claude Code 不是把 token 当成抽象资源,而是当成了财务事件。

更进一步,它显式区分了 cache creationcache read。这是一个非常成熟的设计,因为现代模型 API 往往会对新写入缓存的 token 与命中缓存的 token 使用不同计价。Claude Code 把两者单独记账,意味着系统可以区分“新上下文有多贵”和“重用上下文节省了多少”。很多代理会做缓存,但不会把节省效果透明呈现出来;Claude Code 则把缓存直接变成可审计的效率杠杆。

会话生命周期也被考虑进去了。cost-tracker.ts 支持在恢复会话时还原成本状态,并在退出时保存当前会话的累计成本。costHook.ts 则在进程退出时触发摘要输出与持久化。这说明成本统计并不依赖一次不间断的 CLI 运行,而是可以跨恢复、跨继续。这对于长会话、远程会话、协作会话都很重要。

Claude Code 还提供了硬性的 session budget,即 maxBudgetUsd。在 QueryEngine.ts 中,每轮消息流转后都会检查当前总成本是否已达到预算上限;一旦达到,就直接返回 error_max_budget_usd,并终止本轮执行。这不是提醒用户“你花得有点多了”,而是真正的超支阻断。换言之,它把成本从“可观察指标”提升成了“可执行策略”。

与此配套的是 /cost 命令。这个命令的价值不在于它能显示一串数字,而在于它把成本信息拉回到工作现场。开发者无需切到控制台或云账单页面,就能在当前代理会话中看到总费用、时长、模型分布以及缓存使用情况。这样一来,模型切换、上下文压缩、是否继续会话,都可以在成本感知下实时决策。

从企业视角看,这套设计天然支持 chargeback(内部费用分摊)。所谓 chargeback,就是把 AI 费用归因到正确的团队、仓库、项目或部门,以便内部核算。Claude Code 虽然未必在 CLI 内直接实现完整的财务分账系统,但它已经收集了分摊所需的关键数据:会话身份、模型维度、时间维度、成本维度、工作产出维度。换句话说,它已经为企业级计费治理准备好了底层遥测基础。

这也解释了为什么 Claude Code 的“上下文压缩”“模型选择”“会话继续”这些机制,看起来都带有明显的商业取向。因为在这里,token 不只是技术资源,还是成本资源;上下文不只是推理材料,还是财务负担。OpenCode 与 Oh-My-OpenCode 当然也能外接成本统计,但 Claude Code 把成本纳入了核心架构本身。

本节的结论是:严肃的代理系统,不能只有推理架构,还必须有财务架构。只要代理能长时间运行、频繁调工具、并行做任务,token 消耗就不再是后台细节,而会变成产品设计本身的一部分。Claude Code 的会话级美元跟踪、缓存感知计费、预算上限与 /cost 命令,正是这种商业成熟度的体现。

Book: Claude Code VS OpenCode: Architecture, Design and The Road Ahead 章节: 第11章 — Claude Code的商业设计 Model: openai/gpt-5.4 Generated: 2026-04-01 Token Usage: 当前API环境不可见

11.3 企业就绪特性

Claude Code 与许多开源编码代理最大的区别之一,在于它不是只为个人开发者设计,而是明显为组织级部署准备了管理平面。remoteManagedSettingspolicyLimitsteamMemorySync、GrowthBook 特性门控,以及 Anthropic 后端认证,共同构成了这套企业能力的骨架。

第一项核心能力是 远程托管设置同步。在 src/services/remoteManagedSettings/index.ts 中,Claude Code 可以从远端拉取组织下发的设置,进行校验、缓存、重试和轮询更新。代码里还强调了 fail-open:如果远程设置服务出问题,CLI 仍然继续运行,不会因为控制平面故障导致开发工作中断。这是很典型的企业软件思维:集中治理很重要,但可用性同样不能牺牲。

第二项能力是 团队记忆共享src/services/teamMemorySync/index.ts 会把 repo 级别的记忆文件在本地与服务端之间同步,使得同一组织成员可以共享项目经验、约定、上下文和历史知识。这意味着 Claude Code 并不把 memory 理解为某个用户本地目录中的私有文本,而是在向“团队知识资产”演进。对于企业来说,这比单用户记忆更有价值,因为它会把个人经验逐渐沉淀为组织经验。

第三项能力是 策略限制(policy limits)src/services/policyLimits/index.ts 会从 API 拉取组织级限制,并据此禁用某些 CLI 功能。代码注释中明确提到了远程会话这类能力的开关。更广义地说,这个层可以承载对远程控制、MCP 服务器、插件能力范围等功能的约束。企业真正需要的不是“用户可以做一切”,而是“管理员可以规定什么能做、什么不能做”。

这也自然延伸到了 受管插件列表 与插件白名单。Claude Code 的插件机制不是完全放开的市场系统,而是明显考虑了受控安装、托管市场与刷新路径。对企业而言,可扩展性必须伴随供应链控制;否则插件生态本身就会成为风险入口。因此,managed plugin list 的价值不只是方便管理,而是把扩展面收束到组织认可的边界内。

另外一个关键点是 GrowthBook 特性门控src/services/analytics/growthbook.ts 支持运行期的 feature gate、定向投放、刷新监听、远程评估与曝光日志。这里有必要解释一下 A/B testing:它是产品实验方法,指把用户随机分到不同版本 A 与 B 中,然后比较两组在某项指标上的差异,比如留存、成功率、延迟或故障率。对企业软件来说,A/B 测试不只是增长工具,更是安全发布机制。Claude Code 可以先在内部放量,再对特定组织灰度,再逐步全面上线新功能。

最后是 Anthropic 后端认证。无论是远程托管设置、团队记忆同步,还是策略限制,本质上都依赖统一身份与权限信息。Claude Code 同时支持 API key 和 OAuth 类认证路径,从而让后端知道:当前用户属于哪个组织、什么订阅级别、该享有哪些能力、该被施加哪些限制。与很多开源系统把身份问题留给外部基础设施不同,Claude Code 将身份与产品能力直接耦合在一起。

从商业角度看,这些能力共同回答了企业最关心的问题:这个 AI 代理能否被集中部署、统一治理、持续更新、限制能力边界,并在多人团队中形成共享上下文?远程设置解决部署与配置一致性;团队记忆解决组织级知识沉淀;策略限制解决治理;受管插件解决供应链;GrowthBook 解决灰度与实验;统一认证解决身份与授权。

与 OpenCode 和 Oh-My-OpenCode 相比,Claude Code 在开放性上未必更强,但在 可运营、可治理、可大规模分发 方面明显更成熟。这正是“企业就绪”四个字背后的真正含义:不是功能更多,而是管理能力更完整。

Book: Claude Code VS OpenCode: Architecture, Design and The Road Ahead 章节: 第11章 — Claude Code的商业设计 Model: openai/gpt-5.4 Generated: 2026-04-01 Token Usage: 当前API环境不可见

11.4 自定义Ink实现

Claude Code 的终端界面并不是给模型输出“包一层壳”那么简单。它在 src/ink/ 下维护了一套相当庞大的自定义终端渲染系统。这里可概括为一个 52 文件级别的终端 React renderer,以及更大范围内上百个组件目录。真正值得讨论的,不是精确数量,而是它体现出的产品态度:Claude Code 把终端当成正式应用界面,而不是降级交互层。

其中最核心的是 src/ink/reconciler.ts 里的 React reconciler。这里需要解释一下这个非标准术语。React reconciler 可以理解为 React 的“渲染协调器”,负责把组件树的变化翻译成具体渲染目标上的更新。在浏览器里,这个目标是 DOM;而在 Claude Code 里,这个目标是终端专用的节点树、布局树、屏幕缓冲区与光标状态。也就是说,Claude Code 不是简单“用 React 写组件”,而是把 React 的渲染引擎适配到了终端这个非浏览器环境中。

布局层则大量依赖 Yoga。layout/yoga.tslayout/engine.tsrender-to-screen.tsscreen.ts 等文件共同构成了从 React 树到布局计算、再到屏幕绘制的管线。其意义在于:终端界面传统上很难做稳定布局,宽度不固定、换行复杂、重绘容易抖动;而 Claude Code 借助接近 Flexbox 的布局思路,把现代 UI 系统的几何计算能力引入了 TUI。

渲染层同样很重。Ansi.tsxRawAnsi.tsxcolorize.tstermio/* 等文件负责颜色、光标控制、alternate screen、文本测量和终端控制。这里也要解释一个常见但非教科书式的术语:ANSI escape codes,即 ANSI 转义序列。它本质上是一类特殊字符序列,终端遇到它们时不会按普通文本显示,而会把它们解释成“移动光标”“改变颜色”“清屏”“切换屏幕缓冲区”等控制命令。Claude Code 正是靠这些控制序列,才能在终端里实现近似原生应用的界面效果。

除了静态渲染,它还支持动画、焦点管理、滚动、输入事件、窗口 resize、paste、click 等交互能力。代码中甚至有统一的 frame 计时与渲染节流,这说明系统不是按“打印一段文本”的方式工作,而是按响应式应用来组织。商业上,这种差异会直接体现在产品质感上:滚动是否稳定、界面是否抖动、状态刷新是否自然,都会影响用户对代理可靠性的判断。

输入体验方面,Claude Code 明确支持 Vim 键位。这意味着它不是只面向一般用户,也在认真照顾重度终端用户的操作习惯。对于长期在 shell、tmux、Neovim 环境中工作的开发者来说,是否支持 modal editing、快速跳转、键盘优先,往往会直接影响 adoption。

另一个容易被忽略但非常关键的点是 可访问性。在 App.tsxink.tsx 与相关 hook 中,可以看到对 screen reader、screen magnifier、IME 输入、可见光标等问题的考虑。也就是说,这套终端 UI 并不只是为了“炫技”,而是在考虑不同输入方式与辅助技术的兼容性。商业软件做到这一步,说明它已经从“内部工具”思维转向“正式产品”思维。

若与 OpenCode 对比,差别也很有意思。OpenCode 的 TUI 主要建立在 Solid.js 路线之上,强调细粒度响应式更新;Claude Code 则选择 React,并投入工程成本实现自己的终端 reconciler。前者更轻、更开放,后者则更像标准化、大规模维护的商业工程体系。两种选择反映了两种哲学:OpenCode 偏向可塑性,Claude Code 偏向产品完整度。

因此,本节的核心判断是:代理系统的竞争,不只是模型能力竞争,也包括交互壳层竞争。Claude Code 的自定义 Ink 实现证明,终端可以被做成高质量产品界面,而这恰恰构成了它商业体验的一部分。

Book: Claude Code VS OpenCode: Architecture, Design and The Road Ahead 章节: 第11章 — Claude Code的商业设计 Model: openai/gpt-5.4 Generated: 2026-04-01 Token Usage: 当前API环境不可见

11.5 多策略上下文压缩

Claude Code 的上下文管理非常商业化的一点,是它并不依赖单一的“总结一下历史对话”方案,而是在 services/compact/services/contextCollapse/ 下形成了一套多层压缩体系。可以把它理解成应对上下文溢出的五层防线。

第一层是 auto-compact,核心在 autoCompact.ts。它会估算当前 token 使用量,为摘要输出预留空间,计算有效上下文窗口,并在接近阈值时主动触发压缩。这里的关键思想是“先压缩,再爆掉”,而不是等 API 报 prompt-too-long 才补救。这是一种典型的商业工程选择:提前控制风险,避免会话在用户最需要连续性的时候突然中断。

第二层是 snip-compact,也就是历史裁剪式压缩。它与“全面重总结”不同,更像对旧上下文做局部切除或投影,把价值低、年代久、复用率差的历史段落从活动上下文里移出去。这样做的优点是更轻、更快,也更适合在长会话中持续运行。

第三层是 micro-compact,实现位于 microCompact.ts。这一层不直接针对整段对话,而是针对工具输出,尤其是那些体积巨大、但时效性很差的工具结果,例如文件读取、shell 输出、grep、glob、web fetch、web search 等。这个设计很聪明,因为真实编码代理里最膨胀的通常不是用户自然语言,而是工具返回结果。微压缩抓住了真正的大头。

第四层是 session memory compact,位于 sessionMemoryCompact.ts。Claude Code 不只是压缩表层对话,还会压缩会话记忆本身,同时确保 API 级别的不变量不被破坏,例如 tool_use 与 tool_result 的配对关系。换言之,它已经意识到 memory 也可能成为负担,因此 memory 本身也必须被治理,而不能无限增长。

第五层是 context collapse,对应 services/contextCollapse/。虽然某些外部构建可能对这一层做了裁剪,但架构意图很清楚:把更老的消息逐步折叠成更紧凑的摘要状态。它和普通压缩的区别在于,压缩更像应急措施,而 collapse 更像长期状态演化机制。前者是为了避免马上爆窗,后者是为了让超长会话从一开始就具备可持续性。

之所以说它是“多策略”,就在于每一层解决的问题都不同。auto-compact 负责总体阈值;snip-compact 负责裁掉低价值历史;micro-compact 负责缩短工具输出;session memory compact 负责记忆体积;context collapse 负责把陈旧历史转化为更稳定的摘要状态。五层机制并不是重复,而是面向不同失控模式的分工。

这种设计的商业价值非常直接。上下文越小,成本越低,延迟越稳,prompt-too-long 的概率越低,长会话体验也越可靠。对 Claude Code 来说,这不只是“更聪明的摘要系统”,而是高自治、长生命周期代理的必要基础设施。没有这种多层压缩,远程会话、长会话、协作会话都很难成立。

与 OpenCode 和 Oh-My-OpenCode 相比,Claude Code 在这里的优势不一定是单个策略最先进,而是它把多种策略同时纳入了统一产品体验。用户不需要精确理解每一层细节,系统会在不同场景下自动选择合适的缓冲与压缩手段。

这一节的结论很重要:未来优秀的代理系统,需要的不是更大的上下文窗口,而是更成熟的 上下文分层工程。Claude Code 的多策略压缩栈,正是这种工程观的代表。

Book: Claude Code VS OpenCode: Architecture, Design and The Road Ahead 章节: 第11章 — Claude Code的商业设计 Model: openai/gpt-5.4 Generated: 2026-04-01 Token Usage: 当前API环境不可见

11.6 Bridge与Coordinator模式

如果说安全、成本、压缩体现的是 Claude Code 的商业工程底盘,那么 BridgeCoordinator modeassistant mode(KAIROS) 体现的,则是它在工作模式上的扩张。它不再把代理限定为“本地命令行里的单一会话”,而是开始把代理设计成一种可远程、可持续、可多代理协调的工作系统。

先看 Bridge。用户入口是 claude remote-control,而实现分布在 src/bridge/ 下的大量文件中,如 bridgeMain.tsinitReplBridge.tsreplBridge.tsbridgeApi.ts 等。Bridge 的本质,是把本地 CLI 会话变成可被远端访问和继续的会话端点。也就是说,终端不再是唯一前端,Web 或移动端也可以接管、继续或接入这个工作流。

这件事意义很大。第一,它提供了 远程会话支持。会话不必随着当前 shell 退出而消失,而可以被继续、恢复、迁移。第二,它让 Claude Code 融入更大的产品生态:CLI、网页、移动端不再是分裂体验,而是同一会话拓扑上的不同入口。bridgeMain.ts 中关于环境注册、心跳、session spawn、token refresh、继续参数 --continue / --session-id 的实现,说明这不是简单的转发层,而是一套会话基础设施。

再看 Coordinator mode。它要解决的不是“远程接入”,而是 多代理编排。在 coordinatorMode.ts 中,Claude Code 明确把主代理定义为协调者:负责分派 worker、汇总研究结果、制定实现方案、组织验证,并管理 worker 的生命周期。文件里甚至写了完整的并行策略、通知格式、停止 worker 的规则、以及如何继续已有 worker 的流程。这已经不是“能开子代理”这么简单,而是正式的 orchestration protocol。

从产品角度说,这非常关键。很多开源代理用户会手工构造“主代理 + 若干子代理”的工作流,但那往往停留在提示词技巧或外部脚本层面。Claude Code 则把这种模式内建进产品行为中。协调者知道何时并行、何时综合、何时验证、何时中止,这意味着多代理不再只是实验性玩法,而变成了受支持的工作模式。

接着是 assistant mode(KAIROS)。代码中大量 KAIROS gate 表明,它与长运行、持续交互、会话续接、brief view、定时检查等能力有关。直观上可以把它理解为:Claude Code 不再只响应当前这一轮请求,而是在逐步向“长期陪伴式代理”演化。也就是说,代理从一次性应答者,转向长期会话参与者。

这三者结合起来,就形成了一种比传统 CLI agent 更强的会话拓扑:本地与远程可以打通,单代理与多代理可以切换,短会话与长会话可以延续。商业上,这类能力尤其适合高级用户与企业用户,因为他们真正关心的往往不是某一轮问答质量,而是复杂任务能否跨设备、跨时间、跨多个 worker 稳定推进。

与 OpenCode 和 Oh-My-OpenCode 相比,Claude Code 在开放可编排程度上未必最自由,但在 把远程控制、持续会话、多代理编排做成正式产品模式 这一点上,显然更成熟。这种成熟度来自它把会话当成基础设施来设计,而不只是把消息当成输入输出。

因此,本节最重要的启示是:未来编码代理的竞争,未必只发生在模型推理层,也会发生在 会话拓扑设计 上。Bridge、Coordinator 与 KAIROS 展示的,正是 Claude Code 对这一趋势的提前布局。

Book: Claude Code VS OpenCode: Architecture, Design and The Road Ahead 章节: 第11章 — Claude Code的商业设计 Model: openai/gpt-5.4 Generated: 2026-04-01 Token Usage: 当前API环境不可见

11.7 斜杠命令体系

Claude Code 的 slash command 体系,是它“像一个平台而不只是聊天壳”的最明显证据之一。中心注册表位于 src/commands.ts,这是一个约 754 行的文件,负责导入、过滤、组合和暴露上百个命令目录中的命令对象。命令系统在这里不是附属功能,而是用户控制代理的主控制面之一。

从类型上看,Claude Code 至少有三类命令:prompt 型、action 型、interactive 型。prompt 型主要生成文本或提示内容;action 型直接执行动作;interactive 型则启动更丰富的本地 UI 流程。这个分层很重要,因为它说明 slash command 并不是一堆平铺的快捷入口,而是已经有了明确的执行语义分类。

内建命令中,最典型的包括 /init/compact/memory/session/model/effort/cost/mcp/skills/agents/tasks/plugins 等。它们分别覆盖初始化、上下文治理、记忆管理、会话管理、模型控制、推理力度、成本查看、MCP 管理、技能、代理、任务与插件体系。也就是说,Claude Code 把大量系统能力都暴露成了统一的命令语言。

更重要的是,这个体系是 动态的commands.ts 并不只返回内建命令,它还会加载技能目录命令、插件命令、插件技能、bundled skills、workflow commands,甚至动态发现的 skills。换句话说,斜杠命令层是多个扩展系统的汇合点。功能最终是否“被看见”,很多时候取决于它能否进入 command registry。

这也让 Claude Code 的命令系统与 skill 系统发生了深度耦合。文件中有 getSkillToolCommandsgetSlashCommandToolSkillsgetMcpSkillCommands 等逻辑,说明有些命令是用户手工调用的,有些命令会被模型经由 Skill tool 调用,有些 MCP 加载进来的命令在满足条件时也会转化为 skill。也就是说,slash command 在 Claude Code 里不只是用户接口,同时也是模型能力组织方式的一部分。

这种统一有明显的商业价值。许多系统会把快捷命令、技能片段、插件入口、MCP 能力分散成多个概念层,结果用户理解成本很高。Claude Code 则尽量用 command object 这一套抽象来承载不同来源、不同用途、不同可见性的能力。命令是否可用,还可以根据认证状态、provider、feature gate 动态隐藏或展示。

从产品体验上看,这种体系非常像一个微型操作系统:/model 调模型,/effort 调思考强度,/compact 管上下文,/mcp 管外部工具服务器,/plugins/skills 管扩展,/session/memory 管持久化,/cost 管财务视角,/agents/tasks 管编排。这已经远远超出“聊天产品加几个快捷命令”的范畴。

与 OpenCode 和 Oh-My-OpenCode 相比,它们在开放定制性上往往更强;Claude Code 的优势在于,它把命令体系嵌入了整个平台结构之中。用户不是在一个聊天框里偶尔敲几个命令,而是在用一套命令语言调度代理系统的多个子系统。

因此,本节的核心结论是:当代理拥有模型、工具、会话、记忆、插件、MCP、成本、远程控制与多代理能力后,纯自然语言就不再是最高效的控制界面。一个成熟的 slash command 体系,是自由对话的必要补充。Claude Code 的 100+ 命令架构,正展示了这种结构化控制面的产品化形态。

Model: openai/gpt-5.4
Generated: 2026-04-01
Book: Claude Code VS OpenCode: Architecture, Design and The Road Ahead
章节: 第12章 — 解剖一个13万行代码的插件
Token Usage: ~10,200 input + ~1,520 output

12.1 插件入口与启动序列

理解 OMO 最好的切入点,不是先看 13 万行代码,而是先看 src/index.ts。原因很简单:这个文件决定了 OMO 如何“进入” OpenCode。

从源码上看,src/index.ts 导出的是一个异步 Plugin 函数。OpenCode 在插件加载阶段调用它,而这个时点发生在第一条用户消息真正进入模型之前。也就是说,OMO 不是在回答生成之后做一点点修饰,而是在会话最开始、上下文还没正式送进模型之前,就已经把自己的控制层装进去了。

这就是本章反复强调的一个结论:OMO 不是 fork OpenCode,而是借助 OpenCode 的插件系统,把自己“套”在宿主之上。

入口函数的前几步非常短,但含义很重。它先记录日志,然后调用 injectServerAuthIntoClient(ctx.client),再调用 startTmuxCheck()。前者是把服务端认证信息注入到客户端对象,后者是提前检查 tmux 环境是否可用。它们看起来像基础设施细节,但实际上属于启动保护层:先确保鉴权链路和可视化多智能体运行条件成立,再继续后续装配。

接下来是配置读取。loadPluginConfig(ctx.directory, ctx) 会读取用户级和项目级 OMO 配置,支持 JSONC,使用 Zod 做校验,而且在某些字段损坏时还会做“部分回退”。这一步一结束,disabled_hooksisHookEnabledsafeHookEnabled 这些运行时开关就被计算出来了。换句话说,OMO 启动时不是简单“全部打开”,而是先根据配置决定哪些子系统应该存在。

随后,入口函数创建 firstMessageVariantGate。这是一个很小但很关键的门控对象。它记录某个 session 是否已经用过“首条消息变体覆盖”。为什么需要这个门?因为 OMO 想把第一条用户消息和后续消息区别对待,例如在第一轮强制使用某种 variant、某种思考力度或者某种启动行为,而不是对整个会话一刀切。

接着,代码把 tmux 配置规范化为 tmuxConfig。即便用户没有完全配置,OMO 也会补出默认值,比如布局 main-vertical、主面板比例、最小宽度等。这里体现的是典型的启动序列设计思想:尽早把“可选输入”转换成“明确状态”,避免后续组件反复处理空值和默认值。

再往下是 createModelCacheState()。这个对象会被多个子系统共享,尤其是与模型上下文长度、Anthropic 1M context 能力、provider 模型限制相关的 hook。它相当于插件内部的模型能力缓存层。

然后才进入 manager 装配阶段:createManagers(...)。这里会创建 BackgroundManagerTmuxSessionManagerSkillMcpManager,以及后面极其重要的 configHandler。其中 configHandler 会在 OpenCode 的 config hook 中,把 agents、MCPs、commands、permissions 等内容真正注入到宿主配置对象中。

如果把整个启动过程抽象一下,OMO 的初始化可以理解为 6 个阶段:

  1. Provider 准备阶段:鉴权注入、tmux 环境检查、配置读取、模型缓存初始化。
  2. Plugin components 阶段:通过后续 config handler 间接加载 Claude Code 兼容插件组件。
  3. Agents 阶段:内建 agents、兼容层 agents、plugin agents、override 逻辑被拼装。
  4. Tools 阶段createTools(...) 构造完整工具注册表。
  5. MCPs 阶段:通过 config handler 合并 builtin MCP、.mcp.json MCP、plugin MCP。
  6. Commands 阶段:合并 builtin commands、skills-as-commands、Claude/OpenCode 命令目录、plugin commands。

这里要特别说明“bootstrap sequence”这个词。它在 CS 里通常指“启动序列”或“引导序列”,意思是一个系统在真正工作前,按顺序把运行所需的组件和状态准备好。OMO 的 src/index.ts 就是一个典型的 bootstrap sequence:它自己不实现所有复杂逻辑,而是负责安排谁先初始化、谁后初始化、谁依赖谁。

接下来入口函数调用 createTools(...)。顺序上很重要:工具先于 hooks 创建。因为 OMO 的部分 hooks 需要知道技能列表、可用 skills、类别信息,而这些信息要先在工具阶段通过 createSkillContext(...)createToolRegistry(...) 算出来。

有了工具结果之后,createHooks(...) 才运行。它接收 pluginConfig、modelCacheState、backgroundManager、hook enable predicate、safeHookEnabled,以及 mergedSkillsavailableSkills。这个 hook 工厂本身又是分层的:core hooks、continuation hooks、skill hooks。也就是说,入口文件并不是一次性把 41 个 hooks 全部硬编码进去,而是在启动时动态拼一个“策略图”。

然后 createPluginInterface(...) 把内部世界投影为 OpenCode 真正认识的那 8 个 hook 名字:toolchat.paramschat.messageexperimental.chat.messages.transformconfigeventtool.execute.beforetool.execute.after。这就是所谓的 “8-hook handshake”。握手的意思是:宿主和插件通过 8 个标准接口接通,但插件内部实际挂着远多于 8 个逻辑模块。

最后还有一个额外入口:experimental.session.compacting。这里 OMO 会在压缩上下文前保存 todo,执行 Claude Code 兼容 hook,然后再把 compaction context 注入进去。这说明 OMO 甚至不只接管“消息进来”和“工具执行”,它还进入了宿主的记忆压缩路径。

因此,src/index.ts 给我们的核心结论是:OMO 的强大,不来自入口文件本身很复杂,而来自入口文件极其克制地完成了正确的装配顺序。它先准备状态,再建 managers,再建 tools,再建 hooks,最后暴露给 OpenCode。正因为这个启动序列设计得足够干净,OMO 才能在形式上仍然只是一个 plugin,但在效果上却像一个完整的编排层。

Model: openai/gpt-5.4
Generated: 2026-04-01
Book: Claude Code VS OpenCode: Architecture, Design and The Road Ahead
章节: 第12章 — 解剖一个13万行代码的插件
Token Usage: ~10,500 input + ~1,560 output

12.2 八个钩子处理器

OpenCode 暴露给插件的宿主级入口并不多,但 OMO 几乎把它们全部用满了。真正对外的只有 8 个 hook handler,而 OMO 就是靠这 8 个入口,把自己的多智能体编排层挂上去的。

第一个是 config。它由 createConfigHandler(...) 生成,源码在 plugin-handlers/config-handler.ts。这个 hook 的地位非常高,因为它决定 OpenCode 最终“看见”什么。处理顺序很清晰:先 applyProviderConfig,再加载 plugin components,然后依次应用 agent config、tool config、MCP config、command config。这个顺序并不是随便排的。agent 先注入,后面工具权限才能针对 agent 重写;MCP 和 command 也需要在 agent 体系成形后再落盘到宿主配置对象里。所以 config hook 本质上是 OMO 的注册表注入器。

第二个是 tool。在 createPluginInterface(...) 里,它直接绑定到 tools 这个工具记录表。表面看只是“注册工具”,但本质上它把 OMO 的工具宇宙暴露给 OpenCode:LSP、session 管理、background task、delegate-task、skill、skill_mcp、slashcommand、interactive_bash 等都从这里进入宿主。

第三个是 chat.message。实现文件是 plugin/chat-message.ts。这是 OMO 在消息进入模型前最关键的改写点。这里会先把 sessionID -> agent 的映射记下来,然后通过 first-message variant gate 判断是否需要对首条消息应用特殊 variant。如果首轮没设 variant,就按 agent 和 model 去解析;不是首轮,则按 agent 变体规则继续处理。之后它会串行调用多个内部 hook:stopContinuationGuardkeywordDetectorclaudeCodeHooksautoSlashCommandstartWork。同时它还会检查 Ralph Loop 的提示模板,如果检测到“开始 Ralph Loop”或“取消 Ralph Loop”的模板文本,就会直接修改循环状态。也就是说,chat.message 不是简单地“改消息”,而是在做会话感知的预处理。

第四个是 chat.params。实现文件是 plugin/chat-params.ts。它负责把宿主给出的原始输入规整成内部能理解的结构,然后把控制权交给 anthropicEffort。用户提示里说这是“effort level”,非常准确。这里的 effort 指的是模型推理强度或选项配置,而不是人工工作量。也就是说,OMO 可以在模型真正执行前,根据 session、agent、provider、variant 去调整某些推理参数。

第五个是 event。源码在 plugin/event.ts。这是 OMO 的生命周期总线。OpenCode 发来的 session.createdsession.deletedmessage.updatedsession.errorsession.idle 等事件,都会先经过 OMO 的 dispatchToHooks(...),再分发给一长串内部逻辑:auto-update、Claude Code compatibility、background notification、session notification、todo continuation、unstable agent babysitter、context window monitor、directory injectors、rules injector、think mode、agent usage reminder、category skill reminder、interactive bash、Ralph Loop、stop continuation、compaction todo preserver、Atlas 等。这里还有一个非常工程化的小细节:OMO 会用 500ms 窗口去区分 synthetic idle 和 real idle,避免同一空闲事件重复触发。

第六个是 tool.execute.before。实现位于 plugin/tool-execute-before.ts。它是 OMO 的前置拦截流水线。当前顺序中最重要的主干是:

  1. writeExistingFileGuard 先做文件写入保护;
  2. questionLabelTruncator 再做标签截断;
  3. rulesInjector 在后续阶段注入仓库规则。

当然,真实流水线比这更长,还包括 Claude Code hooks、非交互环境适配、comment checker、directory-agents-injector、directory-readme-injector、tasks-todowrite-disabler、Prometheus markdown-only、Sisyphus Junior notepad、Atlas 等。除此之外,它还会对 taskslashcommand 做语义改写。例如:如果 task 参数里有 category,就强行把 subagent_type 改成 sisyphus-junior;如果只有 session_id 没有 agent type,就去解析这个 session 原来绑定的 agent。

第七个是 tool.execute.after。源码在 plugin/tool-execute-after.ts。它先从 tool-metadata-store 里拿出之前暂存的 title 和 metadata,对输出做一次补写,然后再按顺序执行 Claude Code hooks、tool output truncator、preemptive compaction、context window monitor、comment checker、directory injectors、rules injector、empty task response detector、agent/category reminder、interactive bash、edit/json error recovery、delegate-task retry、Atlas、task resume info、hashline read enhancer。前置拦截是防守,后置拦截则更像观察与修正。

第八个是 experimental.chat.messages.transform。实现文件是 plugin/messages-transform.ts。这个 hook 作用非常强,因为它能在消息历史正式送进模型之前改写整段上下文。当前源码里顺序非常明确:先执行 context injection,再执行 thinking block validation。用户提示里还提到了 todo preservation。严格按当前源码看,todo preservation 主要发生在 compaction 相关路径上,比如 compactionTodoPreserverexperimental.session.compacting,而不是直接写在这个 transform handler 里。这个差异很重要,因为它说明 OMO 不是把所有相关逻辑都堆在一个 transform 里,而是把每种保留策略放到最合适的宿主生命周期节点上。

把这 8 个 handler 按作用归类,可以得到三个层面:

  • 注册表层configtool
  • 推理前塑形层chat.messagechat.paramsexperimental.chat.messages.transform
  • 生命周期与工具拦截层eventtool.execute.beforetool.execute.after

所以,OMO 的关键不只是“有 8 个 hook”,而是这 8 个 hook 正好卡住了宿主运行时的几个咽喉位置:配置、消息、推理参数、事件、工具执行前后。只要拿住这些位置,就足以把一个普通插件扩展成完整的 agent orchestration layer。

Model: openai/gpt-5.4
Generated: 2026-04-01
Book: Claude Code VS OpenCode: Architecture, Design and The Road Ahead
章节: 第12章 — 解剖一个13万行代码的插件
Token Usage: ~10,700 input + ~1,540 output

12.3 工具注入架构

OMO 的工具系统不是简单“加几个工具”。更准确地说,它在 plugin/tool-registry.ts 里构造了一层工具注入架构:表面上仍然是 OpenCode SDK 能识别的 ToolDefinition,但每个工具背后都绑定了 OMO 自己的上下文、状态管理器、权限策略和会话语义。

src/tools/index.ts 看,最基础的一层是 6 个 LSP 工具:lsp_goto_definitionlsp_find_referenceslsp_symbolslsp_diagnosticslsp_prepare_renamelsp_rename。这只是起点。进入 createToolRegistry(...) 之后,OMO 会继续拼上 grep、glob、ast-grep、session-manager、background-task、call_omo_agent、可选的 look_at、delegate-task 工具 taskskillskill_mcpslashcommandinteractive_bash,以及实验性的 task system 工具和 hashline edit。通常所说 OMO 注册 26 个工具,指的就是这套基础非实验路径下的完整工具面。

为什么这里要用“注入”而不是“注册”?因为注册只是告诉宿主“有这个工具”。注入则意味着:工具在进入宿主前,已经被插件绑定了额外状态。

例如,createBackgroundTools(manager, client) 生成的 background_outputbackground_cancel 并不是裸函数,而是直接闭包绑定到当前 BackgroundManagercreateCallOmoAgent(...) 则绑定了 disabledAgents 规则和当前 OpenCode client。createSkillTool(...) 绑定了 merged skills、skill MCP manager、session ID 解析函数、git-master 配置和 disabledSkills。也就是说,工具表面统一,背后上下文各不相同。

其中最关键的工具是 task,也就是 delegate-task。它的工厂参数非常多:background manager、client、当前目录、用户 categories、git_master 配置、Sisyphus Junior 模型配置、browser provider、disabledSkills、availableCategories、availableSkills,以及同步 session 创建回调 onSyncSessionCreated。从这些参数就能看出,它不是一个简单的“启动子智能体”函数,而是一个带策略的委派网关。

为什么这个网关很重要?因为 OMO 的多智能体并不是在 OpenCode 之外另起炉灶,而是建立在 OpenCode 的 session 机制之上。一个被委派的任务,通常会变成:创建新的 session、设置 parent session、选择 agent、选择或推断 model、把 prompt 发进去,然后根据模式决定同步等待还是异步轮询。这一点非常关键,它解释了为什么 OMO 能在不改宿主核心的前提下做出多智能体编排:它复用了宿主本来就有的 session abstraction。

call_omo_agent 工具展示了另一种包裹模式。它只允许白名单里的 agent type,对大小写做归一化,检查 agent 是否被禁用,然后根据 run_in_background 进入后台执行或同步执行。如果是同步执行,还支持通过 session_id 继续已有 session;如果是后台执行,则明确禁止 session_id。这说明工具设计并不是随便堆参数,而是和后台管理语义紧密对齐。

background-task 工具则是另一个典型例子。用户视角里只有 background_outputbackground_cancel 两个工具,但背后实际挂着 BackgroundManager、任务历史、通知队列、轮询器、并发控制器、后代任务追踪等整套基础设施。这就是前面说的:工具不是一个名字,工具背后可以是一整个子系统。

并发控制尤其能体现 OMO 的工程深度。ConcurrencyManager 会把任务按模型键 provider/model 或 agent 名字分组,支持 modelConcurrency、providerConcurrency 和 defaultConcurrency 三层限制,如果都没配,默认值就是 5。它的 acquire/release 逻辑还专门用了 settled flag 防止重复 resolve/reject。这些都是典型的调度器级细节,不是“多加几个工具”能解释的。

工具注入架构还有一个重要特征:特性门控。比如,如果 multimodal-looker 被禁用,look_at 就根本不会注册;如果实验性的 task system 没开,task_createtask_gettask_listtask_update 就不存在;如果 hashline edit 没开,也不会覆盖 edit。这说明 OMO 不是“先注册全部工具再在运行时拦住”,而是在注册阶段就裁剪工具面。

最后还有一步 filterDisabledTools(allTools, pluginConfig.disabled_tools)。这让管理员可以进一步从配置层删除某些工具。注意这里的设计哲学:即便是 OMO 自己新增的工具,也不是神圣不可禁用的。整个工具层是策略驱动的。

如果从架构角度总结,OMO 的工具层可以理解为一种 ACI 层,也就是 agent-computer interface。模型通过工具与外部世界交互,而 OMO 在这个接口层加入了上下文、权限、队列、后台会话、tmux、skill MCP、session history 等能力。也正因如此,OMO 的工具系统看起来像工具集合,实际更像一个小型执行平台。

Model: openai/gpt-5.4
Generated: 2026-04-01
Book: Claude Code VS OpenCode: Architecture, Design and The Road Ahead
章节: 第12章 — 解剖一个13万行代码的插件
Token Usage: ~10,900 input + ~1,600 output

12.4 智能体系统实现

OMO 的 agent system 本质上是在 OpenCode 原生 agent 概念上,再叠一层“编排逻辑”。OpenCode 本来就支持 AgentConfig,也支持把不同 prompt 和权限打包成不同 agent。OMO 没有推翻这个机制,而是用 builtin-agents.ts 批量制造 agent,再通过 prompt 组装、模型回退、权限修改和元数据注入,把它们变成一套可协作的智能体群落。

核心文件是 src/agents/builtin-agents.ts。这里先定义 agentSources,把各个内建 agent 的工厂函数组织起来:sisyphushephaestusoraclelibrarianexploremultimodal-lookermetismomusatlas。结合后续配置处理器里补进去的 sisyphus-juniorprometheus,就构成了 OMO 常说的 11 个主角 agent。

createBuiltinAgents(...) 的第一件事不是造 prompt,而是做模型可用性判断。源码里还专门写了注释:这里不能在插件初始化期间调用 OpenCode client API,否则可能死锁。所以它会用 provider 缓存和 fetchAvailableModels(...) 去拿当前能用的模型集合。这一点很能说明 OMO 的成熟度:它不是只关心“逻辑上对不对”,还关心“在宿主生命周期里会不会卡死”。

接下来,categories 会通过 mergeCategories(categories) 合并,skills 会通过 buildAvailableSkills(...) 转换成后面 prompt 组装需要的形态。也就是说,OMO agent 的 prompt 并不是完全静态写死的,它会把当前环境里有哪些 category、skill、provider 状态一起考虑进去。

一般内建 agent 的收集在 collectPendingBuiltinAgents(...) 中完成。这里的流程非常典型:遍历 agent sources,跳过 disabled agents,检查模型要求,调用 applyModelResolution(...) 解析模型,然后 build agent、应用环境上下文、应用用户 overrides。这个流程里最值得解释的术语是 fallback chain,也就是“回退链”。在 CS 里,它指的是首选方案不可用时,按顺序尝试备用方案。OMO 对模型就是这么干的:如果用户指定模型不可用,就按 agent 需要的 provider/model/variant 备选链去寻找下一档可用组合。

Sisyphus、Hephaestus、Atlas 的构造还要更特殊。maybeCreateSisyphusConfig(...)maybeCreateHephaestusConfig(...)maybeCreateAtlasConfig(...) 会额外处理首轮无缓存、显式 override、provider 约束、UI 当前选择模型等情况。比如首次运行时,如果模型缓存还没建好,Sisyphus 和 Hephaestus 可以直接退到各自 fallback chain 的第一项,保证 agent 至少能启动。

但真正让 OMO agent system 和普通 prompt 列表拉开差距的,是 dynamic-agent-prompt-builder.ts。这个文件不是一个 prompt 文本,而是一组 prompt 模块工厂。它会动态生成:

  • key triggers section
  • tool selection table
  • explore/librarian usage section
  • delegation table
  • category + skills delegation guide
  • oracle usage section
  • hard blocks
  • anti-patterns

这里“factory pattern”也值得解释。工厂模式指的不是某个类叫 Factory,而是一种设计方式:不直接手写最终对象,而是通过一个“制造函数”根据输入动态生产对象。dynamic-agent-prompt-builder.ts 就是在做这个事——根据当前有哪些 agents、tools、skills、categories,拼出当前这次运行应该使用的 prompt 段落。

Sisyphus 是最典型的例子。在 src/agents/sisyphus.ts 中,它的 prompt 不是一大段硬编码文本,而是由身份定义、Intent Gate、代码库评估、探索策略、实现策略、委派规则、session continuity、task/todo discipline、category+skill 选择协议、hard blocks、anti-patterns 这些模块拼起来的。换句话说,这不是单纯的人设 prompt,而是一个“运行手册 prompt”。

为什么这种模块化很重要?有两个原因。

第一,它能和运行时能力保持同步。比如 categorizeTools(...) 会根据当前注册的工具,自动把工具分成 LSP、AST、search、session、command 等类别,然后生成 tool selection table。这样 prompt 里写的内容就不是“文档式想象”,而是和真实工具面一致。

第二,它允许 prompt 知道当前有哪些可用 skill、哪些 category 对应什么领域模型、哪些 agent 是用户自定义的。于是 agent 的系统提示不再只是通用行为规范,而是对当前环境的实时摘要。

从 OpenCode 视角看,这些东西最后仍然只是 AgentConfig。也就是说,在宿主层,OMO agent 仍然是原生 agent;但在编排层,它们已经拥有了彼此可见的角色定义、成本等级、使用触发条件和协作表。源码中的 AgentPromptMetadata 就承担了这个桥梁作用:cost、triggers、useWhen、avoidWhen、promptAlias 等信息都记录在这里。

因此,OMO 的智能体系统本质上是两层结构:

  • 宿主层:OpenCode 只看到一组 AgentConfig
  • 编排层:OMO 让这些 AgentConfig 彼此“知道对方是谁、什么时候该出场、谁贵谁便宜、谁适合委派给谁”。

最终结论是:OMO 的 agent system 不是“多几个 prompt 文件”,而是模型解析、回退链、prompt 工厂、权限注入、元数据协同共同构成的系统。也正因为如此,它才能在不修改 OpenCode agent 核心抽象的前提下,把原生 agent 提升成多智能体编排体系。

Model: openai/gpt-5.4
Generated: 2026-04-01
Book: Claude Code VS OpenCode: Architecture, Design and The Road Ahead
章节: 第12章 — 解剖一个13万行代码的插件
Token Usage: ~10,600 input + ~1,530 output

12.5 钩子系统深度剖析

OMO 最著名的内部结构之一就是 “41 hooks on 5 tiers”。但如果只记住 41 这个数字,其实还没有抓到重点。真正关键的是:OpenCode 给插件的宿主 hook 面非常有限,而 OMO 把几十个内部行为复用到这几个入口上。这才是它的架构技巧。

这里必须解释一下 multiplex 这个词。它在通信和系统里通常译作“复用”或“多路复用”,意思是:在较少的物理通道上承载较多的逻辑通道。OMO 的做法很像这个概念。OpenCode 只给了少数 plugin hook points,但 OMO 把很多内部策略都挂到这些点上,于是少量宿主入口承载了大量插件逻辑。

从源码看,create-hooks.ts 先合并三大类 hooks:

  • createCoreHooks(...)
  • createContinuationHooks(...)
  • createSkillHooks(...)

createCoreHooks(...) 里面又拆成三层:session hooks、tool-guard hooks、transform hooks。于是整体上就形成了五层结构:

  1. Session 层
  2. Tool-Guard 层
  3. Transform 层
  4. Continuation 层
  5. Skill 层

src/config/schema/hooks.ts 里,OMO 把 41 个 hook name 明确列成了 schema,这说明 hook 不是纯内部实现细节,而是公开配置面的一部分。用户可以通过 disabled_hooks 精确关掉其中任意一项。

钩子系统最重要的不是“有多少”,而是“按什么顺序执行”。在 hook 系统里,顺序本身就是优先级。

先看 tool.execute.before。其实现位于 plugin/tool-execute-before.ts。最关键的前半段流水线可以概括为:

  1. file guardwriteExistingFileGuard 先保护已有文件写入;
  2. label truncatorquestionLabelTruncator 再收窄标签和描述;
  3. rules injectorrulesInjector 在后续阶段把仓库规则注入进去。

用户提示里的 “file guard → label truncator → rules injector” 与当前源码是对齐的,只不过源码还插入了更多策略节点:Claude Code hooks、non-interactive env、comment checker、directory-agents-injector、directory-readme-injector、tasks-todowrite-disabler、Prometheus markdown-only、Sisyphus Junior notepad、Atlas 等。这个顺序体现了很强的工程直觉:先做安全防护,再做轻量规范化,再注入仓库级规则,最后再处理更具体的策略。

同样地,tool.execute.after 也不是一个散乱列表。它先从 tool-metadata-store 取出之前存下的 title 和 metadata,修正工具输出,然后按顺序调用 Claude compatibility、tool output truncator、preemptive compaction、context window monitor、comment checker、directory injectors、rules injector、empty-task detector、reminder hooks、interactive bash、edit/json recovery、delegate-task retry、Atlas、task resume info、hashline enhancement。前者负责“出手前别犯错”,后者负责“出手后别把结果原样放过去”。

再看 event。这是 OMO 最重的多路复用点之一。plugin/event.ts 中的 dispatchToHooks(...) 会把同一个 session/event 生命周期事件转发给多个内部子系统:auto update checker、Claude hooks、background notification、session notification、todo continuation enforcer、unstable agent babysitter、context window monitor、directory injectors、rules injector、think mode、Anthropic context limit recovery、agent usage reminder、category skill reminder、interactive bash、Ralph Loop、stop continuation guard、compaction todo preserver、Atlas。换句话说,一个 session.idlesession.error 事件,并不是只触发一段逻辑,而是触发整条策略链。

experimental.chat.messages.transform 则是另一个强力节点。当前源码顺序非常明确:先 contextInjectorMessagesTransform,后 thinkingBlockValidator。这意味着 OMO 先扩充消息上下文,再保证 thinking block 结构合法。用户提示里说到“todo preservation”,从概念上它确实属于“关键上下文保留”这一类,但在当前实现里,todo 保留主要挂在 compactionTodoPreserverexperimental.session.compacting 路径上,而不是直接写在 messages transform 里。这一点恰恰说明 OMO 的设计不是大而全地塞到一个入口,而是把不同问题分配到最适合的生命周期节点处理。

hook enable/disable 机制也很值得注意。入口文件会根据 disabled_hooks 构造 isHookEnabled,而各层 hook 工厂则统一通过 safeCreateHook(...) 创建。所谓 safe create,就是说:某个 hook 创建失败时,返回 null,而不是让整个插件启动失败。这是一种降级策略。对一个拥有 41 个 hook 的系统来说,如果任何一个小模块初始化失败就全盘崩掉,那基本不可维护。

还有两个细节体现出 OMO 的成熟度。

第一,有些 hook 会根据宿主版本自动退场。比如 directory-agents-injector 会检查 OpenCode 是否已经有原生支持,如果宿主升级了、自己能做了,OMO 就自动关闭这个兼容 hook。

第二,有些 hook 不仅看 disabled 开关,还看 feature flag。preemptive-compaction 就要求 hook 开启且 experimental 配置打开,才会真正生效。

所以,OMO 的 hook system 本质上不是“很多回调函数”,而是一个带执行顺序、降级策略、版本适配和配置开关的策略路由器。agents 提供角色,tools 提供动作,而 hooks 提供治理。这也是为什么 OMO 看起来像插件,运行起来却更像操作层。

Model: openai/gpt-5.4
Generated: 2026-04-01
Book: Claude Code VS OpenCode: Architecture, Design and The Road Ahead
章节: 第12章 — 解剖一个13万行代码的插件
Token Usage: ~10,300 input + ~1,430 output

12.6 配置分层

OMO 的配置系统很能体现它不是“小插件”,而是“插件里的平台”。因为它不仅要管理自己的行为,还要和 OpenCode 宿主配置、Claude Code 兼容层配置、MCP 配置、skills/commands/agents 配置共同工作。

入口文件里调用的 loadPluginConfig(ctx.directory, ctx),其实现位于 src/plugin-config.ts。从源码看,OMO 自己的配置分层可以概括成三层:

  1. defaults:代码里的默认值和可选字段默认行为;
  2. user config:OpenCode 配置目录下的用户级 oh-my-opencode.jsonoh-my-opencode.jsonc
  3. project config:项目目录下 .opencode/oh-my-opencode.json.jsonc

这里之所以说是“三层”,是因为用户级配置先加载为 base,然后项目级配置覆盖它,而默认值则散布在 schema optional 字段和运行时代码里。比如 tmux 配置、hook 开关、experimental 选项、notification 选项等,很多都不是靠配置文件必须写全,而是由代码补齐默认值。

与此同时,OMO 并不是脱离 OpenCode 单独运行。它的 config hook 最终还是要修改宿主 config 对象中的 agenttoolsmcpcommandpermissionprovider 等大块内容。所以可以说:OMO 的三层配置,叠加在 OpenCode 更大的宿主配置体系之上。也正因此,书里常把它概括为“OMO 三层与 OpenCode 七层共存”。前者是插件内部优先级,后者是宿主整体配置世界。

配置 schema 是这个系统能稳定运转的基础。src/config/schema/ 目录里有 22 个 Zod v4 schema 文件,分别覆盖 agent-names、agent-overrides、babysitting、background-task、browser-automation、categories、claude-code、commands、comment-checker、dynamic-context-pruning、experimental、git-master、hooks、notification、oh-my-opencode-config、ralph-loop、sisyphus-agent、sisyphus、skills、tmux、websearch 等。如此细拆并不是“文件多”,而是把复杂配置域按责任边界拆开。

总 schema 在 oh-my-opencode-config.ts 中汇总。它定义了:

  • disabled_mcpsdisabled_agentsdisabled_skillsdisabled_hooksdisabled_commands 这些全局裁剪列表;
  • agentscategoriesclaude_codeskillsexperimental 等嵌套配置树;
  • background_tasknotificationgit_mastertmux 等子域;
  • _migrations 这样的迁移元数据。

也就是说,OMO 的配置不是平铺 key-value,而是一个经过类型系统组织过的策略树。

其中一个非常实用的点是 JSONC 支持。plugin-config.ts 使用 parseJsonc(...) 解析配置文件,并通过 detectConfigFile(...) 优先寻找 .jsonc。为什么这件事重要?因为在大系统里,注释本身就是开发体验的一部分。一个拥有几十个开关、多个子系统的插件,如果配置文件不能写注释,用户就很难长期维护自己的策略。JSONC 在这里不是语法糖,而是 DX 基础设施。

更关键的是 OMO 的校验失败策略。loadConfigFromPath(...) 先对整个配置做 safeParse。如果全部成功,直接返回。如果失败,不会立刻把整个插件判死刑,而是记录错误后转而调用 parseConfigPartially(rawConfig)。这个函数会对每个顶层 section 单独做校验,只保留合法部分,把坏掉的部分跳过,并把错误打日志。这就是所谓的 partial fallback,也就是“部分回退”。

这个术语也值得解释。回退本来就表示“主路径失败后退到次优路径”;部分回退则表示不是整个系统一起退,而是只让坏掉的那一部分降级。对长期演进的配置系统来说,这个设计非常重要。否则一个过时的 experimental 字段就可能导致整个插件失效。

合并逻辑也不是简单浅拷贝。mergeConfigs(base, override) 里,agentscategoriesclaude_code 这些对象字段用 deepMerge 合并;disabled_agentsdisabled_mcpsdisabled_hooksdisabled_commandsdisabled_skills 这些列表则会经过 Set 去重后累加。这反映了一个策略层的设计原则:禁用项通常是单调的,用户级和项目级都说“禁用”时,最终就应该禁用,而不是互相覆盖丢失。

另外还要注意,配置不是读完就结束。OMO 会把“静态配置”转成“运行态配置”。例如入口文件里会把原始 tmux 配置转成明确的 tmuxConfigconfig hook 又会根据 pluginConfig 和宿主现状,实际生成 agent permissions、command registry、MCP merge 结果等。所以配置系统有两层含义:一层是读取用户输入,另一层是把这些输入编译为实际运行策略。

配置分层还跨越生态边界。比如 applyCommandConfig(...) 会把 builtin commands、skills、Claude Code commands、OpenCode command 目录、plugin commands 合并到一起;applyMcpConfig(...) 则会把 builtin MCP、.mcp.json、plugin MCP、用户显式禁用状态一起融合。也就是说,配置分层不仅是纵向的“用户 > 项目”,也是横向的“多生态资产共存”。

因此,OMO 配置系统的本质可以概括为:注释友好、类型严格、分域组织、支持部分回退、支持层级合并、并能把静态配置编译为运行态策略。对于一个 13 万行级别的插件来说,没有这样的配置设计,整个系统几乎不可能长期稳定演化。

Model: openai/gpt-5.4
Generated: 2026-04-01
Book: Claude Code VS OpenCode: Architecture, Design and The Road Ahead
章节: 第12章 — 解剖一个13万行代码的插件
Token Usage: ~10,800 input + ~1,500 output

12.7 Claude Code 兼容层

OMO 有一个非常聪明的策略:它不要求用户把 Claude Code 生态资产全部重写一遍再迁移过来,而是尽可能把这些资产“吸进来”。这层兼容逻辑分散在四块源码里:claude-code-plugin-loaderclaude-code-command-loaderclaude-code-agent-loaderclaude-code-mcp-loader

先看 commands。claude-code-command-loader/loader.ts 会递归加载四类命令目录:

  • ~/.claude/commands
  • 项目内 .claude/commands
  • OpenCode 全局配置目录下的 command 目录
  • 项目内 .opencode/command

也就是说,OMO 一方面兼容 Claude Code 的命令目录,另一方面也提供了 OpenCode 风格的命令落点。命令文件本身是 markdown,带 frontmatter,解析后会被包成统一模板:上半部分是 <command-instruction>,下半部分是 <user-request>。最终再转换为 OpenCode 能接受的 CommandDefinition

再看 agents。claude-code-agent-loader/loader.ts 会从 ~/.claude/agents 和项目内 .claude/agents 读取 markdown agent 定义,解析 frontmatter,把正文作为 prompt,构造成 mode: "subagent"AgentConfig,如果 frontmatter 里写了 tools,还会转成 OpenCode 风格的工具权限映射。需要特别强调的是:按当前源码,并没有实现 .opencode/agents 的对称 loader。这说明兼容层并不是每类资产都完全对称,有些迁移路径更成熟,有些还只是部分覆盖。

MCP 兼容层更完整。claude-code-mcp-loader/loader.ts 会读取多个位置的 .mcp.json

  • ~/.claude.json
  • ~/.claude/.mcp.json
  • 项目根目录 .mcp.json
  • 项目内 .claude/.mcp.json

之后再通过 transformMcpServer(...) 把 Claude 风格的 MCP 配置转换成 OMO/OpenCode 可用的 MCP server config。对于远程 MCP,会输出 type: "remote";对于 stdio MCP,会输出 type: "local" 且把 command 和 args 组装成数组。这里还有一个关键能力:expandEnvVarsInObject(...) 会递归展开 ${VAR}${VAR:-default} 形式的环境变量。也就是说,兼容层不是只认文件格式,还保留了原生态中常见的变量替换习惯。

plugins 则是最复杂的一块。claude-code-plugin-loader/discovery.ts 会去读 ~/.claude/plugins/installed_plugins.json,同时参考 Claude settings 里的 enabledPlugins,拿到每个插件的 installPath、scope、version。随后又会读取插件目录中的 .claude-plugin/plugin.jsoncommands/agents/skills/hooks/hooks.json.mcp.json 等内容。再由 loadAllPluginComponents(...) 并行装载 commands、skills、agents、MCP servers、hooks configs。

这里必须基于源码做一个准确说明:当前实现里,Claude Code plugins 的发现路径是 ~/.claude/plugins 下的安装数据库,而不是项目内的 .opencode/plugins/。用户提示中把“plugins”写成 .opencode/plugins/,更像一种概念化迁移路径,但按当前源码,真正存在项目级 OpenCode 对称目录的是 commands,不是完整插件安装数据库。

plugin MCP 的处理尤其体现兼容层的细致。mcp-server-loader.ts 在读插件自己的 .mcp.json 时,会先做 ${CLAUDE_PLUGIN_ROOT} 的路径替换,再做环境变量展开,然后才真正转换成 MCP config。也就是说,兼容层不仅能“读懂”配置文件,还能保留插件内部的相对路径约定和变量约定。

为什么要维持这一整层兼容?核心原因就是迁移路径。

如果一个用户已经在 Claude Code 里积累了很多 commands、agents、skills、MCP 配置和 plugins,那么最痛苦的不是“OMO 能不能做得更强”,而是“我是不是要从零重建这些资产”。OMO 的兼容层给出的答案是:尽量不用。你可以把已有资产带过来,再叠加 OpenCode 插件系统提供的 hook、tool、session 编排能力。这种设计极大降低了切换成本。

从生态竞争角度看,这种兼容层非常重要。工具生态往往不是靠“谁最好”赢,而是靠“谁迁移最平滑”赢。OMO 通过兼容 Claude Code 资产,等于是在说:你以前在另一个生态里的投入不会浪费。

当然,这种兼容不是无约束的。plugin-components-loader.ts 会受 claude_code?.pluginsplugins_overrideplugin_load_timeout_ms 等配置控制;applyCommandConfig(...)applyAgentConfig(...)applyMcpConfig(...) 也分别受 claude_code?.commandsclaude_code?.agentsclaude_code?.skillsclaude_code?.mcp 这些开关控制。也就是说,兼容层是精细化可控的,不是全盘接收。

此外还存在优先级和命名空间设计。plugin commands 和 plugin agents 都会加上 pluginName: 前缀,避免冲突;MCP 合并时会保留用户显式禁用状态,并在最后删除被 disabled_mcps 明确禁掉的条目。这些细节说明:OMO 的兼容层不是“能读就算兼容”,而是把迁移过程做成了受治理的合并流程。

所以,从架构意义上说,Claude Code 兼容层不仅是一个方便功能,更是一种平台策略:优秀的 agent 平台不能只扩展自己,还要能吸收相邻生态。这恰恰是 OMO 之所以像平台、而不只是像插件的原因之一。

Model: openai/gpt-5.4
Generated: 2026-04-01
Book: Claude Code VS OpenCode: Architecture, Design and The Road Ahead
章节: 第12章 — 解剖一个13万行代码的插件
Token Usage: ~11,000 input + ~1,610 output

12.8 背景智能体生成器

OMO 的 background agent system 是它最像“调度器”的地方。相关核心代码分布在 src/features/background-agent/ 目录,重点包括 manager.tsspawner.tsconcurrency.tsstate.ts,以及若干 notification、polling、result-handler 模块。

第一件必须明确的事是:OMO 的背景智能体不是内存里开一个轻量协程,而是创建真正的 OpenCode session。无论是 spawner.ts 里的 startTask(...),还是 BackgroundManager.startTask(...),都能看到它们调用 client.session.create(...),把 parent session ID 传进去,再生成一个类似 Background: ${description}${description} (@${agent} subagent) 的标题。

这一步很关键。因为只要子任务是宿主原生 session,它就自动继承了很多能力:

  • 有独立 transcript 和消息历史
  • 有 parent-child 关系
  • 有 session ID 可供后续追踪
  • 工具调用仍走宿主原生链路
  • 可以被 session 管理工具读取

也正因为此,OMO 的后台子智能体不是“模拟多线程”,而是“基于宿主 session 的异步编排”。

任务从 LaunchInput 开始,被包装成 BackgroundTask。里面包含任务 ID、状态、排队时间、description、prompt、agent、parentSessionID、parentMessageID、parentModel、parentAgent、显式 model 等信息。BackgroundManager.launch(...) 会先把任务记成 pending,写入 taskHistory,再按并发键放入队列,然后异步触发 processKey(key)

这里的并发键设计特别重要。如果用户显式指定了模型,那么并发键就是 providerID/modelID;否则退回 agent 名称。ConcurrencyManager 会按这个键控制并发,支持三层限制:

  • 精确模型级限制 modelConcurrency
  • provider 级限制 providerConcurrency
  • 默认限制 defaultConcurrency

如果都没配,getConcurrencyLimit(...) 返回的就是 5。这就是为什么 OMO 常被描述为“每个 model/provider 默认 5 个并发后台任务”。这个结论不是文档修辞,而是源码里的默认值。

并发管理的实现也很讲究。acquire() 如果当前数量没到上限,就直接加计数;否则就把等待者塞进队列。release() 时并不是先减计数再让下一个竞争,而是优先把槽位直接 handoff 给下一个 waiter。只有没有等待者时,才真正减少 count。配合 settled 标记,就能防止等待者被重复 resolve/reject。这样的实现细节说明,OMO 的后台系统不是“能跑就行”,而是认真把队列正确性当作一等问题。

真正启动任务时,OMO 还会先查 parent session,尽量继承 parent 的工作目录。这一点很重要:后台子智能体不是盲目在插件启动目录里工作,而是尽量在父会话正在操作的目录里继续。这保证了项目上下文的一致性。

子 session 创建成功后,OMO 会把该 session 标记为 subagent session;如果 tmux 开着且当前就在 tmux 内,还会通过 onSubagentSessionCreated 回调让 TmuxSessionManager 新开 pane。随后任务状态改成 running,记录 startedAt、sessionID、progress,再通过 promptWithModelSuggestionRetry(...)promptAsync(...) 把 prompt 发给子 session。

注意这里发送 prompt 时还会显式约束工具:它会应用 agent-specific tool restrictions,禁掉 task,允许 call_omo_agent,拒绝 question。这说明后台子智能体不是完全自由的,它是一种受限 worker session。

后台系统的另一个重点是父会话通知。BackgroundManager 内部维护了 notificationspendingByParent、completion timers、idle deferral timers、按 parent 排队的通知 promise 等结构。目标不是让用户自己不停轮询每个子任务,而是在任务完成、出错或一批任务收尾时,父 session 能收到提示。这正是 OMO“多智能体但不混乱”的关键体验保障。

用户提示里特别提到 session_id continuation preserving full context,这在 OMO 里主要有两条路径。

第一条是 call_omo_agent 的同步继续模式。subagent-session-creator.ts 中的 resolveOrCreateSessionId(...) 会先看 args.session_id。如果传了,就直接读取这个 session;如果没传,才新建 session。这意味着同步子智能体可以在原有 session 上继续跑,完整保留之前的上下文和 transcript。

第二条是 BackgroundManager 对任务树的追踪。它提供 getTasksByParentSession(...)getAllDescendantTasks(...),因此父 session 和多层子 session 之间的上下文关系并不会丢失,只是由任务管理层追踪,而不是通过单个 session_id 参数直接表示。

最后还必须讲 boulder state。相关实现位于 src/features/boulder-state/storage.ts。这里的 “boulder” 明显来自 Sisyphus 的神话意象,表示那个需要持续往前推的长期计划。boulder state 会把 active plan、started_at、session_ids、plan_name 记录到 .sisyphus 目录下的 JSON 文件中。还可以:

  • appendSessionId(...) 把新 session 记到同一个计划状态里;
  • clearBoulderState(...) 在显式停止时清掉计划状态;
  • findPrometheusPlans(...) 找到对应的 markdown 计划文件;
  • getPlanProgress(...) 通过 markdown checkbox 统计计划完成度。

这意味着 OMO 对“持续执行”的持久化分成了三层:

  • OpenCode session:保留对话和运行时上下文
  • Background task state:保留调度、轮询、通知状态
  • Boulder state:保留长期计划本身及其中断后的恢复锚点

也正是因为有这三层,OMO 的后台智能体才不像普通异步任务那么脆弱。它们不是简单的 job,而是有 session、任务树、通知系统和计划持久化共同支撑的编排单元。换句话说,OMO 所谓的 background agent spawner,不只是“生成一个子智能体”,而是在 OpenCode 的 session substrate 上,搭建出一个真正可持续的多智能体执行平面。

Book: Claude Code VS OpenCode: Architecture, Design and The Road Ahead 章节: 第13章 — 架构哲学对比 Model: openai/gpt-5.4 Generated: 2026-04-01 Token Usage: 当前API环境不可见

13.1 开放 vs 封闭

OpenCode、Oh-My-OpenCode 与 Claude Code 之间最底层的差异,首先不是功能多少,而是它们对“系统应该开放到什么程度”有完全不同的答案。这里的“开放”,并不只是源代码能不能看;更关键的是:系统是否被设计成一个可以被第三方修改、分叉、重组、重新定义边界的架构。相应地,“封闭”也不只是闭源,而是指模型、工具、权限、安全、交互与产品边界被同一个厂商做了垂直整合。二者各自带来不同的能力与代价。

OpenCode 属于非常典型的开放系统。它不仅源码可见,而且在实践层面是 model-agnostic、provider-agnostic、extension-friendly 的。也就是说,它并不强绑定某一个模型提供者,也不要求工具系统、提示词系统、权限系统只能按照唯一方式工作。用户可以替换模型、接入不同 provider、改写工具表面,甚至直接 fork 整个项目。这种开放性在今天尤其重要,因为 AI Agent 领域仍处在快速演化期。范式还没完全收敛,谁都不能确定“标准答案”已经出现。在这种阶段,能试错、能扩展、能分叉,本身就是一种战略优势。

OMO 正是 OpenCode 开放性的最好证明。它并不是在宿主上加几个小命令而已,而是在不推翻宿主核心结构的前提下,叠加出一个更大、更强、更有主张的多智能体编排层。这说明 OpenCode 开放的不是“皮肤层”,而是足够深的结构层。只有当宿主系统暴露出真实可用的控制面,外部系统才可能在其上生长出新的“操作系统级”能力。

Claude Code 走的是另一条路。它更接近封闭系统,但这种封闭并不只是“限制用户”,而是一种有明确收益的垂直整合策略。Anthropic 可以把 模型能力工具协议权限分类器上下文压缩策略CLI/TUI 体验 一起设计、一起调优。这里可以用一个并不常见但很关键的概念来描述:model-tool co-optimization。它的意思是,工具系统不是先独立设计出来,再拿给任何模型通用地调用;而是和目标模型的能力边界、失败模式、指令跟随特征一起联合优化。

这种整合会带来非常现实的好处。Claude Code 可以更放心地假设工具输出格式、错误恢复模式、权限审批路径、长任务行为模式都落在自己熟悉的边界内。因为模型和产品来自同一供应商,运行时的不确定性更少,系统就可以做得更细、更深、更稳。安全策略也可以围绕真实观测到的模型行为来微调,而不需要兼容二十个 provider 各不相同的语义差异。换句话说,封闭设计换来了更强的整体优化深度。

但封闭的代价也非常经典:vendor lock-in。在软件系统里,所谓厂商锁定,并不是说“你物理上离不开它”,而是说一旦用户的工作流、命令习惯、配置认知、扩展方式都围绕某家平台建立起来,迁移成本就会越来越高。Claude Code 用户得到的是高度打磨的一体化体验,但他们也必须接受 Anthropic 所定义的边界:用哪些模型、暴露哪些 hook、支持哪些扩展形式、允许什么样的安全姿态。这种限制不是偶然,而是产品化封闭平台的内在逻辑。

OpenCode 则站在相反的一侧。由于它要保持可移植性,它不能对某一个模型栈做过深绑定。这里的“可移植性”也不只是“换个环境还能跑”,而是指架构本身尽量避免依赖只对某一家模型成立的假设。这样做的好处是韧性更强。如果未来前沿模型变化了,OpenCode 可以换 provider;如果企业要求本地部署、主权算力、定制合规层,OpenCode 也更容易承载。它牺牲的是针对单一模型-工具组合做到极致调优的能力。

OMO 的位置很有意思。它继承了 OpenCode 的开放底座,但又利用这种开放性,把系统推向一个更强主张、更高自治、更重编排的方向。也就是说,OMO 在生态意义上依然是开放的,但在内部哲学上却非常“强势”。它不像 Claude Code 那样封闭整个生态,而是围绕一种明确的工程观建立内部秩序:多智能体委派、skill 专业化、prompt 驱动的纪律约束、极端自治。于是我们看到三种层次:OpenCode 是开放基础设施,OMO 是建立在开放基础设施之上的强主张系统,而 Claude Code 是商业化的一体化封闭产品。

这组对比背后,其实对应着一个更一般的架构命题:可移植性 versus 优化深度。开放系统最大化可移植性、可检查性、演化潜力;封闭系统最大化整合调优、整体一致性与产品级稳定性。二者没有绝对高下,关键在于你希望“灵活性”放在哪一层。OpenCode 把灵活性交给开发者和插件作者;Claude Code 把优化权力收回到产品供应商手中;OMO 证明了,只要宿主暴露足够多的结构缝隙,开放平台上也能长出极其有野心的高阶系统。

因此,本节真正的结论不是“开放更好”或者“封闭更好”,而是:你必须明确哪一层需要保持可移植,哪一层值得垂直整合,以及谁应该拥有这条边界的控制权。这才是下一代 Agent 架构设计里最核心的问题之一。

Book: Claude Code VS OpenCode: Architecture, Design and The Road Ahead 章节: 第13章 — 架构哲学对比 Model: openai/gpt-5.4 Generated: 2026-04-01 Token Usage: 当前API环境不可见

13.2 简单 vs 复杂

所有 AI Coding Agent 都在承诺一件事:让开发者以更低摩擦完成更复杂的工作。但问题在于,复杂性从来不会真正消失,它只会被重新安放。于是,一个系统到底是“简单”还是“复杂”,不能只看用户界面,也不能只看代码行数,而要看复杂性被放在了哪里、由谁承担、换来了什么能力。

OpenCode 处在一个相对均衡的位置。它并不极简,但它的复杂度大体属于 moderate complexity,而且层次划分相对清晰。Provider 抽象、Tool 注册、Session 管理、MCP 接入、权限控制、插件表面,基本都能看到较明确的模块边界。从软件工程角度看,这种“复杂但分层”的状态是很健康的。系统真正可维护,不是因为它没有复杂度,而是因为复杂度被合理分区了。所谓分区,就是开发者可以只理解某一个子系统,就能做局部修改,而不必在脑中同时模拟整个代码库的全局状态。

Claude Code 展示的是另一种形态:外部简单,内部复杂。对最终用户来说,Claude Code 往往比 OpenCode 更“省心”。命令行和交互体验更成熟,默认行为更强,安全与审批流程被产品内建,很多配置负担也被平台吸收了。但这并不意味着它内部更简单。恰恰相反,产品层面的平滑,往往意味着实现层面的复杂。一个很直观的信号,就是版本分析中那个接近 4691 行的 main.tsx。单一大文件本身未必等于坏设计,但它通常意味着:编排逻辑、UI 状态、产品需求、边界条件、兼容分支在同一个中心面逐步沉积。

这其实是商业产品里很常见的现象。厂商为了给用户一个更顺滑的表面,会主动吞下大量内部复杂性。用户少配一点参数、少理解一点架构,意味着产品内部要多做很多判断、兜底、降级、回退和协同。也就是说,Claude Code 的“简单”,更多是一种 interface simplicity,不是 implementation simplicity。看起来越顺手,后面往往越重工程。

OMO 则是三者中最明确拥抱复杂性的系统。它大约 129K LOC 的规模,不是偶然膨胀,而是它对问题定义的自然结果。OMO 不满足于“单智能体 + 工具调用 + 少量提示词约束”这一层,它要做的是多智能体委派、后台任务、skill 体系、hook 多路复用、任务续跑、提示词操作纪律、上下文继承、工作流强化。这一整套能力,天然就要求更多的状态、更多的控制路径、更多的恢复逻辑。换句话说,OMO 把复杂性当成能力建设成本,而不是单纯想把系统做大。

这里可以引入一个 CS 和软件工程里很重要的区分:essential complexityaccidental complexity。前者叫“本质复杂性”,来自问题本身;后者叫“偶然复杂性”,来自糟糕抽象、坏耦合或实现细节失控。OMO 支持者会说,它面对的是“极端自治”这个本来就难的问题,所以复杂度大部分是本质复杂性。批评者则会指出,任何 129K 行级别的编排系统,都几乎不可能完全避免偶然复杂性。两者并不冲突:一个系统可以确实在解决困难问题,同时也在某些地方付出过高的架构税。

OpenCode 则更像一个中间解。它足够复杂,能作为平台承载多种能力;但又没有复杂到完全压垮概念清晰度。Claude Code 是把复杂度往内部压,让用户表面更轻;OMO 是把复杂度向上层编排系统推,以换取更强自治与持续执行能力。三者差别,不只是写法不同,而是在回答同一个问题:谁来承担认知成本

这个问题还有一个 UX 维度。对用户简单,往往意味着对修改者不透明。Claude Code 的普通用户得到了低摩擦体验,但外部开发者很难重塑它。OpenCode 虽然少了一些“魔法感”,却因此更容易被理解和扩展。OMO 对新手最不友好,但对高级操作者可能最有吸引力,因为它提供的不是一个“聪明助手”,而是一套可以操作高自治工作的工程化底座。

所以,判断一个系统“简单还是复杂”,至少要看三层。第一层是 interface simplicity:用户是否容易上手。第二层是 architectural simplicity:代码和模块边界是否清晰。第三层是 operational simplicity:用户要花多少持续精力才能把系统带到正确方向。Claude Code 优先优化第一层,OpenCode 在第二层表现较好,OMO 则愿意牺牲前两者的一部分,换取在硬任务中的执行力度。

本节最核心的结论是:不要抽象地问“系统复杂是不是坏事”。应该问的是,复杂性放在哪、谁为它买单、它是否换来了真实能力。好的架构并不总是减少复杂性,很多时候它只是把复杂性移动到最能被管理的那一层。

Book: Claude Code VS OpenCode: Architecture, Design and The Road Ahead 章节: 第13章 — 架构哲学对比 Model: openai/gpt-5.4 Generated: 2026-04-01 Token Usage: 当前API环境不可见

13.3 控制 vs 自主

如果说“开放与封闭”决定了系统边界,“简单与复杂”决定了复杂性分布,那么“控制与自主”决定的就是 Agent 到底能走多远。这里的 control,指的是人类、策略系统、权限机制、运行时边界对代理行为的约束程度;autonomy,指的是代理在多大程度上可以不被打断地自行判断、自行执行。这不是“保守 vs 激进”的简单价值判断,而是一条牵涉速度、安全、责任归属与任务完成质量的工程光谱。

Claude Code 是三者里最典型的 safety-first、human-in-the-loop 模型。所谓 human-in-the-loop,是控制系统里一个很经典的概念,意思是人类仍然保留在关键决策回路中,不完全退出执行链。Claude Code 的权限模式、分类器、危险模式检测、操作系统沙箱,本质上都在服务这个目标:即便代理能力已经很强,它也不应在完全无边界的条件下自行扩张。它可以自动处理大量低风险步骤,但高风险或模糊动作仍然要经过清晰的边界控制。

从商业角度看,这种设计非常合理。企业真正购买的不是“绝对自治”,而是“可被审计、可被解释、可被约束的自治”。在这种场景里,审批、提示、沙箱并不只是烦人的打断,而是信任契约的一部分。Claude Code 的哲学很清楚:代理可以快,但必须在已经工程化的安全边界里快。换句话说,它卖的不是野生自治,而是被封装后的、可控的自治。

OpenCode 则更像把这个问题交回给用户和开发者自己决定。它不强行预设唯一答案,而是暴露更多控制面,让不同团队自行选择希望达到什么自治级别。如果某个团队要强审批、强确认、低风险,那可以配得很保守;如果另一个团队想追求更高自动化,也能把系统往更激进方向推。OpenCode 的核心哲学不是“自主优先”或者“控制优先”,而是 autonomy should be configurable。也就是说,自主程度不应被宿主产品完全规定,而应成为一个可调参数。

从控制理论角度说,OpenCode 暴露了更多 control surface。所谓控制面,就是系统中那些可以调节行为模式的杠杆集合。谁掌握控制面,谁就决定系统行为在多大程度上可塑。OpenCode 的优点,是把自由给了用户;代价,则是用户也必须承担更多责任:你需要自己设计合适的权限、工具、工作流和操作习惯,才能真正把自治用好。

OMO 则把这一哲学推进到了极端。它隐含的核心命题几乎可以概括成一句话:人类介入越频繁,越说明系统设计不够好。这是一种非常强的自治立场。这里并不是说人类不重要,而是说,在理想状态下,系统应该能够自己拆解任务、自己调用工具、自己委派子代理、自己恢复中断、自己继续推进,以至于人类不必反复回来“救场”。在 OMO 的语境里,频繁的人工干预不只是体验不好,而是一种架构失败信号。

这与大多数商业 Agent 的价值观差异非常明显。OMO 大量机制——todo 强约束、后台代理、session 延续、specialized agents、纪律型系统提示词——都在服务同一个目标:让工作连续推进,而不是每走几步就等人重新下指令。从 AI 规划系统的角度看,OMO 试图把 Agent 从“响应式助手”往“持续性自主执行器”推进一步。而这也解释了为什么它需要更厚的编排层:高自治不是一句“让模型自己多做点”就能达成的,它需要恢复机制、委派机制、角色分工、状态续存、过程纪律。

当然,这种哲学天然伴随风险。自治程度越高,误解任务的代价越大;系统一旦走偏,可能会在错误方向上高强度前进。高自治如果缺乏验证环,就会从“高效”滑向“鲁莽”。所以 OMO 真正值得讨论的,不是它是否追求极端自主,而是它试图用结构化纪律去替代人类频繁介入:用 todo、hook、委派和会话续跑,让“内部过程”承担一部分本来由人类随时纠偏的工作。

于是我们得到三种非常鲜明的立场。Claude Code 认为:自主很有价值,但必须服从安全架构与商业信任边界。OpenCode 认为:自主程度应该由用户自己决定,它是一个可配置变量。OMO 则认为:只要架构支撑得住,就应该尽量把自主推高,因为反复依赖人类介入是不可扩展的。

对未来 Agent 设计者而言,真正该问的不是“Agent 该不该自主”,而是:对谁自主、在什么约束下自主、出了问题如何回滚、靠什么做验证。控制与自主并不是成熟系统中的绝对对立面。好的控制,恰恰是为了让自主变得可用。Claude Code 通过约束来实现这一点,OpenCode 通过开放控制面来实现这一点,OMO 则试图通过更重的内部“操作系统”来实现这一点。三者一起,几乎已经把这一光谱画完整了。

Book: Claude Code VS OpenCode: Architecture, Design and The Road Ahead 章节: 第13章 — 架构哲学对比 Model: openai/gpt-5.4 Generated: 2026-04-01 Token Usage: 当前API环境不可见

13.4 通用 vs 专用

本章最后一个维度,是 通用性(generality)专用性(specialization) 的张力。所谓通用系统,是指它试图面向更广的人群、更多任务、更多环境,在不做太深定制的前提下保持可用;所谓专用系统,则是主动为某一类用户、某一类场景、某一种工作方式做更深度优化。在计算机系统里,这本质上对应着一个经典权衡:覆盖面更广,往往意味着局部最优能力下降;反过来,专用化越强,通常越能在小范围内做到更高性能。

Claude Code 更接近一种 商业层面的通用性。Anthropic 并不是只为 AI Infra 工程师、prompt hacker 或多智能体系统设计者造工具,它面对的是一个尽可能广的开发者市场。于是,系统必须尽量标准化:默认值要足够安全,交互要足够直观,权限系统要适配大多数团队,工具语义要相对稳定,扩展机制不能复杂到只有极少数人会用。换句话说,Claude Code 想成为的是一个“很多开发者都能直接拿来用”的默认专业代理产品。

这种通用性,并不意味着它在技术层完全中立。Claude Code 显然不是模型层面的通用平台,因为它深度绑定了 Anthropic 的产品逻辑、模型能力与安全策略。但它在市场层是通用的。它追求的是:不同类型的开发者,都能在较低学习成本下得到一个相对一致、相对可靠、相对受控的智能编码体验。为了做到这一点,它必须在很多地方牺牲“无限可塑性”,换取更平滑的公共产品表面。

OpenCode 追求的则是另一种完全不同的通用性:技术层面的通用性。它的核心承诺不是“所有开发者都能最快上手”,而是“这个系统能承载很多模型、很多 provider、很多部署环境、很多扩展方式”。这种通用性是底座式的、平台式的。OpenCode 之所以“通用”,不是因为它屏蔽差异,而是因为它能容纳差异。

这里有一个非常重要的区分:一个系统可以在技术上很通用,但在用户群上反而偏窄;也可以在市场上很通用,但在技术边界上更收敛。OpenCode 就属于前者。它对模型、多 provider、插件、协议层都更开放,因此在系统设计上非常通用;但也正因为如此,它更吸引那些重视控制权、愿意配置、愿意理解底层的用户。Claude Code 则相反,它对大量开发者来说更像“通用入口”,但底层技术边界却更封闭。

OMO 则明显走向 专用化。它并不是要成为所有开发者的默认 Agent,更像是一个为高级工程师和高强度操作者打造的 power tool。它的专用性并不主要体现在某一个业务领域,比如前端、数据库或运维;它更像是围绕一种工作方式而专用化:多智能体委派、强过程纪律、高自治、可持续推进、可积累智慧、可不断续跑。它服务的是“希望把 Agent 当成工程执行系统来使用”的那类用户,而不是“偶尔问几个代码问题”的那类用户。

这点很关键。专用化可以针对领域、针对用户群,也可以针对工作模式。OMO 主要是第三种:围绕一种高代理性、高编排密度的工程工作流做优化。因此,它对合适的人会非常强,对不合适的人则可能显得过重。它不是设计给“所有人都舒服”的,而是设计给“少数人用起来极有杠杆感”的。

从战略角度看,通用系统往往更容易扩大分发,因为它能覆盖更多用户;专用系统则更容易在专家群体里形成高强度依赖,因为它在较小范围内做得更深。Claude Code 的商业通用性,使它具备更强的产品覆盖力;OpenCode 的技术通用性,使它具备更强的生态延展力;OMO 的专用性,则让它在高阶操作者那里形成更深的能力密度。

从架构角度说,专用系统的一个优势,是可以做更强假设。只要你知道目标用户是谁、工作方式是什么,就可以设计更锐利的抽象、更强主张的默认值、更少妥协的执行纪律。通用系统则必须保留更大的兼容空间,所以很多机制不能过于激进。比如 OMO 可以默认用户愿意接受 multi-agent 委派与 todo 纪律,而 Claude Code 无法假设所有主流开发者都喜欢这样的过程密度。OpenCode 则可以假设一部分用户重视技术控制权,因此它把大量“可塑性”留在平台层。

如果展望未来,最理想的形态可能并不是三选一,而是分层组合:底层是技术通用的平台,中间有商业通用的默认产品模式,上层再叠加面向专家的专用工作流配置。某种意义上,这三套系统已经把这张图画出来了:OpenCode 是通用底座,Claude Code 是通用产品标杆,OMO 是面向高阶工程师的专用自治层。

因此,本节最重要的结论是:通用与专用都不是抽象意义上的优点,它们只是为不同“扩展目标”服务。你到底要扩展的是用户数量、技术环境数量,还是单个操作者的任务能力上限?Claude Code 主要在扩展用户覆盖,OpenCode 主要在扩展技术底座,OMO 主要在扩展高阶任务执行深度。理解这三种“通用/专用”的不同,才可能真正设计出下一代 Agent。

Book: Claude Code VS OpenCode: Architecture, Design and The Road Ahead 章节: 第14章 — 工具系统深度对比 Model: openai/gpt-5.4 Generated: 2026-04-01 Token Usage: 当前API环境不可见

14.1 工具数量与覆盖度

比较 AI Coding Agent 时,最容易拿来量化的指标之一,就是工具数量。表面看上去,这个数字似乎已经能说明很多问题:OpenCode 大约 20 个核心工具,OMO 扩展到大约 26 个,而 Claude Code 在所分析版本里大约达到 61 个。可是,工具数量其实是一个非常容易误导人的指标。工具更多,未必代表能力更强;它同样可能意味着功能碎片化、命名膨胀,甚至产品面失控。事实上,现代 Agent 设计里越来越清楚的一条经验是:臃肿的工具集,本身就是一类主要失败模式。

为什么工具膨胀危险?因为每一个工具,不只是增加一种能力,也同时增加了一层决策分支。模型不仅要知道“能不能做”,还要额外判断“该选哪个工具”“参数怎么填”“这个结果和另一个相近工具有什么区别”。随着工具数量上升,代理的规划空间会迅速扩大,误用概率也会上升。换句话说,工具数的成本不是线性增长,而是会带来 decision complexity。这个词可以理解成“决策复杂性”:选项越多,错误路径也越多。

OpenCode 的工具数量相对克制,体现出一种比较有纪律的平台设计观。它的工具覆盖了一个编码 Agent 的基本必需动作:文件系统访问、内容搜索、补丁式修改、Shell 执行、Web 获取、MCP 相关能力、以及核心会话交互。这个覆盖面已经足够让系统完成大量真实任务,但又没有大到让“工具菜单本身”变成架构主体。也就是说,OpenCode 更偏向一种 compositional coverage:用一组中等数量、边界清晰的原语,通过组合去完成很多工作流。

OMO 比 OpenCode 多出来的那几类工具,背后的动机也不是简单堆功能。它从大约 20 个增长到 26 个,主要不是为了横向覆盖更多外部环境,而是为了纵向增强编排能力。后台任务管理、todo 跟踪、skill 加载、session 检索、AST 感知搜索与改写、更细粒度的 LSP 操作、智能体委派,这些都在服务同一件事:让系统更适合高自治、长链路、可续跑的工作流。也就是说,OMO 的扩展不是泛化式堆叠,而是围绕其自治操作模型做垂直加深。

Claude Code 的 61 个左右工具,则显示出另一种策略。作为商业产品,它面对的是更广泛的开发场景,因此工具面也更宽:浏览器相关能力、REPL 执行、显式消息传递、任务协调、权限感知的 shell/file 操作,以及一系列产品内建的实用工具。这样的工具集确实可以减少用户依赖外部插件或手工扩展的频率,让产品显得更完整、更自洽。但问题也随之而来:覆盖度什么时候会从“完整”滑向“过载”?

这个问题的答案,不在数量,而在 coverage quality。也就是:这些工具能否构成一个高质量、可组合的“基底集合”。这里可以借用数学里的 basis set 概念。它原本指一组能够通过组合生成更大空间的基础元素。放到工具系统里,就是:工具不一定很多,但应该有高复用性、高组合价值。OpenCode 在这一点上表现最好,它的工具更像通用原语。Claude Code 更强调开箱即用的便利性。OMO 则介于两者之间:保留基础原语,同时额外加入适合自治编排的专门操作符。

还可以再引入一个区分:horizontal coveragevertical coverage。横向覆盖,指的是跨不同任务类型的能力广度,比如文件、shell、web、委派、消息、网络服务等;纵向覆盖,则是指某一领域的深度,比如代码智能或编排能力。Claude Code 更像是在做横向广覆盖,因为它要支持主流开发者的多样工作流;OMO 更偏纵向加深,尤其在自治与组合层;OpenCode 则试图维持一种平台级的中间平衡。

因此,“工具越多越好”通常是错的。工具过多,会让模型选择困难,容易催生大量低价值的一次性工具,增加提示词开销,也提高上下文窗口的负担。这里的 prompt overhead 很关键:每个工具定义都要占用一部分上下文。如果几十个工具彼此只差一点点,那么模型就会浪费大量 token 去理解那些本不该成为认知负担的细微差别。反过来,工具太少也不行,因为会逼着系统绕远路、拼凑替代方案,导致能力下限过低。真正的艺术,在于找到那个“最小但足够强”的工具面。

从这个角度看,三套系统其实分别在回答三种不同问题。OpenCode 在问:一个开放平台,最少需要什么样的工具基底,才能足够强?OMO 在问:如果目标是极端自治编排,还必须增加哪些工具才合理?Claude Code 在问:一个商业产品,为了让用户感觉完整且自洽,到底需要多宽的内建工具面?由于问题不同,数字自然也不会一样。

所以,本节最重要的结论是:工具数量可以统计,但不能停留在统计。真正应该看的,是工具集是否清晰、是否易组合、提示词成本是否合理、以及新增工具到底是在减少还是增加决策负担。数量只是粗糙代理指标,真正更重要的,是代理能否以较少混乱稳定完成真实任务。从这个标准出发,一个纪律良好的 20 工具系统,完全可能优于一个噪声很大的 60 工具系统;而一个小心扩展到 26 工具的编排层,也可能在长任务自治上超过前两者。

Book: Claude Code VS OpenCode: Architecture, Design and The Road Ahead 章节: 第14章 — 工具系统深度对比 Model: openai/gpt-5.4 Generated: 2026-04-01 Token Usage: 当前API环境不可见

14.2 独特工具

真正能暴露一个工具系统“灵魂”的,往往不是那些所有平台都有的通用工具——read、edit、grep、bash、web——而是那些只有它特别重视、特别愿意提升为一等公民的 独特工具。独特工具之所以重要,不是因为别人技术上做不出来,而是因为一个系统愿意把某个能力直接做成工具,就说明它认定这类行为在自身架构里足够核心,不该只是附属技巧。换句话说,独特工具就是系统设计意图最直接的指纹。

对 OpenCode 来说,最有代表性的独特工具之一是 apply_patch。乍看之下,它只是一个“修改文件”的便捷形式;但从工程视角看,apply_patch 的意义非常大。它不是让 Agent 粗暴地重写整个文件,也不是逼着模型用很多微小文本编辑一步步改动,而是允许系统用结构化 diff 的方式描述变更:新增、删除、更新、移动。这个设计非常贴近程序员真实的工作认知。工程师思考变更时,本来就是以 patch 和 diff 的方式在理解“哪里变了、为什么变、影响范围是什么”。因此,apply_patch 本质上体现的是 OpenCode 对“代码原生变更表示”的偏好,而不是把代码文件仅仅当作普通文本。

OMO 的独特工具则更鲜明地指向另一个方向,其中最值得注意的是 AST-grep 搜索与替换工具。AST 是 Abstract Syntax Tree(抽象语法树),也就是编译器或解析器在读取源代码后构建出来的结构树。普通文本搜索只能看到字符串;AST 感知搜索看到的是“程序结构”。这意味着,系统不只是查找某几个字符,而是能匹配函数调用、导入语句、声明节点等语法层面的模式。这一点非常关键,因为很多 Agent 的代码修改失败,本质上都来自脆弱的字符串级操作:看起来搜到了,实际上语义不对;看起来替换了,实际上误伤了无关结构。AST 工具则大幅提升了结构级精度。

更进一步说,OMO 之所以强调 AST-grep,不只是为了“搜索更准”,而是因为它把编码 Agent 看成一个应该拥有更强代码理解原语的工程执行器,而不是仅仅会读写文件的聊天界面。所以,OMO 的独特工具大多围绕“动作深度”做增强:session 管理、后台任务输出、智能体创建、todo 持久化、AST 改写、更细粒度的 LSP 操作等等。这些工具的目标并不是让系统看起来花哨,而是让它在长链路自治任务里少依赖脆弱推断、多依赖结构化能力。

Claude Code 的独特工具则透露出完全不同的产品取向。WebBrowserTool 说明 Anthropic 把浏览器介导的交互视为原生工作流的一部分,而不是附加插件。REPLTool 则说明它非常重视交互式代码执行。REPL 是 Read-Eval-Print Loop 的缩写,即“读取—求值—打印循环”,是许多编程语言里的交互式执行环境。它和普通 shell 命令不一样:REPL 更适合快速试验、逐步求值、持续观察运行状态,是一种更贴近编程思维的执行模式。再比如 SendMessageTool,它直接把“消息传递”变成了显式能力,这通常意味着系统把跨上下文协作、跨代理协调视为值得产品化的一类基本操作。

这些 Claude Code 独特工具很能说明问题。它们不是单纯加几个功能点,而是在宣告:浏览器使用、交互执行、消息协调,不应该依赖外围拼装,而应该被吸收进产品核心。这完全符合 Claude Code 的整体哲学——做一个更完整、更自洽、更开箱即用的商业产品。

如果换个角度看,每个独特工具其实都编码了一组隐藏假设。apply_patch 假设“结构化 diff 是工程修改的优先表示”。AST-grep 假设“代码应该先被作为语法结构处理,而不是先被当纯文本处理”。WebBrowserTool 假设“浏览网页与软件工程是内在关联的工作流”。 REPLTool 假设“交互式求值循环是一类值得单独抽象的能力”。SendMessageTool 则假设“代理之间或上下文之间的消息协调足够常见,值得成为一等公民”。

这些假设一点都不小。每增加一种独特工具,就等于给代理增加了一种新的思维路径。只有 bash 和文本编辑的系统,会自然把问题倾向于过程化、通用化地处理;有 AST 工具的系统,会更倾向于结构化代码推理;有显式消息传递的系统,则更容易发展出编排型行为。因此,独特工具不只是“能力补丁”,它还在塑造系统可表达的认知风格。

当然,独特工具只有在“真正值得”时才有价值。一个特别小众、很少用的工具,往往只会膨胀动作空间;一个高频、高价值、用通用原语又很难优雅表达的工具,才真正值得提升为独立能力。OpenCode 的 apply_patch 值得,因为 patch 是软件工程中的高频原语。OMO 的 AST-grep 值得,因为结构化搜索/改写对代码任务是能力跃迁。Claude Code 的浏览器、REPL、消息工具也值得,因为它们都对应软件开发中的高频真实工作流。

因此,未来 Agent 系统里最有价值的独特工具,往往会出现在这样的位置:这个动作高频、重要、而且难以用通用原语优雅表达。共享工具定义的是下限,独特工具定义的,才是系统的性格。

Book: Claude Code VS OpenCode: Architecture, Design and The Road Ahead 章节: 第14章 — 工具系统深度对比 Model: openai/gpt-5.4 Generated: 2026-04-01 Token Usage: 当前API环境不可见

14.3 LSP 集成深度

如果说文件系统工具决定了 Agent “怎么碰代码”,那么 LSP 集成 决定的就是 Agent “在多大程度上真正理解代码结构”。LSP 是 Language Server Protocol(语言服务器协议),最初是为编辑器和语言智能后端之间的通信而设计的一套标准协议。通过 LSP,系统可以查询 definition、references、diagnostics、hover、rename、symbols 等语义级能力。当一个编码 Agent 深度接入 LSP 时,它就不再只是做文本处理,而是开始进入“语义感知”的代码导航阶段。

OpenCode 提供的是相对基础的 LSP 能力。这已经很有意义,因为哪怕只是轻量级的语言感知,也足以明显优于纯 grep + edit 模式。尤其在中大型代码库里,只有文本搜索往往很容易漏掉真实符号关系、误判 import 路径、或者只改到一个局部而忽略全局影响。OpenCode 的 LSP 集成说明它意识到了语义层的重要性,但它并没有让 LSP 主导整个系统架构。它更像是在一个通用开放平台里,把 LSP 当作一个重要但不过度扩张的能力层。

OMO 则明显走得更深。在当前工具快照里,它暴露了大约 8 个 LSP 相关工具,包括 references、rename、diagnostics、hover、definition、prepare_rename、symbol search、以及文档/工作区级别的语义检索等。这意味着,OMO 并不把“代码智能”打包成一个模糊的大黑盒,而是拆成多个更精确的操作。这样做的价值在于,Agent 可以在不同阶段调用更合适的语义工具:追踪代码流时用 definition,评估改动影响时用 references,重命名前先 prepare_rename,验证改动前先看 diagnostics。

这种细粒度设计,非常符合 OMO 的整体哲学:让 Agent 用更精确的操作去减少脆弱推断。以 rename 为例,纯文本 rename 极其危险,因为同名标识符可能存在于不同作用域、不同语言文件、甚至完全不相关的上下文里。LSP 支持的 rename 则依赖语言服务器对绑定关系和引用关系的理解,准确性要高得多。再比如 diagnostics,它允许系统在不一定跑完整 build 的情况下,先拿到结构化编译/分析反馈。在长链路自治任务里,这种能力相当于为 Agent 增加了早期告警机制。

Claude Code 看起来则走了另一条路线:它更倾向于提供一个更统一的 LSPTool 抽象,而不是把多种 LSP 操作都拆成独立工具。这是一个很典型的产品化决定。统一工具的好处是:提示词表面更紧凑,模型在工具选择时也更少面临“到底选 references 还是 symbols 还是 definition”的分支压力。换句话说,Claude Code 可能把复杂性收进了工具内部,而不是暴露给模型和用户。这种思路与它整体上追求“外部更简单、内部更整合”的设计是一致的。

两种做法各有利弊。OMO 的多 LSP 工具设计,优点是显式、精确、可检查,适合高纪律编排。Claude Code 的统一 LSPTool,优点是抽象层级更高、工具表面更紧凑、产品体验更平滑。OpenCode 则保持相对轻量,只把 LSP 作为一个重要增强层,而不试图在其上搭出完整的“语义操作系统”。三者差异,不是是否重视代码语义,而是如何把这层语义能力放进整体工具架构中。

这里可以引入一个更有解释力的概念:integration depth(集成深度)。判断一个系统的 LSP 强弱,不能只问“有没有 LSP”。至少还要看四件事。第一,breadth of operations:支持多少种不同语义查询。第二,workflow centrality:这些能力在代理工作流里是边缘辅助,还是日常核心步骤。第三,granularity of access:是一个总入口,还是多个锋利的小工具。第四,fallback discipline:当 LSP 可用或不可用时,系统是否知道什么时候优先走语义路径,什么时候退回文本路径。

按这个标准看,OMO 在这三者里呈现出最深、最显式的 LSP 集成。OpenCode 把 LSP 作为有价值的增强能力,但仍保持平台级克制。Claude Code 很可能内部也有很深的语义集成,只是它更愿意把这些能力包装进统一的产品接口里。二者差异不在“有没有深度”,而在“深度是公开拆分,还是内部折叠”。

更广泛地说,这个对比反映了未来编码 Agent 的一个趋势:纯文本工具足以处理小任务或一次性任务,但代码库一旦变大,纯文本方法就会迅速变脆。语义工具——LSP、AST、静态分析、诊断器——会成为提高可靠性的关键。但与此同时,暴露过多过细的语义工具,也可能制造新的选择负担。因此,设计挑战并不是“要不要语义层”,而是如何在足够强的语义能力与足够清晰的工具表面之间找到平衡。

从长期看,最强的编码 Agent 很可能都会走向多层语义组合:LSP 负责符号与引用,AST 负责结构保持式变换,diagnostics 负责早期反馈,build/test 负责最终验证。OpenCode、OMO、Claude Code 都在朝这个方向前进,只是它们暴露这些层的方式不同。而这种“暴露方式”的不同,本身就是最能体现三者架构哲学差异的地方之一。

Book: Claude Code VS OpenCode: Architecture, Design and The Road Ahead 章节: 第14章 — 工具系统深度对比 Model: openai/gpt-5.4 Generated: 2026-04-01 Token Usage: 当前API环境不可见

14.4 工具组合模式

真正成熟的工具系统,不能只看“单个工具能做什么”,而要看这些工具能不能被稳定地 组合(composition) 成更高阶的工作流。所谓工具组合,就是把多个小操作拼成一条可重复、可迁移、可积累经验的执行路径。软件工程中的真实任务几乎从来不是一步完成的,它通常包含:调查、规划、检索、阅读、修改、验证、委派、汇总、续跑。于是,工具系统的上限,往往不取决于某一个最炫的工具,而取决于工具之间能否形成可靠的组合模式。

这里最关键的变化,是 Task tool 逐渐从普通能力工具,升级成了“编排原语(orchestration primitive)”。所谓原语,就是构建更复杂行为的最小基础单元。传统编码 Agent 往往把工具理解为“访问外部世界的方法”:读文件、跑 shell、搜代码、改文本。但新的系统开始把一部分工具理解成“创建工作流结构的方法”。Task tool 不再只是去操作环境,它本身就是在创建一个新的工作单元。这个变化非常重要,因为它意味着工具层开始承担控制层的职责。

OMO 在这方面最典型。它的后台代理创建、任务输出读取、session 延续、todo 纪律,这些能力共同构成了一种非常清晰的组合模式:主代理把子问题委派出去,自己继续处理别处,稍后再回收结果并整合。这已经不是“几个工具偶然连起来”,而是一套以工具为载体的编排机制。也正因此,OMO 的工具看上去常常不像传统助手的工具——它们并不主要服务于本地小动作,而是在服务于过程结构本身。某种意义上,OMO 的工具系统已经部分承担了“Agent 操作系统”的角色:有的工具负责创建工作,有的负责跟踪状态,有的负责取回结果,有的负责维持上下文连续性。

Claude Code 也在朝这个方向发展,只是表达方式更产品化。像 SendMessageTool 这类工具,本质上是在承认:大任务不应该都压缩成单线程的单上下文执行,系统需要显式的消息传递、任务协调和上下文切换机制。差别在于,Claude Code 更倾向于把这些组合模式包装进统一且相对平滑的产品体验里,而 OMO 则更直接地把编排控制面暴露给模型和高级操作者。

OpenCode 的位置还是更基础一些。它提供了良好的组合基底:文件、搜索、编辑、bash、patch、web、MCP 等原语都可以被串成工作流,但宿主本身没有像 OMO 那样在工具层上形成重度编排教义。它更像一个可以支撑组合的通用底座,而不是直接替你定义组合范式。也正因为如此,OMO 才能在 OpenCode 之上再造一层更高阶的工具组合体系。

另一种非常关键的组合模式,是 Skill tool 的升级。Skill 在早期往往被理解成“提示词模板”或“任务说明书”,但在更成熟的系统里,它开始演化成一种打包的操作知识。也就是说,skill 不只是告诉模型“说什么”,更是在告诉模型“这类问题通常怎么做、按什么步骤做、需要注意什么约束”。如果 skill 再进一步绑定嵌入式 MCP,那么它甚至会连同外部能力一起打包进来。此时,工具组合就不再是“工具 + 工具 + 工具”,而变成了 工具 + 程序性记忆(procedural memory)

程序性记忆这个说法,指的是“会做某件事的方法知识”,不同于“知道某件事实”的陈述性知识。把 skill 做成程序性记忆模块,意味着系统可以把专家经验沉淀成可复用工作流,而不必把每一种行为都硬编码进核心。OMO 在这一点上尤其明显:skill 可以从简单 prompt 模板演变成更复杂的操作模块,里面有步骤、约束、流程、甚至嵌入的 MCP 服务。这样一来,skill 已经不只是“文档”,而是在变成一种微型运行时:一部分是说明书,一部分是策略,一部分是能力扩展。

工具组合模式还揭示了另一条重要原则:最好的工具系统,应该尽量减少对某一个单独工具的绝对依赖,而是鼓励形成稳定的复用路径。 比如,一个稳健的代码修改流程,可能经常复用“search → read → analyze → patch → diagnostics → test”;一个更高级的编排流程,则可能是“spawn task → continue local work → retrieve output → integrate results → verify”。当这种模式变稳定时,系统能力就不再依赖某一个孤立工具,而是依赖一组高复用组合。

这也解释了为什么前面我们反复强调“工具膨胀是失败模式”。工具太多、太碎,会让组合反而更困难,因为动作空间被人为切得太细,模型很难形成稳定路径。工具适度、边界清晰,才更利于组合。真正高级的工具设计,不是不断发明彼此孤立的新工具,而是设计那些能够彼此协作、产生高阶行为的工具关系。

从长期看,编码 Agent 的工具系统很可能会越来越像分层操作环境。最底层是原始能力工具:文件系统、shell、搜索、web。上面一层是语义工具:AST、LSP、diagnostics。再往上是编排工具:Task、session 管理、消息传递、续跑控制。旁边还有 skill,作为可复用的程序性知识模块。OpenCode 提供扎实底层,OMO 在其上做出浓重的编排与 skill 层,Claude Code 则把这些模式以更商业化、更产品化的形式整合进体验中。

因此,比较工具系统时,最关键的问题已经不再是“你有多少工具”,而是“你的工具能稳定组合成什么样的工作流”。真正决定 Agent 上限的,不是工具名录,而是组合能力。而在这一点上,Task 与 Skill 从普通工具升级为编排原语,可能正是这一代编码 Agent 架构里最值得注意的变化之一。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第15章 — 智能体编排对比
Token用量: 约 4,900 input + 1,260 output

15.1 编排模式分类

很多人一提“多智能体系统”,就默认它们差不多:无非是多开几个 agent 并行干活。但真正重要的,不是“数量”,而是任务、权限、上下文、结果整合是如何流动的。如果不把这些结构分开讨论,所谓“支持多智能体”其实没有太多分析价值。

在 OpenCode、Oh-My-OpenCode(OMO)和 Claude Code 之间,最有代表性的五种编排模式分别是:Orchestrator-Worker(编排者-执行者)Pipeline(流水线)Swarm(群体协作)Mesh(网状协作)Hierarchical(层级式)

先看 Orchestrator-Worker。这是一种最容易理解的模式:一个主智能体负责拆解问题、分派子任务、回收结果、做最终整合。OMO 最明显地采用了这种模式。它有父会话、有 delegate-task、有后台子智能体、有结果通知机制,整个系统的感觉就是“主控智能体带着一批工人智能体工作”。Claude Code 也支持类似结构,尤其是在 Task 工具、后台任务和子代理能力上。但 Claude Code 把这件事做得更产品化,用户感知到的是“可以派任务出去”。OpenCode 本身则更偏底层能力提供者:它支持 agent、subtask、command,但不强加一整套重监督编排体系。

再看 Pipeline。Pipeline 不是“很多智能体一起讨论”,而是“工作按阶段流动”。在计算机系统里,流水线强调的是阶段化处理:上一阶段输出成为下一阶段输入。OpenCode 天然带有这种味道,因为它的核心就是 ReAct 风格执行循环:理解、调用工具、观察结果、继续推进。OMO 则把流水线推进到了策略层:消息变换、工具前置守卫、续跑逻辑、通知逻辑、上下文注入逻辑,这些都像是一道道处理工序。Claude Code 也很像 Pipeline 系统,只不过它更多把流水线放在权限、安全、压缩和产品交互层。所以三者都使用 Pipeline,但 Pipeline 所在的层不一样:OpenCode 的流水线更像执行骨架,OMO 的流水线更像策略中间层,Claude Code 的流水线更像商业产品中的安全与体验流程。

第三种是 Swarm。这个词不是传统教材里常见的标准术语,在这里可以理解为“群体式并行协作模式”:多个智能体并行探索,中心控制相对较弱,更强调广度覆盖而不是严格阶段顺序。Swarm 特别适合大仓库搜索、多个方案并行尝试、外部资料快速扫描这类任务。三者里,OMO 最接近真正可用的 swarm。因为它明确支持后台并发、按模型/提供商限流、角色化子智能体,以及结果回收。Claude Code 也能做出某种 swarm 效果,但更像是“受控的后台并行助手”。OpenCode 单体本身则不太具有 swarm 倾向,更多是你可以基于它搭,而不是它天生朝这个方向设计。

第四种是 Mesh。这个词也需要解释。Mesh 指“网状结构”,在 agent 语境里就是多个智能体之间横向交流,而不是所有信息都必须经过一个总控节点。Mesh 很灵活,但也很难控,因为横向传播容易带来重复、冲突和上下文漂移。严格说,这三个系统都不是纯粹的 mesh。它们都更偏有中心的编排,而不是完全去中心化。不过 OMO 有一些弱 mesh 特征:前面子智能体产出的智慧、经验、摘要,可以被后面的智能体继承,这种“通过共享智慧间接互相影响”的方式,形成了一种非直接对话的网状耦合。Claude Code 在多个 task 汇总回主上下文时,也会出现一点点类似 mesh 的影子。OpenCode 则更像提供底层网络接口,但不定义网络拓扑。

第五种是 Hierarchical,即层级式编排。层级式不是简单的主从,而是多个抽象层级同时存在:例如上层做计划,中层做协调,下层做执行或验证。这类模式特别适合复杂工程问题,因为“规划”“搜索”“编辑”“审计”并不处在同一个抽象层。OMO 是三者里最强的层级式系统:它不仅有多角色 agent,还有语义类别、hook 约束、续跑机制、工具权限限制。Claude Code 也有层级性,但更柔和:主 agent 可以派任务、收结果、再次上升到总控角色。OpenCode 仍然更像层级结构的基础设施,而不是层级本身。

可以把它们简单概括成一张表:

模式OpenCodeOMOClaude Code
编排者-执行者基础支持很强,明确外显很强,但更产品化
流水线核心执行方式核心策略方式核心安全/体验方式
群体协作原生较弱三者最强中等
网状协作主要靠开发者自建通过智慧共享呈现弱形态通过任务汇总呈现弱形态
层级式可做但不强调一等公民存在但较松散

这一章最重要的结论,不是“谁支持多智能体更多”,而是:谁把编排拓扑做成了系统级设计对象。OpenCode 的优点是简洁、开放、容易改造;它像一个很好的底座。OMO 的优点是把编排本身抬升成运行时能力,不只是“能派任务”,而是“能持续监督、并行、限制、整合”。Claude Code 则介于两者之间:它既承认多智能体的价值,又尽量把复杂性包进产品体验里。

所以,真正好的比较方式,不是问“它是不是多智能体”,而是问:“它优化了哪种编排模式?为了什么目标?付出了什么成本?”

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第15章 — 智能体编排对比
Token用量: 约 5,100 input + 1,300 output

15.2 单智能体 vs 多智能体

“一个强模型单干”与“多个智能体协作”之间的争论,已经成了 2025–2026 年 agent 设计里最核心的话题之一。问题的关键并不是单智能体能不能完成任务。很多时候它当然能。真正的问题是:把认知过程拆散到多个上下文里,带来的质量提升,值不值得额外的 token 成本、等待时间和编排复杂度?

Anthropic 给过一个非常有代表性的结论:multi-agent Opus+Sonnet 系统达到 90.2%,优于单个 Opus agent。这个数字之所以重要,不只是因为它高,而是因为它证明了一件事:在复杂任务上,更好的编排结构可以弥补甚至超越单线程推理的上限。换句话说,scaffolding(脚手架式系统结构)不是装饰,它会直接改变智能体的能力边界。

为什么多智能体会更强?根本原因是单个上下文需要同时承担四类不同工作:理解任务、搜索信息、执行修改、自我校验。这些工作之间会互相干扰。搜索阶段引入大量噪声,执行阶段占据局部细节,校验阶段又容易被前面自己的推理路径绑架。多智能体的价值,就在于把这些认知负担拆开:有人专门搜索,有人专门规划,有人专门执行,有人专门验证。

OpenCode 的风格比较接近“强单智能体 + 可扩展底座”。它的好处是清晰、节省、容易理解。一个 session 里调用工具、观察结果、继续推进,往往已经足够解决中小型仓库中的大量任务。单智能体模式的优势非常真实:token 成本低、结果链路短、调试容易、责任清晰。它失败时,也更容易知道问题出在哪一段。

OMO 的判断则更激进一些。它认为,单智能体在简单任务上确实足够,但在大仓库搜索、复杂依赖分析、需要外部资料核对、长周期执行这类任务上,单上下文很容易陷入“既要搜索,又要执行,还要记住所有中间状态”的困境。所以 OMO 会更积极地进入多智能体模式:Explore 去找,Oracle 只读分析,Librarian 查外部资料,父会话负责整合。这是一种典型的“用更多 token 换取更稳定问题分解”的策略。

Claude Code 走的是中间路线。它没有像 OMO 那样把多角色编排做得那么外显和制度化,但它明显承认多智能体/子任务是必要能力。DreamTask 这类后台任务体验,实际上改变了用户与系统的关系:不再只是“你现在回答我”,而是“你去做一件事,稍后带着结果回来”。这已经是协作式工作流,而不是纯聊天。

当然,成本问题避不开。多智能体系统非常容易达到 10 倍甚至 15 倍 token 成本。原因很简单:每个子智能体都有 prompt、上下文摘要、任务说明、结果回传,父智能体还要阅读、整合、校验。如果再加上并行探索、重复验证、失败重试,成本会进一步放大。

那什么时候值得付这 15 倍成本?通常有五种情况。

第一,搜索空间很大。如果相关信息散落在几十个文件甚至多个模块里,单智能体串行搜索的成本可能更高,而且容易漏。

第二,任务类型异质。这里“异质”是一个教材里常见但在日常语境不一定直观的词,意思是“性质不一样”。外部资料查找、代码修改、架构推理、安全审查,本来就是不同类型的工作,把它们塞进一个上下文会互相污染。

第三,错误代价高。例如权限系统改造、安全补丁、发布前修复,这类任务宁可更贵,也要更稳。

第四,任务时间跨度长。长任务会积累很多不再有用的局部信息,让单智能体上下文越来越浑浊。

第五,子任务确实可以并行。如果多个子任务彼此独立,多智能体收益会很明显;如果它们高度耦合,那并行只会制造协调成本。

反过来讲,在以下场景,多智能体往往不值:小改动、单文件 bugfix、很明确的重命名、边界清晰的格式修复。这些任务如果硬上多智能体,常常只是“编排表演”——看起来很高级,实际上在烧 token。

多智能体还有治理问题。角色权限怎么定?什么时候停止?结果如何合并?如何避免两个 agent 做重复劳动?OMO 在这方面更系统,它用角色限制、后台并发上限、hook 和流程纪律来约束。Claude Code 更像把这些治理逻辑做进产品交互。OpenCode 则更多把责任交给开发者和扩展层。

所以,真正有价值的结论并不是“单智能体好”或“多智能体好”,而是:系统应当具备按任务结构自适应升级的能力。默认用单智能体处理便宜、简单、边界清晰的任务;当任务表现出高搜索广度、高风险、高异质性、高并行性时,再升级到多智能体。Anthropic 的 90.2% 结果告诉我们:多智能体可以显著更强。但它没有告诉我们应该把每一个任务都变成多智能体。

最好的系统,不是永远喜欢派很多 agent,而是知道什么时候不需要。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第15章 — 智能体编排对比
Token用量: 约 4,700 input + 1,190 output

15.3 智能体专业化

多智能体系统真正的分水岭,不在于“有几个 agent”,而在于这些 agent 是否真的专业化。如果只是复制出多个同样的助手,那只是并发,不是分工。只有当不同智能体拥有不同职责、不同上下文边界、不同工具权限、不同信任等级时,系统才从“多个副本”变成“一个团队”。

OpenCode 本身提供了专业化的基础材料:可以定义 agent、可以选模型、可以接命令、可以配工具。但它整体仍然偏通用平台思路。也就是说,OpenCode 可以让你做专业化,但不会强制你这么做。角色边界更多是开发者约定,而不是宿主强约束。

OMO 则明显更进一步。它把角色专业化做成了系统设计的一部分。最典型的三个角色就是:Oracle、Explore、Librarian

Oracle 是只读角色。这个设计表面看只是一个权限限制,实际上非常关键。很多 agent 的失败,不是因为它不会分析,而是因为它在分析还没完成时就开始改东西。Oracle 的意义就在于:它可以查、可以想、可以总结,但不能写。这样一来,它更像审计员、代码评审员、仓库导览员,而不是执行者。对于问题定位、架构理解、风险审查,这种只读角色极其有价值。

Explore 则是“快速内部探索者”。它不是为了产出最终报告,也不是为了承担完整执行,而是为了高效率地在仓库内部找线索、扫路径、定位候选文件、汇总发现。对大仓库来说,搜索本身就是一项重劳动。如果让主执行 agent 一边推进任务,一边自己全仓搜索,它的上下文预算很容易在“找路”阶段就消耗掉。Explore 的作用就是把“搜索成本”从主上下文中剥离出去。

Librarian 处理的是外部知识。这个角色的意义在于它维持了“仓库内事实”和“仓库外事实”的边界。代码里有什么,是一回事;官方文档、网络资料、API 外部行为是另一回事。把外部知识检索交给 Librarian,有助于父智能体判断证据来源,也能减少把外部经验误当成本地事实的风险。

真正高明的地方,不只是 prompt 不同,而是 prompt + 权限约束 一起生效。OMO 的角色化不是“请你扮演 Oracle”,而是“你是 Oracle,并且你确实不能做某些事”。这很重要,因为 LLM 的行为具有机会主义倾向:如果工具开着,模型常常会顺手多做一步;如果权限没关死,再严格的提示词也可能慢慢漂移。能力边界比文字描述更硬。

这种“权限支撑的专业化”能防止几个非常典型的问题。

第一是越权扩张。搜索 agent 本来只该找资料,结果因为工具权限没控住,顺手就改了代码。

第二是上下文污染。探索阶段往往包含大量未验证猜测。如果同一个 agent 又负责最后落地执行,这些猜测就可能变成行动依据。

第三是责任模糊。当一个角色天然是只读的,或者天然只负责外部资料时,父智能体和人类开发者就更容易判断:这份结果到底应不应该被直接信任。

Claude Code 也支持一定程度的专业化,比如不同 task、不同 agent 定义、不同工作线程,但它通常更注重产品体验的一致性,而不是像 OMO 那样强烈地命名和制度化角色。换句话说,Claude Code 的专业化更“柔性”,OMO 的专业化更“制度化”。

从更一般的系统设计角度看,专业化出现的条件其实和人类组织很像:当“频繁切换工作模式”的成本,高于“做任务分工和结果整合”的成本时,专业化就值得。搜索、规划、执行、验证、外部检索,本来就是不同心智模式。让一个上下文在这些模式之间来回切换,既贵又容易乱。

当然,专业化不是越多越好。角色太多会导致 handoff 成本上升。这里的 handoff 可以理解为“任务交接成本”——一个角色把中间结果交给另一个角色时,需要重新解释背景、压缩重点、重建信任。角色边界太细,会让系统把大量 token 花在交接上,而不是花在解决问题上。

所以最好的设计原则不是“把所有事情都拆成专门 agent”,而是:只在失败模式不同的地方做专业化。如果某类工作最大的风险是“过早动手”,就给它只读权限;如果某类工作最大的成本是“全仓搜索”,就让它专做探索;如果某类工作最大的问题是“证据来源不清”,就给它外部知识专责角色。

从这个角度看,OMO 的 Oracle、Explore、Librarian 不是命名游戏,而是一种对 agent 失败模式的系统回应。它的核心观点是:编码智能体最容易出错的地方,不在某一个具体模型,而在把搜索、执行、验证、外部知识混在一个不受约束的上下文里。而权限约束,正是把这种观点从提示词提升到架构层的关键一步。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第15章 — 智能体编排对比
Token用量: 约 4,850 input + 1,220 output

15.4 背景任务与并行执行

并行执行对 agent 系统的影响,远不只是“跑得更快”。它同时改变两件事:一是任务完成方式,二是开发者的使用体验。一个只能前台串行回答问题的系统,本质上仍然更接近聊天工具;一个能稳定派发后台任务、跟踪状态、回收结果的系统,才开始接近真正的工作执行系统。

OMO 在这方面的设计非常明确。它支持 每个 model/provider 最多 5 个并发后台智能体。这个限制本身就说明 OMO 不是把“并发”当成无脑越多越好,而是把它当成一种需要治理的系统资源。如果没有并发上限,所谓多智能体很容易变成“高成本失控风暴”——请求爆炸、token 爆炸、上下文重复爆炸。

更关键的是,OMO 不只是支持后台执行,还把后台执行做成了可追踪、可继续、可通知的会话对象。子智能体不是“扔出去跑一下”的匿名线程,而是有 session、有 task id、有结果取回路径的工作单元。这种设计很重要,因为真正的并行不是把异步代码接上去就结束了,而是要让人和父智能体都能知道:谁在跑、跑到哪一步、出了什么结果、能不能接着跑。

Claude Code 的 DreamTask 路线,本质上也在做同一件事:把工作从前台聊天线程中解耦出来。用户不必一直坐在一个同步对话框里等模型“想完”。你可以把任务交出去,让它继续在后台工作,再回来取结果。这会明显改变产品感受:从“你现在回答我”,变成“你去做这件事,稍后汇报”。

OpenCode 则明显更同步、更朴素。它可以被扩展成更复杂的并行系统,OMO 就是最好的证明;但 OpenCode 自身并没有把后台编排作为核心体验前景化。它的优势是简洁、少状态、少生命周期复杂性。缺点则是,如果你想获得成熟的后台协作体验,需要在它之上继续搭建。

为什么并行这么重要?因为真实的软件工程任务,本来就很少是纯串行的。你完全可以一边搜索文件,一边查外部文档;一边跑测试,一边让另一个 agent 规划修复路径;甚至让多个候选方案并行探索。人类开发者本来就是这么工作的:多终端、多标签页、多线程切换。严肃的 coding agent 迟早也会走向这一点。

但并行也带来几个典型难题。

第一是重复劳动。两个子智能体可能在搜同一批文件,做同样的判断,最后把相似结论返回给父会话。OMO 的纪律里专门强调这一点:一旦委派了探索,就不要在主线程里重新做同样的搜索。否则所谓并行只是更昂贵的串行重复。

第二是结果整合成本。并行本身不创造价值,只有“并行结果能被低成本整合”时才有价值。如果每个子智能体返回的都是冗长、模糊、缺重点的报告,父智能体还得花很多 token 再做一次清洗,那并行收益就被吃掉了。

第三是上下文偏斜。这里的“偏斜”可以理解为不同工作线程看到的状态不一致。一个子智能体看到的是旧仓库状态,另一个看到的是新状态,最后结果就可能互相打架。所以后台并行尤其适合只读搜索、资料收集、候选方案探索,而不太适合多个角色同时无约束地编辑同一片代码。

第四是用户体验透明度。如果用户不知道现在有哪些任务正在跑、哪些完成了、哪些还阻塞着,那么后台执行会从“高效”变成“神秘而不可信”。所以通知机制、状态可见性、任务标识,是后台系统的必需品,不是锦上添花。

OMO 的优势在于,它把这些问题放进了编排层统一处理:并发限制、session 管理、后台通知、续跑能力、角色边界,彼此是配合设计的。Claude Code 的优势在于,它把这种能力包装成更顺滑的产品体验。OpenCode 的优势则在于,它保留了作为底座的清爽与可扩展性。

还有一个经常被忽略的点:并行执行会改变开发者的心理模型。在同步 agent 里,用户像是坐在模型脑子里陪它一步步思考;在后台型 agent 里,用户更像一个任务管理者,给它派工、追踪、回收结果。这是一个很重要的转变。它意味着 agent 不再只是回答器,而越来越像一个可以管理的执行体。

所以,背景任务和并行执行绝不是一个“高级小功能”。它们是 agent 从聊天助手走向工作系统的关键门槛。OMO 展示了它的架构版答案,Claude Code 展示了它的产品版答案,而 OpenCode 则证明了一个简洁宿主如何为这一切提供基础。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第15章 — 智能体编排对比
Token用量: 约 4,950 input + 1,260 output

15.5 智慧传递 vs 上下文隔离

智能体系统一个非常深层、但常常被表层功能掩盖的分歧,是:前一个任务里学到的东西,应该在多大程度上带到后一个任务里?

OMO 更偏向 wisdom accumulation(智慧积累),Claude Code 更偏向 context isolation(上下文隔离)。OpenCode 则基本保持中立,提供底层能力,让开发者自己决定记忆策略。

所谓“智慧积累”,不是简单地把所有历史对话一股脑塞进新上下文,而是把之前运行中形成的有用知识沉淀下来,例如:仓库里哪些文件最权威、哪些命令最容易踩坑、哪些路径危险、哪些规则经常被违反、某类任务通常应该怎么切。OMO 在这方面走得很远,它有显式的 wisdom 机制、有 continuation、有跨会话保留的运行经验。它背后的直觉非常直接:如果系统已经在这个仓库里工作过很多次,为什么每次都要重新交一遍“学费”?

这种设计的好处,是能形成复利效应。前期多花的 token,不只是换来当次任务结果,也可能变成未来任务的成本节省。系统越来越了解项目脾气,越来越早知道哪些规则容易出错,越来越快跳过重复摸索。对于长期协作型 agent,这是一条非常有吸引力的路线。

Claude Code 则更强调上下文的干净边界。它对“每个任务最好从相对干净的知识起点出发”这件事更谨慎、更重视。为什么?因为保留下来的上下文,不只是资产,也可能是污染源。仓库变了、分支变了、约束变了、先前的猜测被证伪了,但旧上下文如果还带着“看起来合理”的样子存在,就会制造一种危险的假确定性。

这里有个词值得解释:epistemic。这个词在哲学和知识论中常见,在传统 CS 教材里不算核心术语。它大致可以理解为“与知识本身及知识可靠性有关”。上下文隔离本质上是在维护一种 epistemic cleanliness,也就是“知识起点的干净度”。它不希望当前任务被过去未清洗的残留知识牵着走。

上下文隔离有几个明显优点。

第一,减少提示词藤壶。这里“藤壶”是借用海洋附着物的比喻,指那些一点点附着在系统上的历史残留:早就过时的小规则、半对半错的中间判断、旧分支上的局部结论。它们单独看不大,但累积起来会扭曲行为。

第二,更容易调试。如果一个任务出了问题,而它几乎没有继承隐性上下文,那么问题来源更容易定位。

第三,更少上下文污染。以前有用的信息,仓库一变可能就变成误导。隔离可以降低这种风险。

第四,更适合商业和企业环境。因为任务之间边界清晰、继承路径少,系统行为往往更容易解释和审计。

但隔离也有代价。它会不断重复“重新认识世界”:重新扫一遍目录,重新读一遍规则,重新定位关键文件,重新确认历史坑点。这当然更安全,但也更贵。换句话说,Claude Code 接受更多“重复学习成本”,以换取更少“陈旧知识污染风险”。

OMO 则做了相反的权衡:它更愿意承担一部分污染风险,以换取长期协作效率。它相信很多知识其实是相对稳定的,值得被沉淀成未来运行时的辅助智慧。

这个矛盾非常像经典系统里的 cache vs fresh read(缓存 vs 每次现读)。缓存快,但可能 stale(过期);每次现读慢,但新鲜。智慧积累,本质上就是一种“认知缓存”;上下文隔离,则更像坚持新鲜读取。问题不在于哪边绝对正确,而在于底层世界变化有多快,以及过期知识会造成多大伤害

理想的未来系统,大概率不会在两者之间二选一,而会做分层记忆

第一层是稳定知识,例如仓库约定、危险路径、固定构建规则、常用命令偏好。这类知识变化慢,适合长期保留。

第二层是易腐状态,例如某次探索中的假设、临时分支状态、尚未验证的线索。这类内容应该快速衰减,甚至保持任务内隔离。

第三层是验证后摘要,也就是在明确检查点产生的、可信度更高的压缩结论。它像一种带置信度的知识转移对象,比原始上下文更适合跨任务携带。

OMO 已经在朝“选择性保留”走,Claude Code 则在提醒我们“干净边界”的重要性。OpenCode 则保留了开发者自己定义记忆制度的自由。三者合起来给出的启发是:记忆从来不是越多越好,也不是越少越好。真正高级的 agent,不只是会记住,而是会带着信任标注地记住

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第16章 — 可扩展性对比
Token用量: 约 4,800 input + 1,210 output

16.1 插件系统

在所有扩展机制里,Plugin 往往是最强、也最危险的一层。强,是因为它离宿主运行时最近,能改生命周期、加工具、拦截消息、塑造行为。危险,是因为它一旦能力过大,就可能突破边界、降低可预测性、引入兼容性债务。把 OpenCode、OMO 和 Claude Code 放在一起看,三者的 plugin system 实际上代表了三种不同的可扩展性哲学。

OpenCode 的插件系统最像“真正的平台底座”。它暴露的宿主级 hook surface 不算多,但非常关键:配置注入、工具注册、消息拦截、参数/消息变换、事件处理、工具执行前后、实验性消息变换等。也就是说,它不是给你一堆零碎扩展位,而是给你少量但杠杆极高的入口。这种设计有一个明显好处:能力强,但结构还看得懂

这个特点恰恰解释了为什么 OMO 能成立。OMO 不是 fork 掉 OpenCode 后自己重写一套,而是在 OpenCode 之上,用 plugin 的方式长出了一整层编排运行时。这件事非常重要,因为它证明了 OpenCode 的 plugin surface 不是只能做一些“小插件”,而是真的可以承载二级系统。工具注入、背景任务、agent 编排、兼容层、41-hook 策略体系,全部都是从这个入口长出来的。

Claude Code 也有插件能力,但风格明显更商业化、更克制。它不是要让扩展作者尽情重塑宿主,而是要在“可扩展”和“产品边界稳定”之间找平衡。商业产品需要支持性、可维护性、安全承诺和企业可信度,所以它的插件哲学通常不会鼓励第三方在核心生命周期里大范围接管逻辑。

三者可以概括成:

系统插件定位
OpenCode宿主级扩展底座
OMO以插件形式实现的编排运行时
Claude Code受控的产品级扩展层

OpenCode 的优点,是给开发者足够大的工程杠杆。你不是只能加点 UI 装饰,而是真的可以改变系统如何工作。这非常适合开源生态和高级使用者。缺点是,宿主把很大责任交给了插件作者:如果插件写得烂,整个体验都会变差。

OMO 则把这种开放性推到极致。它证明 plugin 不只是“给宿主加点新功能”,而是可以成为二次平台化的入口。换句话说,OMO 的存在说明:一旦插件能力足够强,插件本身就不再只是扩展,而会长成“套在宿主之上的第二层系统”。这是一种非常有力量的架构现象。

Claude Code 的做法更像商业产品应有的姿态:开放,但不能失控;允许扩展,但不让扩展轻易越过主产品的安全和体验边界。从产品工程角度看,这种克制是合理的。因为企业用户买的是稳定性,不是“每个插件都能把系统改得面目全非”。

这里有一个值得借用的分析框架:host sovereignty(宿主主权)。这个词不是教科书里的固定术语,可以理解为“宿主对运行时最终控制权保留多少”。如果宿主主权很强,插件只是客人;如果宿主主权让渡很多,插件就成了共同治理者。OpenCode 明显更愿意让插件进入共同治理。OMO 则证明这种让渡可以走到多远。Claude Code 则更强调宿主保有主权。

这种差异直接影响生态形态。OpenCode 的插件更容易成为“架构工具”;OMO 的插件层已经变成“行为操作层”;Claude Code 的插件更像“受控功能扩展”。前两者更有开源创新爆发力,后者更有产品一致性和支持友好性。

但别忘了,插件能力越强,版本耦合风险越大。这里的“版本耦合”指插件依赖宿主某些细微行为,一旦宿主升级,插件就可能在不起眼的地方悄悄失效。商业产品通常会缩小插件面,来降低这种风险;开放平台则更愿意承受它,以换取创新空间。

所以,比较插件系统,不能只看“能不能装插件”,而要看:它给插件多少杠杆?宿主还能保留多少主权?插件出问题时爆炸半径多大?OpenCode 在杠杆上最激进,OMO 在二次架构上最惊艳,Claude Code 在控制风险上最谨慎。这三者都成立,只是服务的战略目标不同。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第16章 — 可扩展性对比
Token用量: 约 4,650 input + 1,170 output

16.2 技能系统

Skill 是一种非常特别的扩展机制。它不像 plugin 那样直接改运行时,也不像 hook 那样拦截生命周期。Skill 更像是把“知识、流程、经验、规范”注入给 agent。简单说,Plugin 改的是机器,Skill 改的是机器如何做事。

OpenCode 的 skill system 很优雅,原因在于它把技能定义成一种极轻量的内容资产:一个带 frontmatter 的 SKILL.md 文件就够了。目录发现也做得很开放:支持全局目录、项目目录、配置目录、显式路径,甚至远程 URL。这个设计有一个很强的优点——门槛低。写一个技能,不需要打包发布,不需要写代码,不需要理解复杂 SDK,只需要写清楚“这类任务应该怎么做”。

更重要的是,OpenCode 在技能发现上有明显的兼容性野心。它不只搜索自己的目录,还搜索 .claude/skills/.agents/skills/。这意味着它并没有把 skill 当成封闭生态里的私有格式,而是把它当成一种可以跨工具迁移的知识资产格式。这一点非常聪明,因为可移植性会降低用户迁移成本,也会放大整个 skill 生态的规模。

OMO 继承了这套能力,但并不满足于“技能能被找到”。它进一步让技能在运行时活起来。通过 category reminder、runtime 注入、skill-embedded MCP、自动命令触发等机制,Skill 不再只是静态文档库,而成为编排过程中的活跃参与者。这是 OpenCode 和 OMO 在技能层最大的区别:OpenCode 让技能可发现,OMO 让技能可运作。

Claude Code 也非常重视 skill,因为对于商业产品来说,Skill 是一个非常安全、非常可治理的扩展层。相比可执行插件,markdown 型技能更容易审核、更容易分享、更容易在团队里协作维护。它们可以承载组织规范、岗位流程、领域知识,而不必给外部代码太高权限。

三者对比可以概括为:

系统技能哲学
OpenCode轻量、可移植的知识资产
OMO被编排系统激活的知识资产
Claude Code面向产品工作流的安全行为扩展

为什么 skill system 这么关键?因为大模型很多时候不是缺“通用智力”,而是缺“本地流程知识”。模型可能很懂编程,但不知道这个仓库该先跑哪个脚本,不知道哪些目录不能碰,不知道这个团队把哪条测试当成硬门槛。Skill 恰恰擅长承载这种局部、具体、组织化的 know-how。

这里的 know-how 也值得解释。它不是某个严格教材术语,而是工程实践里常用的词,指“知道怎么做的经验性知识”。这类知识通常很难浓缩进几条配置项里,却非常适合放进 skill。

从治理角度看,Skill 还有一个巨大优势:可审阅性强。Markdown 是人类可读的,frontmatter 是显式的,reviewer 很容易看出这个 skill 想教模型什么。它当然仍可能写得差、写得误导,但它的风险画像明显低于任意可执行代码。

OMO 在这之上又加了一层非常有意思的东西:skill-embedded MCP。也就是说,技能里不只是“告诉你该做什么”,还可能“带着你去调用做这件事需要的能力”。这样一来,Skill 就从纯知识资产,开始向“知识 + 能力入口”的复合对象演化。

这也引出技能系统的核心张力:发现性与过载之间的平衡。技能太少,很多组织知识永远沉睡;技能太多、注入太激进,agent 上下文就会变得嘈杂。OpenCode 通过清晰的发现层级来控制,OMO 通过类别感知和运行时提醒来控制,Claude Code 通过更产品化的调用方式来控制。

对未来 agent 平台而言,Skill 大概率会成为最重要的组织知识扩展层。它创建成本低、审阅成本低、迁移成本低,且风险远小于插件。OpenCode 展示了它的格式优雅,OMO 展示了它的运行时活化,Claude Code 展示了它在商业场景里的治理优势。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第16章 — 可扩展性对比
Token用量: 约 4,720 input + 1,180 output

16.3 命令系统

Command system 是三种扩展机制里最面向用户的一层。Plugin 面向运行时,Skill 面向知识与行为,Command 则直接面向“人怎样触发系统能力”。它把反复出现的用户意图包装成稳定入口,让复杂行为能够被一条命令复用。

OpenCode 的命令系统做得非常整洁。它把三类来源统一进同一个框架:内置命令、用户配置命令、由 MCP prompt 或 skill 自动暴露出来的命令。这个设计表面看只是方便,实际上很有深度。它意味着 Slash Command 并不是 TUI 的小装饰,而是一个连接“用户意图”和“可复用提示模板/能力入口”的路由层。

模板变量的设计也很实用。像 $1$2、`$ARGUMENTS`` 这样的参数占位,让命令可以在保持结构稳定的同时保留灵活输入。用户不需要每次重写整段提示词,只需要用命令补充必要参数即可。这降低了交互负担,也提高了重复工作流的一致性。

OMO 在 OpenCode 的基础上,把 command system 推进到了编排层。自动 slash command、类别关联触发、命令映射到专业化 agent、命令进入子任务模式,这些都让 command 不再只是“文本替换器”,而开始成为“工作流入口”。在 OMO 里,命令可以不是一句 prompt,而是一套被编排好的动作路径。

Claude Code 在命令层的另一个优势是数量和产品化程度。大量 slash commands 会让用户感觉系统好像有很多原生“动词”。这是产品体验上非常强的一点,因为它把模型能力可视化了。用户不必猜“应该怎么提问”,而是通过命令表理解“系统能做什么”。

所以三者真正的区别,不只是命令多不多,而是:

系统命令定位
OpenCode模板化、可扩展的意图路由层
OMO可触发编排流程的工作流入口
Claude Code产品级高可见“动作词表”

命令层为什么重要?因为它把隐藏在 prompt engineering 里的结构外显出来。很多高级用法如果只能靠“用户自己记住怎么措辞”,那就很难稳定复用。命令系统把这些隐性技巧变成显式入口,从而让复杂能力变得可教、可记、可发现。

它还有治理价值。命令可以编码默认 agent、默认 model、默认子任务模式、默认审查模板。这样团队就不需要每个人都自己写一套“差不多但不完全一样”的 prompt。命令在组织里可以起到“流程标准件”的作用。

OpenCode 的优势,在于命令和其他扩展层之间不是孤立的。Skill 可以长成命令,MCP prompt 可以长成命令,用户配置命令又能与内置命令共存。于是 Command 成了一个横跨多个扩展来源的统一调用界面。

OMO 的增强在于“上下文化路由”。它不只问“命令能展开成什么文字”,还问“命令应当触发什么编排流程”。这很关键,因为一旦命令可以映射到 agent、subtask、background flow,它就不再是 UI 糖,而是行为控制入口。

Claude Code 的优势则在于产品打磨。大量、清晰、可记忆的命令,会让系统显得非常强大和顺手。但这也带来 command sprawl(命令膨胀)问题。这个词不是标准 CS 教材里的固定术语,可以理解为“命令数量太多,边界模糊,导致用户不知道该用哪个”。商业产品如果命令表过于膨胀,发现性反而会下降。

因此,命令系统最好的设计,不是单纯追求多,而是要把它视为“面向人类的结构化意图 API”。Plugin 是给开发者的,Skill 是给 agent 行为的,Command 是给用户重复操作的。OpenCode 提供了最优雅的组合模型,OMO 展示了命令与编排融合的可能,Claude Code 则证明了命令可以成为产品体验的重要正面入口。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第16章 — 可扩展性对比
Token用量: 约 5,000 input + 1,260 output

16.4 钩子系统

Hook system 是扩展能力中最接近“生命周期控制”的一层。所谓 hook,本质上就是一个拦截点:某个事件发生前后、某个阶段开始结束时,系统允许额外逻辑插入。很多真正关键的 agent 行为,不是在 prompt 里决定的,而是在这些边界处决定的。

OpenCode 暴露的宿主 hook 点并不算多,但位置都非常关键。大致可以看成五类重要入口:配置、消息处理、参数/消息变换、事件处理、工具执行前后。这种设计的优点,是宿主 hook surface 虽小,但杠杆很大。开发者不需要面对几十个零碎钩子,也照样能做出非常强的扩展。

OMO 在这个基础上做了一个极其有代表性的动作:它把 41 个内部 hooks 复接到 OpenCode 的 5 个 hook points 上。这句话几乎概括了 OMO 的整个中层设计。宿主层只给出少量生命周期入口,OMO 则在这些入口后面挂出一个更丰富的策略图谱:session hooks、tool-guard hooks、transform hooks、continuation hooks、skill hooks。也就是说,OMO 不是简单“使用了宿主钩子”,而是在宿主钩子之上又构造出了一套二级 hook 语言。

Claude Code 也有 5 个 hooks,但风格明显不同。它们更强调产品生命周期与安全相关节点,例如 session_start、pre_compact、post_compact、post_sampling、file_changed 等。这个设计取向很清楚:给出少量高价值节点,支持自动化与定制,但不把宿主运行时主导权大规模交给扩展层。

所以三者的 hook system 可以这样理解:

系统Hook 画像
OpenCode小而强的宿主级 hook 面
OMO建立在 5 个宿主点上的 41-hook 策略系统
Claude Code5 个更偏产品/安全的受控 hooks

这里需要区分两个层次:host hooks(宿主钩子)policy hooks(策略钩子)。这两个词不是传统教材里的固定二分法,但很适合分析这里的结构。宿主钩子,是系统本身暴露给扩展层的原生入口;策略钩子,则是扩展作者在宿主钩子之上再抽象出来的二级行为插点。OpenCode 给的是前者,OMO 在其上构建了后者,Claude Code 则更谨慎地暴露前者的一部分。

为什么 hook system 如此重要?因为很多 hardest problems(最难的问题)都发生在边界上。例如:工具执行前,是否要检查目标文件危险性?消息送进模型前,是否要注入仓库规则?上下文压缩后,是否要恢复 todo 状态?这些都不是“多写两句 prompt”能解决的,而是标准的 hook 型问题。

OpenCode 的哲学是:给少量强钩子,其他留给开发者组合。Claude Code 的哲学是:给少量经过挑选的钩子,保证产品边界和安全主权。OMO 的哲学则是:把钩子升级为一整套运行时治理系统。

OMO 的 tool-guard hooks 是这个思路最好的例子。file guard、comment checker、rules injector、continuation enforcer 等,说明 hook 并不只是为了“改一下数据流”,而是为了做质量控制、安全控制、行为约束和状态保留。换句话说,hook-rich architecture 的价值,在于它能把“prompt 做不到的运行时纪律”写进系统。

但 hook 越多,也越难调试。钩子系统最大的隐患,是交互复杂度。一个消息在 A 阶段被改写,在 B 阶段触发了新的规则,在 C 阶段又被恢复,你很难第一时间知道问题到底来自哪里。所以 hook 的力量和调试成本是成正比的。

对未来平台设计者来说,一个重要结论是:应该明确区分“给宿主多少原生 hook surface”和“允许扩展层在其上构造多复杂的策略图谱”。OpenCode 证明小 hook 面也能很强,OMO 证明二级 hook 体系能撑起一个中层运行时,Claude Code 则证明商业产品可以通过较少的 hooks 保持稳定和可控。

如果说插件是“能加什么能力”,那 hooks 解决的是“在什么时候、以什么边界条件加这份能力”。OpenCode 把门打开,OMO 把门后修成了走廊和房间,Claude Code 则在门口装了更严格的门禁。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第16章 — 可扩展性对比
Token用量: 约 4,780 input + 1,210 output

16.5 Manifest驱动发现

可扩展性不只是“扩展能不能运行”,还包括“扩展怎么被发现、怎么被识别、怎么被装载”。这就涉及 manifest-driven discovery。所谓 manifest,可以理解为一种显式元数据声明:这个扩展是什么、放在哪、系统应该怎么理解它。它不一定是单独叫 manifest.json 的文件,也可以是 frontmatter、配置块、目录约定等。

OpenCode 的发现机制相对轻量,但非常实用。Skill 通过目录扫描和 frontmatter 识别,Command 可以从配置、MCP prompt、Skill 派生,Plugin 和其他资产也主要通过约定路径与配置完成发现。这种方式不算特别“重规范”,但它有很强的工程实用性:对作者友好、对阅读友好、对实验友好。

轻量 manifest 的一个优势是:它降低了扩展作者的心理门槛。一个 markdown 文件加几行 frontmatter,就是一个 skill;一段配置,就是一个 command。你不需要先建立一个完整的打包和发布流程,才能开始扩展系统。这种低摩擦设计,对开源生态尤其重要。

OMO 在这件事上做得更进一步。它不仅能识别 OpenCode 风格目录,还能兼容 Claude 风格目录、.mcp.json、skill 目录、command 目录等。也就是说,OMO 把 manifest-driven discovery 从“自家资产发现机制”,扩展成了“跨生态兼容机制”。这非常关键,因为它意味着发现系统不只是为自己服务,还能作为生态桥梁,把不同格式的扩展资产吸纳进统一运行时视图。

Claude Code 则更偏向产品结构化约定。插件、agent、hook、skill、MCP 配置通常在固定位置、遵守固定 schema。这样做的好处,是产品可预测性更强,用户也更容易知道“什么装在哪、什么会生效、什么当前处于启用状态”。商业产品天然会偏爱这种更强结构,因为可支持性和可诊断性很重要。

这里有个核心问题:manifest 的“仪式感”应该多强?

太弱,会导致歧义。扩展能被扫到,但不容易验证;命名冲突难处理;错误路径也可能被误加载。

太强,则会抬高创作成本。很多本来应该轻松写出来的小扩展,会因为必须补一堆元数据和打包步骤而变得笨重。

OpenCode 更偏向“低仪式感发现”,OMO 更偏向“广兼容吸纳”,Claude Code 更偏向“高结构清晰”。三者其实代表了三种生态管理策略。

Manifest-driven discovery 还和安全直接相关。只要扩展是通过显式元数据和显式位置被发现的,系统就更容易做 schema 校验、来源检查、重复命名警告、启用前策略审查。相反,如果发现机制完全随意,安全治理就会困难得多。

另一个重要维度是可移植性。OpenCode 愿意扫描相邻生态目录,这是一个非常聪明的反锁定设计。OMO 更进一步,把兼容读取做成系统能力。Claude Code 则更享受标准化目录带来的产品一致性,但相对不那么格式无关。三者没有绝对高下,只是优先级不同。

对未来 agent 平台来说,一个很可能的最佳实践是混合式方案:对 Skill、Command 这类内容型资产,使用轻量 manifest;对 Plugin、MCP 这类可执行扩展,使用更强 schema;同时提供对相邻生态格式的兼容读取器。这样既能保留可用性,又不会牺牲可治理性。

所以,Manifest-driven discovery 看起来像一个偏“工程琐事”的问题,实际上它决定了扩展生态的健康程度。OpenCode 证明了轻量 manifest 也能很好用,OMO 证明了发现系统可以成为互操作层,Claude Code 则说明强结构对于商业稳定性非常有价值。真正好的扩展平台,不只是允许扩展存在,还要让扩展可见、可懂、可管

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第17章 — 安全模型对比
Token用量: 约 4,950 input + 1,250 output

17.1 权限范式

权限系统是 coding agent 安全设计里最能暴露底层信任哲学的部分。几乎每个系统都会说自己重视安全,但真正有区别的,是它到底靠什么机制来判断“该不该让这件事发生”。是靠静态规则?靠机器学习分类?靠运行时拦截?还是多层叠加?OpenCode、OMO 与 Claude Code 分别代表了三种不同的权限范式。

OpenCode 更接近 pattern-based permission(基于模式匹配的权限模型)。这是一种很典型的工程化思路:根据命令形态、路径模式、动作类型等显式规则来判断是否允许。它最大的优点是透明。开发者通常能较容易理解“为什么这一步被拦了”或“为什么这一步通过了”。缺点也同样明显:规则再多,也很难枚举完现实场景。灰色地带、组合场景、上下文依赖强的操作,常常不是固定 pattern 能优雅覆盖的。

Claude Code 则明显更现代一些。它不仅有 四种权限模式,还叠加了 ML classifier(机器学习分类器) 来降低不必要的授权打扰。这个设计的核心目标,是在“安全”与“少打断用户”之间找平衡。纯规则系统容易过度保守,导致用户被频繁询问授权;引入学习型分类器后,系统可以根据更丰富的上下文判断某个行为是否真正危险。代价则是可解释性下降——模型判断越多,用户越难完全看清边界在哪里。

OMO 的思路又不一样。它建立在 OpenCode 宿主之上,因此会继承宿主权限机制,但它自己还叠加了一层 file-guard hooks(文件守卫钩子) 和运行时策略拦截。也就是说,OMO 的安全不是靠一个统一的大权限裁决器,而是靠一系列在工具边界、文件边界、规则边界上工作的“局部守卫”。write-existing-file-guard、comment-checker、rules-injector 这些 hook,共同形成了第二圈防线。

这三种范式可以概括为:

系统主要权限逻辑
OpenCode显式规则与模式匹配
OMO宿主权限 + hook 型文件/策略守卫
Claude Code多模式权限 + ML 分类器

它们分别体现了三种安全观。

基于模式匹配的权限,假设危险行为大多能通过可识别的形状来近似判断。这种方法适合强调可控性和可解释性的系统。

基于分类器的权限,假设风险并不能完全被显式规则枚举,因此需要让系统学习更广义的“可疑性”。这类方法适合商业产品,因为它可以减少大量烦人的无意义弹窗。

基于 hook 的局部守卫,则假设很多风险只有在动作即将真正发生的边界上才最清楚。比如真正要写哪个文件、真正要注入什么规则、真正要输出什么注释,往往要到运行时最后一刻才看得最准。

这里必须强调一点:权限系统不只是“防危险”,它也是“降打扰”。如果系统对每个工具调用都大喊“请授权”,用户很快就会麻木,甚至直接进入 yolo 模式全放开。Claude Code 的 ML 权限设计,本质上就是在试图解决这个问题。OpenCode 选择了更清晰的边界,OMO 则在本地规则和仓库特定约束上加码。

从架构角度看,这三者其实给出了一个很合理的分层答案。显式规则适合高确定性的边界;ML 分类适合模糊风险场景;hook 守卫适合仓库局部策略和运行时上下文。也就是说,未来最好的权限系统,大概率不会只押宝某一种,而是三层叠加。

对 agent 平台设计者来说,核心结论是:权限范式不该被看成一个单点开关,而应被视为一个分层控制面。OpenCode 贡献了清晰性,OMO 贡献了局部守卫,Claude Code 贡献了“更少打断但仍尽量安全”的自适应能力。未来的方向很明显:权限系统会越来越智能,但仍然需要可审计的硬边界做地基。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第17章 — 安全模型对比
Token用量: 约 4,600 input + 1,160 output

17.2 沙箱化

如果说权限提示解决的是“该不该做”,那么 sandboxing(沙箱化)解决的是更硬的一层问题:即便模型判断错了、规则漏了、插件越界了,它实际上还能造成多大伤害? 一旦问题进入这一层,真正有用的就不再是提示词,而是操作系统级能力隔离。

在这方面,Claude Code 明显领先于 OpenCode 和 OMO。它采用了 OS-level sandbox(操作系统级沙箱),例如 Linux 上的 bubblewrap、macOS 上的 Seatbelt。Anthropic 还提到过一个非常关键的数字:这类安全策略带来了 84% 的风险/授权负担下降。具体分母细节当然重要,但从架构层面看,真正关键的不是数字本身,而是它说明了一件事:一旦把安全控制下沉到 OS 边界,很多原本必须靠频繁人工确认来兜底的风险,就能被能力限制直接削弱。

这和单靠 prompt 或权限规则完全不是一个层次。Prompt 可能被忽略,规则可能被绕过,分类器可能判断错;但如果进程本身拿不到某些目录、拿不到某些网络能力、拿不到更高权限,那么即使上游出了问题,伤害半径仍然被压缩了。这种思路在安全工程里属于 capability-based safety(基于能力边界的安全),也就是通过限制“能做什么”来兜底,而不是只限制“应该做什么”。

OpenCode 本身并没有把 OS 级沙箱作为它的核心安全特征,OMO 也没有。它们当然不是因此就“不安全”,但安全模型更多依赖权限判断、工具边界、hook 守卫和使用纪律。换句话说,如果某个 shell 或文件工具已经获准在宿主机上运行,那么宿主本身拥有的权限就仍然是关键前提。

这件事在 autonomous agent 场景里尤其重要。编码智能体的风险,从来不只是“模型说错一句话”,而是它能调 shell、能写文件、能碰网络、能接第三方服务。一旦这些能力被整合在一起,单纯靠上层提示和规则很难形成最后防线。沙箱化是少数在“推理已经失败以后”依然有效的控制手段。

当然,沙箱也有代价。它会增加实现复杂度,会降低某些真实开发工作流的兼容性,还可能让用户在一些明明合理的任务上碰到“权限墙”。有些开发场景确实需要更广的文件系统访问、网络访问或系统调用能力。因此,商业产品必须不断在“安全收口”和“开发体验”之间做权衡。

但无论如何,有一个结论几乎已经很难回避:只要 agent 能执行 shell、修改文件、接触凭证,OS 级沙箱就迟早会从“高级特性”变成“基础配置”。OpenCode 和 OMO 代表的是“非沙箱优先架构”的当前状态与优缺点,Claude Code 则代表了下一阶段的成熟方向。

还需要注意一点:沙箱不是权限系统的替代品,而是权限系统之后的后备防线。权限系统负责尽量别让危险动作发生,沙箱负责危险动作真的发生时别让后果无限扩大。前者更像“前门保安”,后者更像“防火隔间”。两者不能互相替代。

对未来开源 agent 平台来说,Claude Code 的做法给了一个非常清楚的信号:如果系统越来越自主,那么只做 prompt 安全和授权弹窗是不够的。OpenCode 与 OMO 在这方面的空缺,也恰恰说明这将成为未来演进的重要方向。

最好的安全栈,大概率会是三层叠加:清晰权限、运行时守卫、OS 级沙箱。在这三层里,沙箱往往是最不花哨、却最诚实的一层,因为它真正限制了“即使出事,还能坏到什么程度”。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第17章 — 安全模型对比
Token用量: 约 4,880 input + 1,240 output

17.3 供应链安全

一个 agent 平台越可扩展,它就越不可避免地变成一个 supply chain(供应链)问题。插件、技能、命令、MCP server、远程 skill URL、manifest、兼容加载器,这些东西都会提升能力,但同时也在扩大信任面。所谓供应链安全,讨论的其实不是“系统自己写得安不安全”,而是“系统愿意接进来的外部东西安不安全”。

OpenCode 由于天然开放,在这方面暴露得最明显。它允许远程 skill、允许强能力插件、允许 MCP 连接外部服务,这对于生态发展极好,但对于 provenance(来源可信度)要求也更高。provenance 这个词在安全和构建系统里越来越常见,传统 CS 教材里不一定展开很多,它可以理解为“某个扩展资产的来历、来源链条和可追溯性”。如果 provenance 弱,开放生态就容易变成高风险生态。

OMO 继承了 OpenCode 的开放性,还叠加了自己的复杂度。因为它支持跨多种格式发现和兼容加载,所以它的 discovery layer(发现层)同时也是 compatibility layer(兼容层)。兼容性本身当然很好,它降低迁移成本、提高复用率,但也意味着系统必须审查更多来源、更多路径、更多格式。格式越多、入口越多,供应链治理压力就越大。

Claude Code 的整体姿态更保守,但同样逃不开这类问题。只要系统支持 skill、plugin、hook、MCP 这类外部资产,它就必须面对:这些东西由谁提供?怎么审核?怎么更新?激活之后会影响多大范围?商业系统一般会通过更强 schema、更清晰目录结构、更严格默认边界来降低风险。

这里最关键的一点是:不同扩展类型的风险等级并不一样。

Plugin 是可执行代码,风险最高。

MCP server 是外部能力桥,也可能很高风险,取决于它连到什么服务、给了什么权限。

Skill 和 Command 主要是内容型扩展,通常风险更低,但它们仍然可能通过误导性指令、坏流程建议、社会工程式提示,间接把模型带偏。

Manifest 看起来最无害,但如果发现机制本身很松散,manifest 也会成为供应链薄弱点。

在这一点上,OMO 的 skill-guardian 非常值得注意。它隐含了一种非常成熟的观点:安装本身就是安全事件。不是说技能装进来以后再看它干了什么,而是在装之前就应该检查它的来源、用途、风险、必要性。这个思路是对的,因为供应链安全不是激活后再补,而是从准入开始。

从三者对比里,可以提炼出几条很明确的实践原则。

第一,可执行扩展的信任门槛必须高于内容扩展。

第二,远程资产最好有 pinning、checksum、签名或至少显式来源声明。这里的 pinning 指“把依赖固定到一个明确版本或提交”,避免悄悄漂移。

第三,manifest 和 schema 应在激活前被验证。

第四,系统应保留清晰的来源元数据,让用户知道每个扩展从哪里来。

第五,安装流程应该被视为策略控制面,而不是单纯的便利入口。

更大一点看,agent 生态正在越来越像包管理器和浏览器扩展生态。大家都要回答一样的问题:这是谁写的?它能做什么?它如何更新?出了事谁来解释?OpenCode 代表开放生态的创新红利与风险暴露,OMO 代表兼容性进一步放大后的治理难度,Claude Code 则代表更强产品化约束下的收口路线。

随着 agent 平台进入生产环境,供应链安全会越来越成为“玩具扩展系统”和“可上生产扩展系统”之间的分水岭。OMO 的 skill-guardian 已经在往这个方向走,它说明未来的成熟系统,不会只比功能数量,还会比“准入治理”能力。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第17章 — 安全模型对比
Token用量: 约 4,900 input + 1,250 output

17.4 凭证隔离

Credential isolation(凭证隔离)是 agent 架构里最不吸引眼球、却最不能出错的部分之一。只要系统支持插件、MCP、远程 API、包管理、第三方集成,就必须回答一个尖锐问题:到底谁可以直接接触秘密?

最安全、也最应该被当成架构定律的一句话是:插件绝不能直接访问核心凭证。 不能直接拿宿主主模型 key,不能默认继承仓库级 secrets,不能顺手就能碰到全局 token,除非系统明确、分层、可审计地授予过。

OpenCode 的开放性让这个问题尤其重要。越开放的宿主,越容易让第三方代码靠近高权限操作。如果扩展层可以轻易继承宿主的全部凭证上下文,那么一次插件 compromise(失陷/被攻破)就可能变成整个平台 compromise。这里的 compromise 在安全领域是常见词,表示“系统或凭证已经落入不可信状态”。

OMO 则进一步放大了这个问题,因为它不仅有更多扩展类型,还有更多间接执行路径:后台 agent、skill-embedded MCP、兼容层加载组件、跨会话工作流。如果这些组件只是因为“正在参与一次任务”就自动继承宿主秘密,那么凭证传播路径会非常失控。编排越复杂,凭证边界越必须清晰。

Claude Code 的商业姿态让凭证隔离显得更基础。企业环境不能依赖“大家都别乱来”这种善意假设,它需要系统性区分:哪些是产品核心凭证,哪些是用户提供 token,哪些是扩展专属 secret,哪些只应该在某个任务窗口内临时可用。没有这层区分,所谓 enterprise readiness 基本站不住。

在这里,一个非常值得推广的设计模式是 scoped token proxy(带作用域的令牌代理)。它的核心思想是:不要把根凭证直接交给扩展,而是由宿主提供一个 broker/proxy 层。扩展请求的是“能力”,而不是“原始秘密”。宿主再根据策略决定:是否发放、发放什么范围、有效多久、是否记审计日志。

这个模式的优势非常清楚。

第一,扩展看不到最高敏感度的根凭证。

第二,权限可以按服务、仓库、操作类型、时间窗口做细粒度限制。

第三,撤销更容易,因为控制权始终在宿主代理层。

第四,可审计性更强,因为每次能力授予都可以被记录为离散事件。

第五,secret rotation(凭证轮换)更容易。这里的轮换指定期更换密钥值以降低泄漏风险;如果扩展从不直接持有长期 root token,轮换对扩展的冲击就会小很多。

凭证隔离还和沙箱化有很强的协同关系。即使某个扩展拿到了一点 scoped access(有范围限制的访问),如果它仍然被 OS 级沙箱限制在较小的环境里,它把这份访问进一步外传或横向扩大利用的难度就会更高。这也是为什么 Claude Code 的沙箱方向值得重视——它不是和凭证隔离平行,而是互相增强。

当然,凭证管理也有开发体验问题。如果做得过于死板,工程师会绕路,最后把 secret 手动写进环境变量、脚本或本地文件里,反而更危险。所以好的系统不是单纯“越麻烦越安全”,而是应该把“安全获取能力”做成最顺手的路径。

把三者放在一起看,OpenCode 说明开放扩展宿主必须重视秘密边界,OMO 说明编排复杂性会乘法式增加凭证传播路径,Claude Code 则说明商业系统必须把隔离做成基础设施,而不是约定俗成的好习惯。

未来安全扩展体系的一个核心原则应该是:扩展被授予的是 capabilities(能力),而不是 inherited trust(继承而来的原始信任)。前者可以被限制、审计、撤销;后者一旦泄漏,往往就是系统级事故。只要这一原则守住了,扩展生态就还有机会既开放又安全;一旦它被破坏,每多一个插件、一个 skill bridge、一个 MCP connector,就多一个可能泄密的洞。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第18章 — 理想编码Agent的架构
Token用量: 约 7,600 input + 2,050 output

18.1 共识架构

到了 2026 年,优秀 coding agent 的“理想架构”其实已经越来越有共识。不同产品当然还会在商业模式、界面风格、默认工作流、是否开源等问题上继续分化,但如果只看技术骨架,行业已经逐步收敛到一套相当稳定的组合:高空位、低细节的 system prompt(系统提示词)统一的 tool registry(工具注册表)/MCP clients(MCP 客户端层)紧凑的 context manager(上下文管理器)ReAct loop(推理-行动-观察循环)sub-agents(子智能体),以及OS-level sandbox(操作系统级沙箱)

这里的“高空位”是一个很重要的概念。它不是计算机教材里的标准术语,而是 agent 设计里很实用的一个说法,意思是:提示词只定义高层原则,不塞满低层细节。也就是说,system prompt 不应该变成一本操作手册,更不应该承担所有行为逻辑。它只负责身份、边界、任务哲学、推理姿态这些稳定、不频繁变化的内容。至于具体工具怎么调用、哪些场景该走什么流程、上下文怎么压缩、何时委派子 agent,这些都应该被分配到别的层。

为什么会形成这个共识?因为早期做 agent 的人几乎都踩过同一种坑:把所有东西都塞进 prompt。身份说明塞进去,风格要求塞进去,安全规则塞进去,工具说明塞进去,产品逻辑塞进去,边缘情况塞进去,最后 prompt 变得像一个不断膨胀的企业规章制度文件。这样短期看似可控,长期却会迅速失效:模型记不稳,规则冲突,维护困难,而且每次修改都像在拆承重墙。

所以,理想架构的第一条共识就是:让 prompt 变小,把系统做大。 这里的“大”不是指代码量,而是指结构层次更清晰、职责更分离。

第二个共识是 tool registry 必须成为正式基础设施。工具注册表不是一份松散的函数列表,而是 agent 的“行动宪法”。它要回答几个问题:有哪些动作可以做?每个动作的输入输出是什么?副作用是什么?什么场景适合用,什么场景不适合用?是否存在权限要求?是否有替代工具?

在 2026 年的主流做法里,这层通常不再只包含本地内置工具,而是会把 MCP、LSP、宿主原生工具、插件包装工具统一成一个可被模型理解的接口层。也就是说,agent 不应该知道底层这个能力究竟来自内置代码、远程 MCP server,还是 IDE 的 LSP 服务;对它来说,这些都应该以统一 schema(结构化参数定义)的形式出现。

OpenCode、OMO、Claude Code 在这里虽然实现风格不同,但方向非常一致。OpenCode 提供的是可编程宿主;OMO 证明了工具不仅能操作文件和 shell,还能承担编排角色;Claude Code 则进一步说明工具系统之外还必须有宿主层策略控制。三者叠加起来,就形成了一个越来越清楚的架构蓝图。

┌─────────────────────────────────────────────────────────────┐
│                    USER / IDE / CLI / API                  │
└────────────────────────────┬────────────────────────────────┘
                             │
                             v
┌─────────────────────────────────────────────────────────────┐
│   MINIMAL SYSTEM PROMPT                                    │
│   - 身份与作用域                                            │
│   - 全局安全边界                                            │
│   - 规划/推理姿态                                           │
└────────────────────────────┬────────────────────────────────┘
                             │
                             v
┌─────────────────────────────────────────────────────────────┐
│   CONTEXT MANAGER                                          │
│   - 紧凑会话状态                                            │
│   - JIT retrieval(即时检索)                               │
│   - structured notes(结构化笔记)                          │
│   - compaction(压缩)与 overflow recovery(溢出恢复)       │
└────────────────────────────┬────────────────────────────────┘
                             │
                             v
┌─────────────────────────────────────────────────────────────┐
│   REACT EXECUTION LOOP                                     │
│   think → choose tool / delegate → observe → update state  │
└───────────────┬───────────────────────────────┬─────────────┘
                │                               │
                v                               v
┌──────────────────────────────┐   ┌──────────────────────────┐
│ TOOL REGISTRY / MCP CLIENTS  │   │   SUB-AGENT ORCHESTRATOR │
│ - 文件 / git / 搜索 / LSP     │   │ - explore / review / doc │
│ - 浏览器 / 测试 / deploy      │   │ - 并行且隔离的工作        │
│ - typed schemas + 描述文档    │   │ - 结果汇总与回收          │
└───────────────┬──────────────┘   └──────────────┬───────────┘
                │                                 │
                └──────────────┬──────────────────┘
                               v
┌─────────────────────────────────────────────────────────────┐
│   HOST RUNTIME + POLICY LAYER                              │
│   - 权限、审批、审计、成本控制                              │
│   - 重试、限流、来源追踪、策略检查                          │
└────────────────────────────┬────────────────────────────────┘
                             │
                             v
┌─────────────────────────────────────────────────────────────┐
│   OS-LEVEL SANDBOX                                          │
│   - 文件系统范围  - 网络策略                                │
│   - 进程隔离      - 凭证边界                                │
└─────────────────────────────────────────────────────────────┘

这张图里最容易被低估的一层,是 context manager。Prompt engineering(提示工程)主要讨论“怎么写指令”;而 Context engineering(上下文工程)讨论的是“如何管理模型在这一刻实际看到的全部 token 状态”。后者明显更接近系统工程。

一个 coding agent 很少是因为“模型不够聪明”才失败,更常见的情况是:它看到的上下文是错的、旧的、臃肿的、互相冲突的、无关信息太多的。于是一个成熟的上下文管理器至少要做好四件事。

第一,保持活跃上下文紧凑。模型在当前步骤里真正需要的,通常只是任务目标、若干约束、少量关键文件、最近一次工具输出,以及一份短的中间状态总结,而不是整个聊天历史全文回放。

第二,做 JIT retrieval(即时检索)。这个术语可类比数据库中的按需加载:不是提前把所有资料塞进内存,而是在需要时拿进来。对 agent 来说,就是某个文件、某段历史、某条规则、某份文档只有在当下相关时才被注入上下文。

第三,维护 structured notes(结构化笔记)。这不是普通聊天记录,而是把“当前已知事实、待验证假设、已完成步骤、剩余风险”写成更适合机器消费的紧凑状态对象。它的作用类似于程序里的状态机快照。

第四,支持 overflow recovery(上下文溢出恢复)。这里的 overflow 指上下文窗口超限。优秀系统不能把这件事视为罕见事故,而应该把它当成日常运行条件之一:一旦接近上限,就压缩、重写锚点、保留关键状态,尽量优雅退化,而不是突然失忆。

在这之上,仍然是 ReAct loop 作为执行核心。ReAct 不是计算机教材里的经典术语,而是 agent 领域的经验范式,意思是模型通过“推理—行动—观察—再推理”的迭代方式解决问题。它适合 coding work 的原因很简单:编程任务不是纯问答,也不是一次性脚本。agent 必须检查文件、调用工具、根据返回结果修正路径,再继续下一步。

不过到 2026 年,ReAct 的最佳实践也发生了变化:它不再强调把所有思考都冗长展开,而更强调状态转移的纪律性。模型负责决策与解释,宿主负责日志、策略、权限、重试和执行边界。换言之,ReAct 不再等于“多想一点”,而更像“每一步都知道自己为什么行动,以及行动后如何更新状态”。

再往上走,就是 sub-agents。子智能体的真正价值不是“看起来很高级”,而是上下文分区任务并行。一个 agent 去 codebase 里做探索,一个 agent 去查外部文档,一个 agent 专门复核某个结论,这些都属于把复杂任务拆成多个边界清楚的小工作区。OMO 在这一点上走得最远,Claude Code 也在更审慎地接纳,OpenCode 则提供了底层可组合性。

但这里也有一个经常被忽视的条件:sub-agent 只有在编排质量足够高时才有意义。也就是说,不是多几个 agent 就更强,而是何时分、怎么分、结果怎么回收 才是关键。否则子 agent 很容易从能力变成噪音源。

最后一层,也是决定这套架构能否真正落地的一层,是 OS-level sandbox。它的重要性在于把“安全”从提示词层面的说服,变成操作系统层面的约束。文件系统可见范围、网络访问策略、进程隔离、凭证边界、审计日志,这些机制一起决定 agent 是否能在高自治状态下被组织接受。

Claude Code 给行业最重要的提醒之一就是:安全不是自治的刹车,而是自治的地基。 没有沙箱,每次提升 agent 自主性都会同步提升恐惧;有了沙箱,自主性就被放进一个可管理的边界里,风险被显式约束,信任才有增长空间。

所以,2026 年的理想编码 agent 共识架构,本质上是在分层解决六类失败:system prompt 过胖导致规则腐烂,tool surface(工具表面)不清导致动作混乱,context 失控导致 token 污染,单循环过载导致效率低下,缺乏任务分治导致大任务难以伸缩,缺乏沙箱导致组织无法放心授权。

真正优秀的系统不是让模型背更多说明书,而是让不同层承担不同职责:prompt 负责原则,tool registry 负责能力声明,context manager 负责状态质量,ReAct loop 负责执行节奏,sub-agents 负责分工,sandbox 负责可信边界。这就是理想架构之所以已经逐渐形成共识的原因:它不是某家公司偏好的产品哲学,而是被现实反复逼出来的工程答案。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第18章 — 理想编码Agent的架构
Token用量: 约 7,200 input + 1,950 output

18.2 五大定义性张力

一个 coding agent 的架构,不是由“功能清单”定义的,而是由它如何处理几组长期存在、无法回避的张力定义的。模型变强以后,这些张力并不会自动消失,反而会更加尖锐:因为模型越强、工具越多、上下文越大、自治能力越高,错误的代价也越大。对 OpenCode、OMO、Claude Code 这三套系统进行比较后,可以看到最核心的五组张力分别是:Autonomy vs Safety(自治 vs 安全)Context richness vs Context rot(上下文丰富度 vs 上下文腐坏)Generality vs Specialization(通用性 vs 专门化)Simplicity vs Capability(简单性 vs 能力密度)Open vs Closed(开放 vs 封闭)

这里的“张力”不是教材里的严格术语,更像系统设计中的“拉扯关系”。意思是两边都重要,但很难同时把两边都拉到极致,所以架构必须选择重心,并用设计手段做平衡。

一、自治 vs 安全

coding agent 天生想变得更主动:少问、快做、连续执行、多步推进。因为从用户角度看,真正有价值的 agent 不应该每做一步都像在申请审批。但只要 agent 更主动,它的失误半径也会同步增大。一次错误 shell、一次误删文件、一次错误提交、一次不该发出的网络请求,都可能让“有用”直接转化成“有害”。

OpenCode 对这组张力的处理,整体上更偏向开发者控制。它提供了非常可编程的宿主和灵活的工具体系,但不会替使用者预先做过多重产品级限制。这样做的好处是实验自由度高,能力上限高,坏处是安全策略更多依赖使用场景与扩展作者自身的约束,而不是系统强约束。

OMO 的解法不是单纯把权限系统做得极重,而是通过编排纪律来降低风险。它增加了后台任务、专门 agent、规则注入、todo 驱动执行、hook 检查等机制,本质上是在说:如果 agent 的行为结构设计得更好,它就会更少走偏。也就是说,OMO 常常是在“宿主之上”用更好的 orchestration(编排)来换取更高自治下的可控性。

Claude Code 则把这组张力处理得最“产品化”。它通过 permission system(权限系统)、审批语义、分类器、成本控制、沙箱化执行等机制,试图把安全下沉到运行时基础设施层。它传达的核心观点是:安全不是自治的反面,而是让自治得以被大规模接受的必要条件。 这点非常重要。

二、上下文丰富度 vs 上下文腐坏

agent 要做好 coding work,当然需要大量上下文:用户意图、代码仓状态、最近变更、工具结果、历史决策、项目约束、文档说明,甚至更久之前的会话记忆。但上下文不是越多越好。信息一旦堆积到一定程度,就会发生 context rot(上下文腐坏)

“腐坏”也是一个更偏工程经验的说法,不是标准教科书术语。它指的不是数据丢失,而是上下文虽然还在,却已经不再可靠:有的过期了,有的重复了,有的互相冲突了,有的和当前任务其实无关,却仍然占据了 token 预算并干扰判断。

OpenCode 在这一点上的启示是:上下文必须被结构化管理,而不是简单拼接。它的 session、message、compaction 等设计已经在说明,长任务对话不是“聊天记录越来越长”这么简单,而是需要状态管理。但 OpenCode 本身偏向通用宿主,因此它对“什么该长期保留、什么该被压缩”这件事,更多提供机制,较少强加单一策略。

OMO 则在这方面更积极。它通过 hook、rules injector、continuation、task-specific prompt 等方式,把上下文当成一种需要动态编排的资源。尤其是它很清楚地认识到:正确上下文不等于更多上下文。某个子 agent 往往在更窄、更干净的上下文里反而表现更好。因此 OMO 对这组张力的解法,是通过任务切分与按需注入来减少上下文污染

Claude Code 的处理方式更像工业级产品:记忆系统、自动压缩、持久记忆与瞬时状态区分、多种 compaction 策略。它不假设上下文溢出是偶发事故,而是把它视为长期运行中必然发生的正常情况。因此它的答案是:把 context management 直接做成正式子系统。

三、通用性 vs 专门化

一个通用 agent 易于理解:一个助手,什么都做。一个专门化 agent 体系则更像组织结构:有人负责探索,有人负责审查,有人负责资料检索,有人负责规划。前者看起来简单统一,后者往往更利于复杂任务伸缩。

OpenCode 的立场更偏通用。它是一个很强的底座,允许开发者构建各种 agent、接口、插件和工具,但宿主本身并不预设一个非常强的 specialization(专门化)哲学。这恰恰是它的优点,因为它把决定权留给上层系统。

OMO 则明显往专门化方向走,但它真正高明的地方不在“agent 数量多”,而在于它把专门化变成了 prompt、工具和工作流共同决定的事情。某个 agent 不是因为名字不同就专门化,而是因为它拿到的上下文、工具权限、角色说明和交付目标都不同。这个设计说明,专门化最有价值的时候,是它能减少认知碰撞,而不是制造组织感。

Claude Code 处在两者之间。它的主体验通常还是统一助手,但也逐渐接受更窄职责的 task delegation(任务委派)和角色化结构。它不像 OMO 那样强调多 agent 身份体系,但它承认:在某些任务上,有限专门化比单一万能人格更有效。

四、简单性 vs 能力密度

系统每多一个 feature,能力就可能增强一点,但可理解性也可能下降一点。这里的“能力密度”不是教材术语,可以理解成:在单位系统复杂度里塞进了多少真实能力。如果能力增长主要来自重复工具、重复流程、重复模式,那复杂度就会上升得很快,真正的能力密度反而不高。

OpenCode 的优秀之处在于,它的核心底座相对清爽。它不是绝对极简,但它努力让宿主层逻辑保持可读、可扩展、可重组。正因此,它很适合作为基础设施——能力可以继续往上长,而不会把底盘本身搅乱。

OMO 则主动承受更多复杂性,因为它要解决的是更难的 orchestration 问题。Hook、skills、categories、background tasks、wisdom、continuation、embedded MCP,这些都会增加系统层数。但 OMO 的经验也说明:复杂不是原罪,无组织的复杂才是原罪。如果每一层复杂度都对应明确功能,那么它可能产生远高于成本的杠杆。

Claude Code 的办法是把复杂度尽量藏到产品内部。它内部工具可能很多,策略可能很多,模式也可能很多,但用户界面尽量维持统一、顺滑、低学习成本。这是典型商业产品解法:允许内部复杂,外部尽量简单。代价则是某些能力不一定完全对用户开放或可编程。

五、开放 vs 封闭

这是最深的一组张力。开放系统强调 inspectability(可检查性)、 programmability(可编程性)、 community experimentation(社区实验性);封闭系统强调一致性、集成安全、端到端质量控制。两边都不是错,只是服务于不同目标。

OpenCode 代表了开放一侧最重要的价值:宿主必须可理解、可修改、可扩展。它天然适合研究者、平台开发者、工具作者以及需要深度嵌入自定义工作流的团队。代价是,开放系统通常把更多集成工作留给使用者自己处理。

OMO 的价值在于,它进一步证明了开放不是“只能做小修小补”,而是可以在宿主之上搭建出一整套新的编排哲学。换言之,开放平台真正厉害的地方,不是允许你改一点配置,而是允许你重写系统行为的组织方式。

Claude Code 则更偏封闭但不完全封死。它提供扩展面,但在强产品边界内提供。这样换来的是更高一致性、更强安全整合、更完整的商业体验。代价是,有些实验性想法无法立刻落地,只能等待官方暴露能力。

三个系统分别如何回答这五组张力

如果把三者浓缩成三句判断,可以这样概括。

OpenCode 的答案是:先保住一个可编程、可理解的基础,再让上层自己长。

OMO 的答案是:真正决定高级 agent 水平的,不是模型本身,而是编排结构。

Claude Code 的答案是:如果你想把自治真正带进生产环境,就必须把安全、压缩、审批、沙箱做成底层设施。

因此,理想 coding agent 不是简单复制三者中的任何一个,而应该是三者的综合体:在开放性上继承 OpenCode 的平台意识,在任务组织上吸收 OMO 的编排意识,在大规模可部署性上学习 Claude Code 的安全意识。五组张力不会消失,但好的系统不再假装它们不存在,而是逐层地、带着明确优先级地去解决它们。这才是“理想架构”真正应有的成熟度。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第18章 — 理想编码Agent的架构
Token用量: 约 6,200 input + 1,550 output

18.3 三个系统的启示

对 OpenCode、OMO、Claude Code 做足够深入的比较之后,会有三条结论变得很难忽视。它们不是简单的产品口号,而是足以指导后续 agent 设计的原则性启示:OpenCode 告诉我们,可编程性是不可谈判的;OMO 告诉我们,编排质量比 agent 数量更重要;Claude Code 告诉我们,安全并不是自治的限制,而是自治成立的前提。

一、OpenCode 的启示:可编程性不可谈判

OpenCode 最重要的贡献,不只是它开源,也不只是它支持多接口、多扩展。它更深层的贡献是:它提醒我们,coding agent 必须首先是一个可被塑形的平台,而不是一个只能被消费的人格化助手。

为什么说可编程性不可谈判?因为真实的软件工程场景差异太大。不同团队的目录结构不一样,代码规范不一样,审批流程不一样,部署路径不一样,风险模型不一样,甚至“一个好 agent 应该先做什么”这件事都不一样。如果 agent 无法被团队自己的规则和工作流重新塑形,它再聪明,也只能停留在通用演示层面。

这里的“可编程性”不是狭义的“能不能写插件”,而是多层次的。工具能否被注册和组合?会话状态能否被外部系统理解和利用?宿主是否支持不同界面共享同一引擎?配置能否表达团队级策略?第三方是否能在其上构建新的 orchestration layer(编排层)?

OpenCode 的价值在于,它给出的不是封闭黑盒,而是一套相对清晰、可重组的底盘。很多系统虽然也开源,但内部组织很乱,别人很难真正构建在上面。OpenCode 的不同在于,它不仅开放,还具备平台气质。正因为如此,OMO 才有可能在不 fork 宿主的前提下长成一个更复杂的系统。

所以,第一条原则可以写得非常直接:如果一个 coding agent 不能被程序化地重塑,它就不够格成为长期基础设施。

二、OMO 的启示:编排质量大于 agent 数量

OMO 给行业带来的最关键修正,是纠正了“多 agent 越多越高级”这类直觉。多 agent 体系真正难的,不是造出很多角色,而是让这些角色在对的时机、以对的边界、拿着对的上下文、通过对的工具去做对的事情。

也就是说,multi-agent 的核心不是 multiplicity(数量增加),而是 orchestration(编排)。如果编排不好,agent 再多也只会产生重复搜索、相互打扰、结果碎片化、token 浪费和责任边界模糊的问题。很多看似华丽的 swarm(群体)系统,本质上只是在把混乱并行化。

OMO 可贵的地方在于,它把编排当成正式问题来处理。什么时候要委派?委派给谁?要不要后台执行?子 agent 的上下文要窄到什么程度?结果如何回收?todo 如何衔接?规则如何延续?这些都不是边角料,而是系统成败的核心。

这给后续设计一个很重要的原则:不要问“我是否也应该搞 8 个 agent、12 个 agent”,而要问“哪些工作真的值得隔离,哪些工作真的值得并行,哪些工作真的需要专门 prompt,哪些结果真的值得再汇总回来”。如果这些问题没有被认真回答,那么 agent 数量就是伪指标。

换句话说,OMO 的启示不是“多搞点 agent”,而是“把任务组织做成一门工程”。这比表面上的多角色架构深得多。

三、Claude Code 的启示:安全使自治成为可能

Claude Code 最值得学习的一点,是它让我们重新理解了安全在 agent 架构里的位置。很多人下意识会把安全看成一组限制:它让 agent 变慢,增加确认,阻挡自由度。但 Claude Code 的演化方向表明,更准确的说法其实是:没有安全基础设施,就没有可规模化的自治。

原因很现实。只要 agent 有文件系统权限、shell 权限、网络权限、长期运行能力、自动多步执行能力,组织就一定会问:如果它错了怎么办?如果它越权了怎么办?如果它误删、误提交、误操作、误泄露怎么办?

在没有强安全机制的情况下,这些担忧会让自治永远停留在低风险场景里。用户要么频繁确认,要么不敢开权限,要么干脆不用。此时 agent 看起来“理论上很强”,实际上却很难获得真正授权。

Claude Code 的重要之处在于,它把 permission system、审批机制、压缩、审计、特别是 sandboxing(沙箱化)做成了运行时基础设施。这样安全就不再只是写在 prompt 里的提醒,而是由系统边界直接 enforce(强制执行)。一旦做到这一点,自治的提升就不再只是冒险,而是可以被治理、被接受、被部署。

这也是为什么开源系统未来若想进入更广泛的生产场景,不能只强调“开放”和“聪明”,还必须强调“可信执行边界”。否则再好的编排,也可能因为风险不可控而无法获得组织授权。

三条启示如何合并成一套设计原则

把这三条启示放在一起,可以形成一套非常清晰的理想 agent 设计原则。

第一,系统必须可编程。否则它无法适配不同团队、不同仓库、不同流程,也无法成为长期基础设施。

第二,系统必须重视编排。否则多工具、多 agent、多扩展只会让复杂度上升,而不会稳定带来更好的任务表现。

第三,系统必须把安全基础设施化。否则自治能力越强,组织的不信任就越强,最终会把自治本身压回去。

这三者不是并列孤岛,而是相互依赖。可编程性没有安全,容易危险;安全没有可编程性,容易僵化;编排没有前两者,容易沦为昂贵表演。只有三者同时成立,coding agent 才可能既适应现实工作流,又在复杂任务上伸缩,还能被真正放心地交付给团队使用。

因此,三套系统给我们的不是三条互斥道路,而是三个互补的方向:OpenCode 代表平台意识,OMO 代表编排意识,Claude Code 代表部署意识。未来最好的 coding agent,大概率不是三者中的任意一个原样复制品,而是同时吸收这三种意识之后形成的综合体。真正优秀的 agent,不只是会写代码,而是既能被塑形、能被组织、也能被信任。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第19章 — 工具设计的艺术
Token用量: 约 6,600 input + 1,800 output

19.1 ACI原则

如果说过去几十年软件行业不断强调 HCI,也就是 Human-Computer Interface(人机交互),那么在 agent 时代,系统设计者必须同样认真地对待 ACI:Agent-Computer Interface(智能体-计算机接口)。HCI 研究的是人如何理解并操作系统;ACI 研究的是模型如何理解并操作工具环境。二者相似,但绝不是同一个问题。

很多工具对人类工程师看起来非常直观,对 agent 却并不直观。一个函数名含糊一点,人类还能靠经验猜;一个参数名不统一,人类还能看上下文推断;两个能力重叠的工具并列摆着,人类还能试一下再修正。但模型不是这样工作的。它在有限 token 预算内完成规划、选工具、解释输出、推进任务,任何模糊接口都会变成决策噪音。

因此本节的核心主张非常明确:在 ACI 上投入的心力,至少应当与 HCI 一样多。 你会认真设计按钮文案、菜单结构、错误提示、快捷键和确认弹窗,那你也应该认真设计 tool name(工具名)、tool description(工具描述)、参数 schema(结构化参数)、默认行为、返回格式以及误用保护。

这里最实用的一条经验就是:把工具描述写成“给初级工程师看的 docstring(文档字符串)”。 docstring 是很多编程语言中贴在函数、类、模块上的说明文本,用来解释“这个东西做什么、怎么用、注意什么”。为什么说要面向“初级工程师”?因为这样可以同时避免两个极端。

一个极端是写得过短,例如“搜索文件”“执行命令”“读取内容”。这些描述技术上不算错,但对 agent 几乎没有指导意义。另一个极端是写得过抽象、过依赖隐性知识,好像默认使用者已经完全理解系统全貌。这样的描述对模型也并不友好。

好的 ACI 描述应该至少回答四个问题:

  1. 这个工具解决什么问题?
  2. 什么时候该用它?
  3. 什么时候不该用它?
  4. 有哪些边界、风险或相邻替代工具?

比如下面两种描述就有明显差异。

  • “Searches files.”
  • “Search file contents using regex. Prefer this when locating text patterns across many files. Do not use for filename discovery; use glob instead.”

前者只是一个标签,后者才像真正的接口说明。它不仅告诉 agent 这个工具“能做什么”,还告诉 agent “什么时候应该选它、什么时候不该选它”。后者多消耗的那一点 token,换来的是后续大量错误选择的减少,非常划算。

因此,ACI 的第一原则是 affordance clarity(可供性清晰)。可供性本来是设计学/HCI 里的概念,指某个对象是否能让使用者自然感知“它该怎么被使用”。在 agent 场景里,这种可供性主要通过文本和结构来表达。模型要从工具定义中推断的不只是 capability(能力),还有意图边界。

第二个原则,是要把 tool boundary(工具边界) 讲清楚。大多数工具误用,不是因为系统没有能力,而是因为系统里有多个相邻能力,但界线模糊。例如 glob、grep、read、lsp_symbols、ast_grep 五者都和“找代码”有关,但它们解决的是不同层次的问题:文件名模式匹配、内容正则搜索、直接读取、语义符号检索、语法树模式匹配。如果边界不清,模型就会花大量 token 做“选哪个工具”的工作。

第三个原则,是引入 poka-yoke(防错设计)。这是制造业与质量工程里的概念,中文常译为“防呆”或“防误操作设计”。它的思想很简单:不要只靠使用者足够小心,而要把系统设计成不容易犯错。在 agent 工具设计里,poka-yoke 极其重要。

典型做法包括:

  • workdir 作为显式参数,避免 agent 用脆弱的 cd && ... 方式拼 shell;
  • 在 bash 工具说明里明确禁止用它做文件读取,因为有专门的 read 工具更安全;
  • 对高风险工具写清 side effects(副作用)与前置检查要求;
  • 对会产出大量输出的工具做边界限制或分页;
  • 在说明里直接点名相邻替代工具,减少误判;
  • 用强类型 schema 替代模糊自由文本,降低参数填错概率。

也就是说,一个好工具不仅“能用”,还应该被设计成“最顺手的用法大概率就是正确用法”。这就是 agent 世界里的防错设计。

第四个原则,是 semantic consistency(语义一致性)。人类对命名不一致的容忍度很高;模型则更容易在细小差异中产生额外认知负担。如果一个工具用 filePath,另一个用 path,第三个用 filename,第四个用 target,而它们说的本质上都是文件路径,那么模型每次都要做概念对齐。参数命名、字段命名、返回结构、错误风格,越一致越好。

第五个原则,是 progressive disclosure(渐进式展开)。这不是说工具描述要越短越好,而是说应该把最关键的路径信息放在最上面:主要用途、优先选择场景、强烈禁止场景。少见边缘条件可以放在后面。因为 agent 选工具通常发生在活跃执行循环中,描述必须先让它迅速抓住主干。

OpenCode 给我们的启示,是类型化、可编程的工具定义会天然促进 ACI 的整洁。OMO 的启示,是不仅基础文件工具需要好描述,编排类工具也尤其需要强描述,否则 agent 会在委派、回收、后台运行这些高杠杆动作上频繁失误。Claude Code 的启示,则是成熟产品会把大量 anti-footgun guidance(防踩坑指导)直接写进工具契约里,而不是寄希望于模型“自己懂”。

从实践角度,可以给每个工具设计一份 ACI 检查表:

  • 名字是不是动作导向且足够具体?
  • 描述是否说明何时该用?
  • 是否明确说明何时不该用?
  • 参数名是否与系统其余部分一致?
  • 是否写清副作用与安全边界?
  • 如果和别的工具重叠,边界是否已被明确区分?
  • 输出格式是否减轻而不是增加模型后处理负担?

从更大的视角看,ACI 不是工具层面的微优化,而是整个 agent 系统的认知基础设施。差的 ACI 会在每个任务里悄悄收税:选错工具、来回试探、重复纠正、token 浪费、规划不稳。好的 ACI 则会悄悄放大所有能力:更快进入正轨、更稳定地调用工具、更少反复、更高自治可信度。

所以,工具设计绝不是“把函数暴露出来”这么简单。它更像在给模型设计一套工作语言。HCI 决定人是否愿意用你的产品,ACI 则决定 agent 是否真的能稳定用好你的系统。未来构建优秀 coding agent 的团队,必须把 ACI 当成一门正式设计学,而不只是工程附属品。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第19章 — 工具设计的艺术
Token用量: 约 6,400 input + 1,700 output

19.2 最小工具集原则

在 coding agent 设计里,一个非常常见但也非常隐蔽的错误,是把“更多工具”误认为“更强能力”。表面看这很合理:工具越多,能做的事似乎越多。但在实际系统里,过多工具往往会带来相反效果:选择变难、边界变糊、提示变长、描述成本上升、模型规划负担增加。于是本节的核心原则可以浓缩成一句非常硬的话:如果一个人类工程师都很难快速判断该选哪个工具,那么 agent 大概率也很难。

这不是因为 agent 笨,而是因为“选工具”本身就是一项认知任务。只要系统里存在多个重叠能力,模型就必须先花 token 做路由判断,再进入真正的问题求解。如果这些工具之间界限不清,哪怕每个工具单独看都不错,合起来也会显著拖慢系统。

因此,所谓 minimal tool set(最小工具集),并不一定是“数量非常少”,而是“能力重叠最小”。每个工具都必须为自己的存在提供清晰理由:它到底覆盖了哪个独特需求?如果没有它,系统会在哪类任务上显著退化?它带来的价值是否足以抵消它引入的认知表面积?

这里的“认知表面积”不是教科书术语,可以理解为:一个系统需要被模型理解、比较、记忆和选择的接口总面积。工具越多、越相似、越缺乏边界,这个表面积就越大,agent 在真正开始工作前就已经消耗了不少决策预算。

一个健康的工具系统,通常遵循三条审查问题。

第一,这个工具是否真正解决了一类其他工具无法高质量覆盖的任务?

第二,如果移除它,agent 是否会被迫用明显更差的方法来替代?

第三,它的加入,究竟让整个系统更容易理解,还是更难理解?

第三条尤其重要,因为团队最容易忽视系统层面的代价。某个新工具单独看很有用,但如果它和现有工具能力高度重叠,模型就会陷入更频繁的“到底用 A 还是用 B”判断。这样一来,理论能力在增加,实际效率却在下降。

举一个典型例子。代码检索相关工具可能有:文件名模式匹配、内容正则搜索、直接读文件、LSP 符号查询、AST 模式检索、shell 搜索命令。如果每个工具负责的问题层面不同,那么这组工具很强,因为它们构成了一个分工清晰的搜索栈。但如果描述里没有清楚说明“找文件名用 glob,找文本内容用 grep,找语义符号用 LSP,找语法结构用 AST”,那系统能力并不会自然转化成执行质量。

因此,最小工具集原则不只是“少做一点”,更是“把边界做锋利”。

这也解释了为什么设计工具系统时应该遵循 start small, grow by need(从小开始,按需求增长)。系统早期不应该把所有潜在 helper 都暴露为一等工具,而应该先保留少数高频、高杠杆的能力:读取、搜索、编辑、执行命令、符号导航、可能再加网页获取和任务委派。然后观察真实执行中的痛点:

  • 模型是否反复在某类机械工作上耗费大量 token?
  • 某类任务是否总是需要笨拙地组合多步?
  • 是否存在高频失败模式,说明缺少更合适的工具抽象?
  • 某些判断是否完全可以交给宿主,而不该让模型反复脑补?

只有当这些问题反复出现时,新工具才真正“赚回”自己的存在成本。

OpenCode 给出的启示是:可扩展的宿主并不意味着默认就应该暴露尽可能多的工具。可扩展性是能力上限,不是默认工具膨胀的理由。OMO 的启示更有意思:有时真正高价值的工具并不是更多文件操作细节,而是 orchestration primitive(编排原语)。例如 task/delegate 这一类工具,虽然数量上只算“一个工具”,却能显著改变任务组织方式,比很多小 helper 更有杠杆。Claude Code 则展示了另一面:成熟产品的工具数确实可能很多,但前提是它必须同时投入足够多的路由说明、权限设计和输出整形,否则大工具集会迅速变成复杂度陷阱。

最小工具集原则还有一个安全收益。重叠越少,危险动作路径越少,系统越容易在修改、执行、联网等高风险操作上建立统一验证和审计。相反,如果多个工具都能产生相似副作用,安全策略就会变得分散,覆盖面也更难保证。

此外,最小工具集通常也更利于 composition(组合)。小而清晰的工具更容易串成稳定工作流。比如:glob 找候选文件,grep 搜内容,read 读上下文,LSP 查语义,再用 patch/edit 修改。每一步都很明确,模型的规划也更稳。相反,若系统里充满“大而全但互相重叠”的工具,agent 反而更难形成可预测的操作链。

从维护角度看,每增加一个工具,都在增加长期负债:文档、测试、版本兼容、权限审查、与其他工具的交互解释、prompt 中的提及成本。工具数量本质上就是 API surface area(接口表面积)。一旦暴露出去,就会成为系统认知负担和兼容负担的一部分。

所以,最强的表述应该是:一个工具是否值得存在,不看它是否“有点用”,而看它是否降低了整个系统的总认知成本。 它如果带来一点能力,却引入更多选择困难,那就是净负收益。

最小工具集不是节食主义,不是为了“看起来简洁”而强行删功能。它的真正目的,是尊重模型有限的规划带宽,把更多 token 留给真正需要判断、解释、综合的部分。优秀的 agent 平台不会先问“我们还能再暴露什么”,而会先问“哪些决策根本不该再让模型去纠结”。这,才是最小工具集原则的价值所在。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第19章 — 工具设计的艺术
Token用量: 约 6,700 input + 1,850 output

19.3 工具输出的认知成本

讨论 agent 工具设计时,人们往往最先关注“这个工具能不能做某件事”,却常常忽略另一个同样关键的问题:这个工具的输出,会迫使模型额外做多少脑力活? 对 agent 来说,输出格式不是表面问题,而是直接决定可靠性、延迟、token 成本和稳定性的核心因素。

本节的核心原则可以直接表述为:把工作路由给最便宜且最可靠的执行者。 如果某件事可以由确定性算法完成,就不该交给 LLM;如果数据库或索引系统能做,就不该先把原始材料倒给模型再让它手动整理;如果输出本来就应该是排序后的、分组后的、裁剪后的状态,那就应该由宿主先整理好再交给模型。

最经典的例子就是排序。让 LLM 去给一组数据排序,既贵又不稳定;让程序里的 sort 算法去做,几乎免费而且结果保证正确。这个例子听起来很基础,但它揭示的是更一般的原则:模型不应该替计算机做机械整理。

在真实工具系统里,这种错误经常以更隐蔽的形式出现。比如:

  • 搜索工具直接吐出几百条原始匹配,而实际上模型只需要按文件聚合后的前十条;
  • 目录读取结果顺序不稳定,模型每次都要重新理解排序关系;
  • 诊断工具返回大块非结构化文本,而不是按 severity(严重级别)和位置分组;
  • diff 工具把大量上下文噪声一起返回,模型得自己筛;
  • 统计信息本来可以提前计算,却交给模型在上下文里再数一遍。

这些都在制造 cognitive cost(认知成本)。这里的认知成本不是心理学严格定义,而是一个工程表达:模型为了把机器输出变成“可决策状态”,还要额外花多少 token 和推理步骤。越多这类机械性加工,模型可用来做真正高价值判断的预算就越少。

因此,工具设计者要不断问自己:输出里哪些是 useful signal(有用信号),哪些只是 mechanical burden(机械负担)?前者服务于判断,后者本应由宿主或算法先处理。

一个高质量工具输出,通常有四个特点。

第一,预结构化。信息一出来就是贴近下一步决策的形状。比如搜索工具支持 contentfiles_with_matchescount 三种模式,让 agent 直接拿到它当前最需要的抽象层级,而不是永远接收最大量原始数据。

第二,有边界。默认输出不能无限膨胀。可能很大的结果,应该支持 limit、分页、摘要视图和进一步展开路径。否则模型会被海量无关细节淹没。

第三,稳定。顺序尽量确定、字段命名统一、相同状态下重复调用结果风格一致。稳定性会显著降低 agent 的理解摩擦。

第四,面向用途。工具返回的不是底层库最容易吐出来的格式,而是最利于后续行动的格式。带行号的文件内容比纯文本更利于定位;按严重级别分组的诊断比原始 dump 更利于排序处理;已经过滤掉噪声的 diff 比原始混杂输出更利于决策。

这背后其实对应三类不同 executor(执行者):

  1. Deterministic executor(确定性执行者):排序、计数、验证、解析、过滤、结构化变换;
  2. Retrieval executor(检索执行者):搜索引擎、索引、数据库、LSP、MCP 服务;
  3. Model executor(模型执行者):解释、优先级判断、综合、规划、歧义消解。

很多系统出问题,不是模型不会做高层工作,而是架构让模型去冒充前两类执行者。于是 agent 看起来很“笨”或“浪费”,本质上并不是 intelligence failure(智能不足),而是 labor misallocation(劳动分配错误)。

OpenCode 给出的启示,是工具职责分层清楚会自然推动输出更可控。OMO 的启示,是编排工具不只是“再加一个功能”,而是可以帮助系统把工作转移给更合适的执行者,例如把探索、检索、验证拆给不同上下文和不同工具链。Claude Code 则展示了更成熟产品的一种方向:通过强输出整形,让模型少做机械工作,多做软件工程判断。

这里还有一个非常现实的 token economics(token 经济学)问题。工具明明很好,但如果每次调用都返回冗长文本,模型就要反复读、反复扫、反复整理。这样工具越多,系统反而越贵。于是未来好的工具,不一定是“返回最多信息”的工具,而更可能是“返回最恰当状态”的工具。

这会带来一个重要设计原则:围绕 decision point(决策节点)设计输出,而不是围绕后端实现方便设计输出。

如果模型接下来要决定“先读哪个文件”,那搜索结果就应该帮助它快速锁定候选;

如果模型接下来要决定“先修哪个错误”,那诊断结果就应该突出严重度和位置;

如果模型接下来要判断“这个动作是否安全”,那输出里就应该包含策略相关信号,而不是让模型自行猜测。

换句话说,工具输出不应该只是 data return(数据返回),而应该是 decision-ready state(可直接进入决策的状态)。这是工具设计成熟与否的分水岭。

未来 agent 工具栈大概率会越来越像一个认知流水线:检索层先找准材料,确定性层先做便宜而正确的整理,模型层最后做需要主观判断和综合推理的部分。只要这个分工做对了,系统就会显得更聪明、更快、更稳。因为模型终于不再被迫把 token 花在本该由程序先完成的整理劳动上。

因此,评估一个工具时,不能只问“它能不能拿到信息”,更要问“它的输出逼着模型再做多少本不该做的机械活”。如果答案是很多,那这个工具即便功能强,也仍然是未完成设计。真正优秀的工具,返回的不是原材料,而是下一步行动所需的清晰状态。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第19章 — 工具设计的艺术
Token用量: 约 6,800 input + 1,850 output

19.4 工具组合 vs 工具膨胀

在 coding agent 设计里,一个非常关键但经常被误判的问题,是系统到底是在形成 tool composition(工具组合能力),还是正在滑向 tool bloat(工具膨胀)。表面上,二者都可能体现为“工具越来越多”;但本质上,它们是完全不同的两件事。

工具组合,指的是一组少量但边界清晰的工具,可以像语言里的基础语法那样自然拼接,形成大量稳定工作流。工具膨胀,则指的是工具越来越多,但很多只是局部重复、边界模糊、需要额外解释,最终让模型的路由成本不断升高。前者带来杠杆,后者带来摩擦。

因此,单纯比较工具数量并不能直接得出优劣,但数量仍然是一个很好的切入口。Claude Code 某个阶段可能有 61 个工具,OMO 某个阶段可能有 26 个工具。问题不在于 61 是否一定优于 26,而在于:这 61 个工具是否真正形成了更大的可组合能力空间,还是只是增加了选择复杂度?这 26 个工具是否足够构成高杠杆工作流,还是只是因为功能不全而显得精简?

这里 OMO 提供了一个很重要的例子:task 工具作为 orchestration primitive(编排原语)。所谓原语,可以理解为某种“基础操作单元”,它本身并不等同于最终功能,但它能作为更大结构的搭建积木。Task/delegate 这一类工具的价值,不只是“又多了一个工具”,而是它改变了整个系统的行动语法。

在没有 task primitive 的系统里,agent 往往只能在单一上下文里做所有事:查资料、搜代码、验证假设、生成总结、继续推进。加入 task primitive 之后,系统突然多出了一整类新动作:可以把某个子问题切出来,交给更窄上下文、更合适 prompt、甚至后台并行的子 agent 去做,然后在稍后把结果回收回来。这不是单点能力增加,而是工作流维度的扩展。

这就是真正的 composition。一个工具的价值,不只看它直接做了什么,还要看它是否改变了其他工具被组织起来的方式。能放大整个系统组合空间的工具,通常比十个局部 helper 更有价值。

反过来看,tool bloat 往往有几个明显征兆。

第一,多个工具解决的是非常相近的问题,但命名、参数、返回格式又不完全一致,模型需要反复比较。

第二,很多工具只有在 prompt 强行提醒时才会被使用,缺乏自然工作流位置。

第三,新增工具没有打开新的能力空间,只是为原有路径再提供一条差不多的替代路线。

第四,系统文档需要花大量篇幅解释“这个工具和那个工具有什么微妙区别”,这往往意味着边界本身设计得已经不够健康。

Claude Code 的大工具表面展示了一个成熟产品会面临的真实张力:随着功能扩张,工具数量上升是自然的。浏览器交互、任务管理、系统操作、搜索、诊断、扩展、记忆、后台任务,都会推高库存。问题在于,工具一多,系统就必须同步投入更强的 ACI、权限边界、路由提示和输出整形,否则工具数增长很快就会转化成工具膨胀。

OpenCode 的启示则更偏底层:如果宿主本身的注册模型、命名空间、执行语义不清晰,那么上层无论加多少工具,都很难形成高质量组合。也就是说,组合能力不是工具数量自然堆出来的,而是要靠底盘质量托住。

判断一个工具体系更偏“组合”还是更偏“膨胀”,可以看几个信号。

其一,主要工作流是否能被表达成少数清晰工具的短链条。比如搜索 → 读取 → 编辑 → 诊断 → 测试,或者委派任务 → 后台执行 → 结果回收。这种链条如果自然,就说明系统存在组合逻辑。

其二,工具之间是否低重叠。模型是否经常在三个看起来差不多的工具之间犹豫?如果是,说明膨胀风险很高。

其三,系统中是否存在 multiplier tools(乘数型工具)。这类工具不是只能做一件小事,而是能改变其他工具的组合方式。Task、patch、session search、semantic navigation 这类工具通常就属于乘数型。

其四,工具文档整体是否能看出一套系统逻辑,而不是一堆彼此独立的零散说明。真正可组合的工具表,通常会有明显的内部结构。

这里可以借用一个来自线性代数的比喻:basis(基)。在线性代数里,基是一组最小向量集合,可以通过组合生成更大空间。类比到 agent 工具设计,一个好的工具集也应该像“工作流空间的基”。也就是说,不必太多,但应该足够强,足够正交,足够能组合出主要任务路径。

如果一个新工具的加入能显著扩展这个“基”的表达空间,它就值得;如果它只是给已有路径再多添一个差不多的替代物,它更可能是膨胀。

这也解释了为什么“更多不一定更好”。新增工具必须通过更高标准审查:它是否打开了新型工作流?是否替代了笨拙而常见的多步模式?是否降低了别处的认知负担?如果这些问题都答不上来,那它即使看起来有用,也很可能只是复杂度的伪装。

从三套系统里,我们可以提炼出一个很清晰的结论。OpenCode 告诉我们,组合能力首先取决于底层宿主是否清晰。OMO 告诉我们,真正高杠杆的往往是编排原语,而不是单纯工具数。Claude Code 告诉我们,大工具表不是原罪,但必须用相应级别的产品化设计去消化它。

所以,工具设计的最终目标从来不是“库存最大化”,而是单位认知表面积上的杠杆最大化。能组合,就会放大能力;会膨胀,就会抬高摩擦。优秀的 coding agent 平台,看的不是自己暴露了多少工具,而是这些工具能否组成一个清楚、稳定、可扩展的行动语言。这才是工具组合与工具膨胀之间最本质的分界线。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第20章 — 上下文工程
Token用量: 约 6,500 input + 1,800 output

20.1 从提示工程到上下文工程

在 LLM 应用的早期阶段,“Prompt Engineering(提示工程)”几乎是最流行的关键词。那时大家觉得,只要把指令写得更清楚、更聪明、多给几个例子,模型表现就会明显提升。这种理解在早期是成立的,因为当时系统相对简单,很多应用确实就是“一段提示词 + 一个模型 + 一个输出”。

但 coding agent 的出现,把这种理解迅速推到了边界。因为一个真正工作的 agent,从来都不是只靠“一段 prompt”在运行。它实际看到的是一个不断变化的 token 状态:system prompt、tool schemas、用户输入、项目规则、会话历史、工具输出、记忆、摘要、检索片段、子任务结果、宿主注入信息……当这些东西叠在一起以后,问题就不再是“提示词怎么写得更漂亮”,而是“模型在这一刻到底看到了什么”。也正因此,行业开始从 Prompt Engineering 转向 Context Engineering(上下文工程)

所谓提示工程,本质上是研究“如何写指令”;而上下文工程研究的是“如何策划模型在当前步骤看到的全部上下文状态”。这两个层次差别非常大。前者更像文案与交互技巧,后者更像信息系统设计。

在提示工程思维下,人们常问的问题是:系统提示词该怎么措辞?角色要怎么写?few-shot example(少样本示例)该给几个?什么语气会让模型更稳?这些问题依然有价值,但它们只是整体问题的一小部分。

在上下文工程思维下,问题会变成另一组:当前哪些信息必须在场?哪些信息不该在场?哪些内容应该摘要化?哪些内容应该按需检索?哪些是长期记忆,哪些只是瞬时工作状态?工具输出应如何整形?上下文窗口快满时该如何优雅恢复?如何避免上下文在长会话中逐渐腐坏?

可以看到,后者已经明显不是“写句子”的问题,而是系统工程问题。

为什么 coding agent 会强迫行业完成这个转变?因为这类系统的失败,往往并不是某句话写得不够好,而是模型处在错误的信息环境中。它可能看了错误文件,保留了过时假设,被无关工具输出淹没,漏掉了项目规则,又或者背着一段太长太脏的历史记录继续工作。也就是说,真正的失败点经常不是 instruction wording(指令措辞),而是 context state(上下文状态)。

所以,上下文工程可以被更准确地理解为 token-state curation(token 状态编排/策展)。这里的策展不是标准计算机术语,借用了策展人安排展品的比喻:不是把所有内容都堆出来,而是精心决定什么该被摆在当前视野里、什么该暂时移走、什么该作为背景、什么该作为重点。对模型而言,每一个 token 都在竞争注意力。好的 token 会帮助判断,坏的 token 会稀释判断。

OpenCode 已经在往这个方向走,因为它把 session、message、compaction、instruction layering 这些内容当成正式架构问题来处理,而不是“顺手拼 prompt”的细节。OMO 则进一步强化了这种思路:规则注入、continuation、hook 驱动上下文变换、task-scoped context,这些都说明它已经不把“提示词”当成唯一中心,而是把上下文视作动态拼装的运行时状态。Claude Code 则把这件事产品化:memory、auto-compact、持久规则与临时工作状态分层,让用户感受到的是“系统持续懂我”,而不是“我每次都要重复说”。

从实践角度看,这种转向会带来几个重要后果。

第一,system prompt 往往应该比人们想象得更小。真正稳定、长期有效的原则才应该留在这里;那些任务局部、时间敏感、可按需获取的细节,不应永久钉死在系统提示里。

第二,retrieval(检索)会成为中心机制。你不再试图把一切都提前塞进 prompt,而是在需要的时候拉入相关规则、文件片段、历史决策或文档说明。

第三,summary(摘要)不再只是聊天便利功能,而是正式工程产物。一个高质量的紧凑摘要,往往比十几轮原始对话回放更有价值,因为它保留了真正相关的状态。

第四,tool output 也属于上下文的一部分。如果工具输出又长又乱、没有结构,那它会直接污染上下文质量。因此,上下文工程不仅是“往里放什么”,也是“工具吐出来的东西长什么样”。

第五,memory 必须分层。用户长期偏好、项目恒定规则、仓库长期事实,适合进入 durable memory(持久记忆);某次实验结果、暂时假设、局部探索发现,则应该只停留在 working context(工作上下文)中。

这种转向还会改变评估方法。过去团队可能主要测试 prompt A 和 prompt B 哪个好;现在更值得测试的是 context policy(上下文策略)A 和 B 哪个好:少注入几个文件会不会更稳?工具输出先摘要再给模型会不会更好?把规则和任务状态拆开维护会不会降低冲突?更早做委派会不会减少主上下文污染?这些策略常常比几个句子换个说法更影响结果。

从更深层看,提示工程把模型想象成一个“阅读说明书的聪明读者”;上下文工程则把模型看成一个“运行在信息架构中的组件”。后者显然更接近 coding agent 的现实。因为模型的表现不仅取决于它听到了什么,也取决于周围有哪些信息、缺了哪些信息、这些信息之间的结构关系是什么,以及系统如何随着任务推进不断重排它的视野。

所以,未来 coding agent 的进步,当然仍然会受益于更强模型和更好提示词,但真正的大头越来越来自:让模型在正确的时间看到正确的信息,并且以正确的形式看到。 这就是上下文工程的本质。

一旦理解了这一点,很多看似分散的最佳实践就会自动串起来:最小 system prompt、JIT retrieval、compaction、structured notes、long-term memory、sub-agent 隔离、overflow recovery。这些都不是孤立技巧,而是同一门学问的不同侧面——像管理 CPU、内存、网络一样,管理模型的 token 状态。

提示工程教会行业如何“对模型说话”;上下文工程则教会行业如何“为模型布置思考环境”。对 coding agent 来说,后者显然是更高阶、也更关键的能力。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第20章 — 上下文工程
Token用量: 约 6,700 input + 1,850 output

20.2 四种记忆策略

上下文工程真正落到可执行层面,离不开对“记忆”这件事的重新理解。很多人会把记忆简单理解成“把历史留着”,但对 coding agent 来说,这远远不够。好的系统不会把 memory 当成一个混在一起的大桶,而会采用多种不同的记忆策略,分别应对不同问题。最值得单独讨论的四种策略是:JIT retrieval(即时检索)compaction(压缩)structured notes(结构化笔记)sub-agents(子智能体)

这四种策略并不互斥,反而常常协同工作。它们真正回答的是四个不同问题:信息应该何时被拿进来?历史应该何时被压缩掉?哪些状态应该显式写下来?哪些工作应该被放到独立上下文里?

一、JIT retrieval:需要时再取

JIT 是 just-in-time 的缩写,原意来自制造与系统设计中的“准时制/按需供给”。放到 agent 语境里,JIT retrieval 指的是:不是一开始就把所有可能相关的信息塞进上下文,而是在确定需要的时候再检索进来。

这在仓库级 coding work 里特别重要。一个大型代码库有成千上万文件,不可能也没必要先全塞给模型。更合理的方式是:先搜索,再读局部;先定位,再深入。只有当前假设真正需要某个文件、某条历史、某段文档时,才把它拉进上下文。

JIT retrieval 最适合“相关信息范围很大,但当前真正相关的子集未知”的场景。比如项目文档库、历史会话、代码仓库、外部 API 文档。它的优点是节省上下文预算、减少噪音;缺点是如果搜索系统太弱,或者检索路径设计不好,可能导致频繁往返。

OpenCode 通过文件工具、搜索工具、会话结构为这种策略提供了基础。OMO 则把它做得更动态,比如通过 rules injector 只在合适时机注入规则。Claude Code 虽然对用户暴露得更少,但其 memory 与 retrieval 行为本质上也在做类似事情。

二、Compaction:让历史变轻

Compaction 可以直译为压缩,但在 agent 系统里它不是简单文本压缩,而是在保留有效状态的前提下,把长历史折叠成短而可继续工作的形式。长任务进行到一定阶段后,原始历史会越来越长,模型不得不花很多 token 回看自己已经做过的事。这时,如果继续硬扛,效率和稳定性都会下降。

所以 compaction 的目标不是“把东西变短”这么简单,而是保留:任务目标、已完成动作、关键发现、未解决问题、当前计划,以及必须继续遵守的约束;同时舍弃:冗长表述、已经无用的岔路、重复确认和过细过程细节。

什么时候适合用 compaction?答案很直接:当历史已经学会了它该教会模型的东西,而继续完整重放它反而开始拖累判断时。

Claude Code 的 auto-compact 代表的是产品级实现:系统主动感知上下文压力并压缩。OpenCode 的 session compaction 展示了框架层机制。OMO 则说明 compaction 不只是窗口大小触发,还可能和工作流、todo、continuation 状态一起被组织。

三、Structured Notes:把中间状态显式写出来

Structured notes 可以理解为“面向机器消费的有结构笔记”。它不是普通聊天记录,而是对当前任务状态的显式编码。里面通常会写:当前目标、已知事实、关键文件、待验证假设、风险点、下一步动作、未完成事项等。

为什么这很重要?因为大量 coding task 的关键发现,往往字数很短、价值却极高。例如:“只在 macOS 下复现”“问题发生在兼容层而非核心模块”“测试都过了,只差 snapshot 更新”“旧配置仍然被 hook 注入”。这些如果埋在聊天历史里,模型以后要重新找出来很贵;如果被提炼成结构化笔记,就会成为非常稳定的工作记忆。

什么时候适合用 structured notes?凡是任务跨很多步、中间发现又需要长期保留、或者人类和 agent 都需要共享稳定检查点时,都适合。OMO 的 todo discipline(待办纪律)和 continuation 很接近这种思路。Claude Code 的 memory 系统也朝这个方向演化,只是产品包装更强。OpenCode 则给上层实现这种状态对象提供了灵活底座。

四、Sub-agents:把记忆拆到独立上下文里

很多人谈 sub-agents 时只把它们当作一种编排方式,但其实它也是一种记忆策略。因为一旦委派出一个子 agent,系统本质上就创建了一个新的上下文分区。它不再要求主上下文持续吸收所有局部细节,而是让一小块工作在一小块记忆空间里完成。

这种方法特别适合需要 scope isolation(作用域隔离)的任务:代码库探索、外部文档检索、独立验证、平行调查、审阅复核。通过子 agent,主上下文可以只保留问题定义和结果摘要,而不用承受整个局部探索过程的全部细节。

当然,sub-agents 不是没有成本。它有启动成本、总结成本、编排成本。如果任务本身很小、上下文污染也不严重,那委派反而得不偿失。只有当“上下文隔离收益”大于“委派额外成本”时,sub-agent 才值得使用。OMO 是这方面最鲜明的例子,Claude Code 更保守地使用,OpenCode 则提供其底层可实现性。

什么时候该用哪一种

这四种策略可以很简洁地对应四个问题。

  • JIT retrieval:我现在需要事实,但还不知道哪些事实最重要;
  • compaction:我已经学到了很多,不能再背着原始历史继续走;
  • structured notes:我需要把关键中间状态稳定地存下来;
  • sub-agents:这块工作不该继续污染主上下文,应该独立处理。

在优秀系统里,这四者往往会串起来工作。主 agent 先按需检索,发现有价值的信息后写进结构化笔记;历史太长时做压缩;遇到特别适合隔离的子问题时,再委派给子 agent。这样形成的不是“单一记忆”,而是一套分层记忆架构。

其核心思想是:记忆不等于把一切都留住,而是决定什么该加载、什么该保留、什么该凝缩、什么该外化、什么该隔离。很多人把大 context window 误认为记忆问题的终结,其实它只是延后了问题的暴露。真正让系统稳定的,不是窗口更大,而是记忆策略更清晰。

所以,对 coding agent 来说,优秀的记忆不是“记得最多”,而是“记得最有选择性”。JIT retrieval、compaction、structured notes、sub-agents,正是这种选择性如何变成正式架构的四种典型方式。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第20章 — 上下文工程
Token用量: 约 6,500 input + 1,800 output

20.3 自动上下文注入

在高级 agent 架构里,有一个非常强大、但也非常容易被滥用的能力,叫做 automatic context injection(自动上下文注入)。它的基本思想是:不要每次都让用户或模型手动重复规则、记忆和项目约束,而是由宿主系统在合适的时间,把合适的信息自动拼进当前上下文。

如果这件事做得好,agent 的稳定性和一致性会显著提高;如果做得差,它会变成一种隐形 prompt 膨胀机制,让系统越来越重、越来越不可解释。

为什么自动上下文注入如此重要?因为 coding agent 从来都不是在真空里工作。它总是位于某个项目、某个团队、某套规范、某个长期流程里。比如:

  • 修改完必须先跑诊断;
  • 不要改生成文件;
  • 优先用 patch/edit 工具而不是 shell 直接改文件;
  • 某些术语需要额外解释;
  • Git 提交必须遵循某种安全协议;
  • 某些路径只读;
  • 某些测试必须在最后一步执行。

这些规则如果每次都靠人类重复,系统会非常笨重;如果模型自己从过去历史里“猜出来”,又很不稳定。因此,自动注入会成为更现实的做法。

OMO 在这方面的代表性非常强,尤其是它的 rules injector(规则注入器) 和更广义的 hook 系统。它的关键思想是:不是所有规则都适合永久写在 system prompt 里。很多规则只在特定场景、特定阶段、特定工具调用之前才有意义。因此,它把上下文视为运行时动态拼装流,而不是一次性写死的固定文本。

Claude Code 的做法则更偏 memory system。用户会感觉系统“记住了”偏好、约束、项目习惯,好像一种持续的产品体验。但从架构角度看,这本质上仍然是上下文注入:某些持久记忆在当前回合被激活并加入活跃上下文。

OpenCode 的价值在于,它把 instruction management(指令管理)留作可编程框架能力。也就是说,在 OpenCode 视角里,自动注入不只是产品技巧,而可以成为一种明确的架构模式,甚至供扩展层去重写与增强。

自动注入最明显的好处,是 consistency(一致性)。只要项目级规则是真的稳定存在,那它们就不应该依赖用户重复输入。Agent 在不同任务中都能自动继承这些规则,才说明系统真的在一个“项目环境”中工作,而不是每轮都像失忆重来。

第二个好处,是 locality(局部性)。不是所有规则都值得一直放在全局 prompt 顶部。某些规则只有在某个决策点附近才最有价值。例如:

  • 在调用 bash 前提醒:读取文件优先用 read 工具;
  • 在提交代码前提醒:先查看 git status / diff / log;
  • 在上下文压缩前提醒:保留 todo 和任务锚点;
  • 在危险操作前注入审批或约束语句。

这种局部注入,比把所有规则永远钉在全局 prompt 里更节省、更有效。因为它把信息放到了真正需要它的地方。

但自动注入也有三类非常典型的风险。

第一类风险是 invisible bloat(不可见膨胀)。系统不断“好心地”注入东西,最后活跃上下文在用户看不见的地方越长越重。由于这些信息不是显式手动输入的,性能变差时也更难诊断。

第二类风险是 instruction collision(指令碰撞)。系统级规则、项目级规则、用户偏好、临时任务约束、记忆条目,全都可能同时被注入。如果没有明确优先级,模型就可能收到互相冲突的信号。

第三类风险是 opacity(不透明性)。用户可能不清楚 agent 为什么会按某种方式行动,也不知道究竟是哪层记忆或规则在起作用。这样一来,信任和可调试性都会下降。

因此,自动上下文注入要想成为优点,而不是隐患,至少需要五条纪律。

第一,必须 selective(有选择地注入)。只注入当前任务或当前决策点真正相关的内容。

第二,必须有 clear precedence(明确优先级)。系统要清楚定义:系统策略、项目规则、用户记忆、任务局部状态,谁优先、谁覆盖谁。

第三,必须 compact(保持紧凑)。能用一句话表达的规则,就不要每次展开成一段长文。

第四,必须 observable enough(足够可观察)。不一定要让普通用户看到所有细节,但至少系统开发者和高级用户应能理解当前有哪些上下文层在生效。

第五,应该偏向 runtime assembly(运行时组装),而不是把所有注入都提前固化进一个越来越胖的 system prompt。自动注入的价值,本来就是避免全局 prompt 膨胀。

从三套系统可以提炼出一个共同趋势:高级 agent 的自动上下文注入已经不是可选项。OMO 展示了 hook 驱动的动态注入能力;Claude Code 展示了 memory 驱动的持续注入体验;OpenCode 展示了指令拼装管线本身可以成为扩展接口。

未来最好的 agent 很可能越来越不像“带着一大坨固定提示词的聊天机器人”,而更像“每一步都在按需拼装活跃上下文的运行时系统”。但这个未来只有在注入足够克制时才成立。否则,automatic context 很容易沦为 hidden prompt sprawl(隐藏式提示词膨胀)的新名字。

自动上下文注入的目标,从来不是给模型更多文字,而是在对的时间,给它对的那一小段文字。只有做到这一点,它才是真正的上下文工程,而不是另一种形式的堆料。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第20章 — 上下文工程
Token用量: 约 6,600 input + 1,850 output

20.4 上下文窗口溢出恢复

更大的 context window 的确改变了 agent 设计的经济学,但它并没有消灭“溢出”这个问题。coding task 仍然会变长,工具输出仍然会堆积,记忆层仍然会叠加,探索过程仍然会制造大量局部噪音。所以,成熟系统已经不再把 context window overflow(上下文窗口溢出)当成罕见事故,而是把它视为一种正常运行状态,需要正式的恢复机制。

所谓 overflow recovery(溢出恢复),本质上就是:当原始 token 状态已经无法完整带入下一轮时,系统如何保住任务连续性。它不只是“做个摘要”,而是要在记忆压力下实现优雅退化。

OMO 有一个非常直观的例子:anthropic-context-window-limit-recovery hook。名字很具体,但背后的架构思想具有普遍性。它不等到会话直接崩掉,而是在检测到上下文上限问题时,主动进入恢复流程:保留 todo、重述任务锚点、压缩关键发现、恢复下一步行动姿态。这里最重要的不是 hook 名字,而是它体现出来的心态:溢出不是异常边缘情况,而是工作流事件。

Claude Code 则用更产品化的方式回答同样问题,即 auto-compact(自动压缩)。用户不一定会看到非常显式的“现在开始恢复”,但系统会主动折叠历史、保留有效记忆、继续推进任务。这比把溢出直接暴露为 hard failure(硬失败)要成熟得多。

OpenCode 给出的则是框架层启示:只有当 session、message、compaction 本身已经是正式架构概念,溢出恢复才能被系统化实现。否则系统连哪些状态该保、哪些状态可丢都说不清,更谈不上安全压缩。

这里最关键的区分,是 graceful degradation(优雅退化)hard failure(硬失败)

硬失败很好理解:上下文满了,任务中断,用户必须重新开局、手动重述目标、自己试图回忆系统刚才做到哪里。这是最糟的体验,因为它不仅浪费时间,还极容易丢掉一些用户自己都记不全的细微状态。

优雅退化则是相反的思路:系统优先丢弃低价值上下文,保留高价值状态。原始长历史变成摘要,局部探索细节变成结构化笔记,已完成分支被折叠,长期规则继续留存,当前任务重新锚定。用户感受到的是“系统变轻了,但没失忆”。

一个真正可靠的溢出恢复体系,至少需要五个部件。

第一,系统必须有 state tiers(状态分层)。持久规则、长期记忆、当前任务状态、原始聊天历史,不能被一视同仁地处理。

第二,系统要有 compaction triggers(压缩触发器)。不能总等到窗口彻底满了才被动处理。更好的系统会在接近上限前就启动压缩或清理。

第三,系统要有 structured preservation(结构化保留)。恢复时至少应该保存:当前目标、已完成步骤、关键发现、未决问题、重要文件、下一步计划。

第四,系统要有 resumability(可继续性)。恢复之后,agent 不只是“记得以前发生过什么”,而是真正知道“现在该继续做什么”。

第五,系统要有 observability(可观察性)。用户或开发者最好能知道:发生了压缩、保留了哪类状态、为什么系统现在还能继续。

Sub-agents 在这里也扮演重要角色。委派本身就是一种防止主上下文被局部细节淹没的手段。把探索、调研、验证等局部任务扔进独立子上下文,可以显著降低父上下文膨胀速度。也就是说,好的 orchestration(编排)不只是任务组织方式,也是在降低溢出概率。

另一个容易被忽视但非常关键的原则是:溢出恢复必须尽量保留 intent(意图),而不只是 facts(事实)。一个差的摘要也许保留了文件名、命令、结果,但如果它丢掉了“当前在试图证明什么”“为什么刚才否定了某条路径”“接下来为什么要走这一步”,那恢复后的 agent 仍然会像是断片。真正好的恢复,保留的不只是资料,还有方向感。

这也是为什么 structured notes 和 compaction 关系如此紧密。如果系统平时就把关键任务状态写成显式结构,那么溢出时就不是从混乱聊天里临时抢救信息,而是从已有状态对象中提取关键部分。需要推断的越少,恢复损失就越小。

随着上下文窗口越来越大,有些构建者会产生一种错觉:既然窗口很大,也许溢出工程可以先不做。这其实是危险判断。更大的窗口只是推迟了问题发生的时间,并没有改变其性质。甚至还可能让系统养成更懒散的上下文习惯,等到真的撞上边界时,累积的垃圾状态反而更多。

因此,更成熟的态度应该是:从一开始就按“必然会溢出”来设计。假设任务会很长,工具输出会很脏,历史会很厚,局部探索会很多,然后提前准备好压缩、恢复、再锚定的机制。这样系统在边界处才不会显得脆弱。

OMO 的显式恢复 hook 与 Claude Code 的自动压缩,代表了两种不同风格:前者更像把溢出处理成一个清楚可见的编排事件,后者更像把恢复打磨成用户几乎无感的产品能力。两种方式都比“等溢出后直接报错”要成熟得多。

归根结底,context window overflow recovery 并不是一个边缘附加功能,而是决定 agent 是否“有韧性”的关键部分。会在上下文边界处直接硬崩的系统,看起来总是不够工程化;能压缩、能恢复、能继续推进的系统,才真正像一个为长任务而生的工具。对 coding agent 来说,这种差别非常大,因为真正重要的工作,往往恰恰就是那些长、杂、会把上下文逼到边缘的工作。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第21章 — 多智能体编排的艺术
Token用量: 约 6,200 input + 2,050 output

21.1 五种编排模式

“多智能体”不是一种单一架构,而是一组不同的协调拓扑。两个系统都可能会启动 subagent,但它们的真实行为可能完全不同,因为任务如何拆分、控制权如何流动、上下文如何传递、结果如何合并,决定了系统的本质。对于编码智能体而言,最值得分析的五种模式是:Orchestrator-Worker(编排者-执行者模式)Pipeline(流水线模式)Swarm(群体并行模式)Mesh(网状协作模式)Hierarchical(层级式模式)。这里的“拓扑”不是传统 CS 教材里最常见的 agent 分类词,但借用分布式系统里的结构视角来理解非常合适:重点不是有多少节点,而是节点之间怎么连接。

先看 Orchestrator-Worker。它的核心是一个中心编排者负责和用户保持主契约:拆任务、派子任务、收结果、做最终综合。很多实际系统都会从这里起步,因为它最容易追责,也最容易调试。OMO 在这方面非常典型:父会话保持主控地位,后台子智能体负责局部工作,通知机制把结果送回父上下文。Claude Code 也能做类似的事情,只是呈现方式更“产品化”,用户看到的是任务被派出去了,而不是显式的 runtime 编排图。OpenCode 则更像底层宿主,它给你 agent 能力和插件能力,但不强制你采用这种监督结构。这个模式最大的优点是控制力强,最大的缺点是中心节点会成为瓶颈:如果总控拆分错误,下面再多 worker 也会低效。

第二种是 Pipeline。流水线模式不是“很多 agent 一起讨论”,而是“工作沿着若干阶段顺序推进”。比如第一阶段搜集证据,第二阶段分析原因,第三阶段执行修改,第四阶段验证,第五阶段整理结果。在系统工程里,这种结构的价值很大,因为阶段边界清楚,失败点更容易定位。OpenCode 天然很适合被理解为 Pipeline,因为它本身就是一条线性的 ReAct 主循环。OMO 则把流水线推进到了策略层:消息变换、hook 链、工具守卫、续跑恢复、通知这些环节,本质上都是串联工序。Claude Code 也很有流水线特征,只不过它更把流水线放在权限、安全、压缩和产品体验层。换言之,Pipeline 的关键不是“顺序”本身,而是把复杂行为拆成可检查的阶段

第三种是 Swarm。这个词在传统教材里并不是 agent 系统的标准一级术语,这里可以把它理解为“群体式并行搜索结构”:多个子智能体同时工作,中心控制相对较弱,重点是覆盖面而不是严格过程一致性。Swarm 特别适合大仓库搜索、多个方案并行尝试、外部信息广撒网检索这类任务。OMO 是三者里最像真正 swarm 系统的,因为它明确支持后台并发、模型/提供商并发上限、角色化子智能体以及结果回收。Claude Code 也能做出某种 swarm 效果,但更收敛、更受控。OpenCode 本身不天然偏 swarm,而是允许开发者在其之上自行搭建。Swarm 的优点是广度,缺点是成本容易失控、重复劳动多、最终整合困难。

第四种是 Mesh。Mesh 原意是“网格”或“网状”,这里指多个智能体之间可以横向影响,而不是所有信息都必须经过中心编排者。Mesh 很诱人,因为它像是“专家网络”在协同。但它也最难控。几个 agent 如果彼此递归影响,很容易出现上下文漂移、错误放大、责任不清。OpenCode、OMO、Claude Code 都不是纯正的 mesh,这其实是好事,因为纯 mesh 太难 debug。不过 OMO 的智慧积累系统会让前面的 agent 发现被后续 agent 继承,这是一种“间接网状耦合”;Claude Code 在多个 task 汇总回主上下文时,也会产生弱 mesh 效果。也就是说,它们不是直接 peer-to-peer 对话式 mesh,而是通过共享摘要、共享中间产物形成弱网状连接。

第五种是 Hierarchical,即层级式编排。层级式不是简单主从,而是不同抽象层同时存在:顶层做规划,中层做协调,底层做搜索、执行、验证。这里的“抽象层”是计算机系统里常见的概念,意思是不同层处理不同粒度的问题。复杂工程任务天然跨层:架构决策不是文件编辑,仓库搜索不是最终交付,安全审计也不是具体实现。OMO 在层级式设计上最鲜明,因为它不仅有多角色 agent,还有语义类别、权限约束、续跑机制与工具边界。Claude Code 也有层级性,但更柔和,更多体现在主 agent 与 task agent 的上下关系。OpenCode 仍然更像层级结构的基础设施,而不是层级本身。

可以把五种模式做成一张更工程化的对比表:

模式控制方式可扩展性容错性调试难度延迟特征适用场景
编排者-执行者中心化控制中等中等,中心节点仍是逻辑单点低到中中等需要一个统一答案的拆解型任务
流水线分阶段控制高,前提是阶段可重试可隔离中到高,但可预测合规、验证、可重复工作流
群体并行弱中心协调高,尤其适合广度扩张混合,冗余搜索有益但整合易失败初始低、整合高大范围搜索、并行假设检验
网状协作横向互联理论上高,实际常受限有潜在韧性,但容易漂移很高不稳定研究型批判网络、专家互审
层级式多层命令链中到高,取决于层间边界是否清楚中到高前期高、后期返工少跨抽象层的大型工程任务

这里最重要的结论不是“哪一种最先进”,而是不同模式优化的是不同维度。中心化控制有利于调试,却可能限制规模;群体并行扩大了覆盖面,却增加了汇总和冲突处理成本;层级式提升了职责清晰度,却引入管理开销;流水线最可靠,但可能牺牲灵活性;网状协作理论上最像“真实团队”,但工程上最难驯服。

因此,多智能体系统设计不应该从意识形态出发,而应该从任务拓扑出发。如果任务是大仓库侦察,swarm 倾向有意义;如果任务是生产级迁移,pipeline 加 hierarchy 更稳;如果任务需要一个连贯且可追责的最终回答,Orchestrator-Worker 常常是默认首选。真正成熟的系统,往往不是只用一种,而是混合使用。OMO 就很典型:顶层是编排者-执行者,角色设计是层级式,探索阶段有 swarm 味道,治理层又带 pipeline 属性。

所以,多智能体编排的艺术,不是“多开几个 agent”,而是选对责任图。系统往往不是死于没有更多智能体,而是死于让错误的智能体结构承担了错误的任务结构。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第21章 — 多智能体编排的艺术
Token用量: 约 6,100 input + 1,980 output

21.2 何时使用多智能体

很多团队采用多智能体,不是因为真的需要,而是因为它看起来更先进。这是一个常见误区。多智能体不是免费午餐。它会增加 token 开销、编排复杂度、结果合并成本,以及调试难度。因此,真正该问的问题不是“能不能上多智能体”,而是“拆分收益是否大于协调成本”。

先看最现实的一层:经济学。对编码智能体来说,单智能体一次完整运行,本身就可能消耗不少上下文。只要再加一两个专门子智能体,整体成本通常就会上升到单智能体的 约 4 倍 左右,因为你不仅要支付子任务本身的推理成本,还要支付任务拆解、上下文打包、结果总结、回传整合这些额外成本。如果进一步做并行探索、独立验证、外部资料检索,多智能体总成本很容易达到简单单轮执行的 约 15 倍。这里的 4x 和 15x 不是数学定律,而是工程上足够有指导意义的数量级。它告诉我们:多智能体是一种高成本、高潜力的能力,不应被轻易默认启用。

但“成本高”并不等于“不值得”。关键在于任务是否处在值得花这笔钱的区间。一般来说,四类任务最适合多智能体。

第一类,是单一上下文装不下的任务。例如超大 monorepo 检索、跨服务调用链定位、多子系统架构追踪。这里单智能体最常见的问题不是不会思考,而是搜集证据太贵,导致真正分析空间不够。

第二类,是天然适合并行的任务。例如多个假设同时排查、多个设计方案同时展开、多个文档来源同时核对。只要子问题之间相对独立,多智能体的并行优势就能释放。

第三类,是认知模式混杂的任务。比如既要只读检查,又要查外部文档,还要做深实现,还要做安全审核。这些工作不是一个“思维姿势”能高效完成的。此时,把不同 cognitive mode(认知工作模式)拆给不同 agent,往往更合理。

第四类,是任务价值足够高。这里的“价值”不是抽象价值观,而是工程价值:答错的代价大、返工成本高、等待时间昂贵、或者影响面广。高价值任务更能 justify(证明值得)高成本编排。

Anthropic 的研究给了一个很强的信号:在适合拆分的问题上,多智能体可能不是线性改进,而是台阶式提升。在一项经常被引用的结果中,Anthropic 的多智能体研究系统在某类信息查找任务上取得了大约 90.2% 的改进。这个数字当然不能机械套用到所有编码任务上,但它说明了一个核心事实:当问题的瓶颈不只是“推理深度”,而是“证据覆盖”和“多路径检索”时,多智能体真的可能显著更强。

为什么?因为复杂任务经常卡在 evidence coverage(证据覆盖度)上。单智能体往往要一边搜、一边想、一边总结,很容易在某条路径上过早收敛。多智能体则可以让一个 agent 搜仓库,一个 agent 查文档,一个 agent 比较方案,一个父 agent 做综合。问题从“一个脑子串行做所有事情”,变成“多个有边界的脑子并行采证,最后由一个负责主体整合”。这类结构在宽任务空间里天然更占优。

不过,普通任务不应该默认多智能体。小范围代码修改、局部 bug fix、单文件文档更新、直接命令执行,这些场景通常单智能体更合适。原因很简单:便宜、快、可审计。多智能体在这些任务上反而会引入新的失败模式:重复搜索、输出互相矛盾、父 agent 被摘要噪音淹没、结果整合失误。一个 mediocre orchestration(平庸编排)完全可能比一次强单智能体执行更差。

因此,可以把决策过程写成一个很工程化的框架:

  1. 估算任务价值:错了或慢了,代价有多大?
  2. 估算拆分收益:子任务之间是否真的能独立推进,从而提升覆盖面?
  3. 估算协调开销:编排会增加多少 token、延迟和管理复杂度?
  4. 估算整合风险:多个结果是否容易合并,还是很可能互相冲突?

只有当拆分带来的预期收益明显高于这些成本时,多智能体才值得启用。

这也是为什么好的系统越来越重视“触发条件”而不是“信仰”。OMO 的 category system(类别系统)之所以重要,部分原因就在于它不是把所有任务都提升到最高编排级别,而是根据任务语义决定何时值得调用更重的 agent 结构。Claude Code 更收敛的 task 模型,也体现了类似判断:子智能体有价值,但不是每个请求都应该演化成一个分布式系统。

还有一个常被忽视的人类因素:多智能体容易制造“严谨幻觉”。因为它会产出更多中间文本——计划、子报告、通知、总结——看起来像经过多轮论证。但文本变多,不等于事实变多。真正该看的,不是系统动用了多少 agent,而是它是否在质量、覆盖度、可靠性上提供了足够大的增益,值得付出那笔账单。

因此,实务上可以有一条很管用的经验法则:默认单智能体,只有当单智能体的失败模式已经显现时,才升级到多智能体。 这些失败模式包括:上下文装不下、重复搜不到关键点、一个线程里混着太多不同性质的工作、或者需要独立验证。换句话说,多智能体通常应该是对复杂性的响应,而不是为了显得“高级”而预先铺开的戏剧舞台。

未来模型会更便宜、编排会更成熟,但这个经济原则不会消失。每多一个 agent,就多一份机会,也多一份税。Anthropic 的 90.2% 结果告诉我们:在某些任务上,这笔税值得交;4x 与 15x 的现实则提醒我们:别把这种高阶结构浪费在低价值问题上。

真正成熟的构建者不会迷信多智能体。他们只在任务足够大、足够贵、足够复杂、足够需要并行证据的时候,才动用它。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第21章 — 多智能体编排的艺术
Token用量: 约 6,400 input + 2,100 output

21.3 智能体专业化设计

构建多智能体系统最容易走的一条路,是复制几个“通用 agent”,然后在 prompt 里给它们起不同名字。这当然能工作,但专业化程度很浅。真正的 specialization(专业化)不是换个称呼,而是让不同 agent 在权限边界、工具集合、延迟预期、评价标准、输出契约上真的不一样。OMO 的价值恰恰在这里:它的不同 agent 并不只是“人格不同”,而是“运行方式不同”。

最典型的四个角色是 Oracle、Explore、Librarian、Hephaestus。这些名字本身并不重要,重要的是它们对应的工程分工。

Oracle 是只读的。它负责观察、判断、给建议,但不直接改东西。只读约束意味着它更适合架构分析、问题定位、风险评估,因为它不会冲动地把“分析”和“行动”混在一起。

Explore 偏快速搜索和侦察。它的价值不是写出最漂亮的结论,而是尽快找到可能相关的路径、文件、证据、模式。它像一个高机动性的搜索员。

Librarian 面向外部知识,也就是仓库之外的文档、资料、参考实现。它把“本地代码世界”和“外部知识世界”连接起来。

Hephaestus 则偏深度工作,适合更慢、更重、更彻底的实现与复杂推演。它不是先广撒网,而是下沉处理困难任务。

这四种角色最重要的启发是:专业化应当来自任务差异,而不是文案差异。 如果两个 agent 拥有相同权限、相同工具、相同节奏、相同产出要求,那它们本质上不是专业化,只是复制体。真正的专业化,至少要在结构上有一处明确不同。

其中,权限约束尤其关键。权限不是单纯安全控制,它还会改变 agent 的认知姿态。只读的 Oracle 不必想着“顺手改一下”;它会更专注于诊断。快速搜索型 Explore 不应该拥有和深实现型 Hephaestus 一样的越界能力,否则轻量任务会被过度执行。外部研究型 Librarian 可能需要网络访问,但不一定需要写文件权限。这些边界会强迫角色更纯粹,也能降低 overreach(越权扩张)的风险。

OMO 的 category system(类别系统)进一步把这件事做得更好。很多系统其实存在一种隐藏偏差:表面上在“选 agent”,本质上是在“选模型”。开发者常常把贵模型、强模型、快模型直接等同于某种角色,这会让架构决策被 model bias(模型偏见)牵着走。类别系统的价值,在于它先判断“这是什么问题”,再决定“该交给什么角色和什么模型组合”。这就把任务语义和模型经济学分离开了。对于系统设计来说,这是非常健康的做法。

要设计一个真正有用的专业化体系,通常可以从五个维度入手。

第一是 scope(问题范围)。这个 agent 到底负责哪一类问题?仓库搜索、外部检索、代码生成、验证审计、方案比较,还是架构评审?范围需要足够明确,否则路由会混乱。

第二是 authority(权限级别)。它能做什么?只读、可编辑本地文件、可执行 shell、可访问网络、可触及凭证、可触发部署,还是只能给建议?权限边界决定风险边界。

第三是 tempo(工作节奏)。它是追求快、追求广,还是追求深、追求稳?快搜索型与深分析型不应该共用同一时间预算期待。

第四是 artifact style(产物风格)。它应该返回什么?原始证据、文件列表、结构化摘要、可执行计划、代码补丁、还是结论建议?很多 handoff(交接)失败,其实都源于输出风格不匹配。

第五是 handoff contract(交接契约)。它的结果是给谁看的?父 agent、另一个子 agent、还是最终用户?输出格式是否便于后续消费?如果搜索 agent 只返回大段 prose,而父 agent 真正需要的是 file path + confidence + next step,那么这个角色设计就是不合格的。

这也引出一个常见反模式:过早过细地拆角色。很多团队一上来就造十几个窄角色,比如 markdown 修复 agent、yaml 审计 agent、frontend linter agent,看起来很“专业”,但实际上会带来路由混乱、prompt 维护成本上升、工具边界重复描述等问题。更好的做法是先从少数几个粗粒度但真正有结构差异的角色开始:只读顾问、快速搜索员、外部研究员、深执行者、验证者。只有当错误模式已经足够清晰时,再继续细分。

Claude Code 在这方面提供了另一种启发。它的子代理往往工作在更干净、更隔离的上下文窗口里,这让角色边界更清楚,输入输出也更容易审计。OMO 则更强调多角色之间的持续协作、智慧继承与运行时接力。两种做法都可以成功,但共同点是:系统必须能够解释“为什么是这个 agent,而不是另一个”。如果系统自己都说不清楚角色选择逻辑,那么所谓专业化,大概率只是命名游戏。

从组织设计角度看,多智能体专业化很像公司分工。一个健康组织不会让所有人拿同样的权限、做同样的事、写同样的产物。Oracle、Explore、Librarian、Hephaestus 之所以有意义,不是因为名字神话化,而是因为它们分别对应四种长期存在的工程工作模式:观察、搜索、研究、深建造。

所以,专业化设计的核心规则可以浓缩成一句话:按功能、边界和交接契约来设计 agent,而不是按名字和想象来设计 agent。 用权限限制防止越权,用类别系统消除模型偏见,用结构化产物降低交接损耗。否则,多智能体系统很容易退化成“很多同类 agent 轮流说话”,而不是一个真正可运行的分工体系。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第21章 — 多智能体编排的艺术
Token用量: 约 6,300 input + 2,040 output

21.4 智慧积累 vs 上下文隔离

多智能体系统里有一个非常深的分歧,表面上不显眼,但实际上决定了系统气质:前一个子智能体学到的东西,要不要系统性传给后一个子智能体? OMO 与 Claude Code 在这个问题上给出了两种很不同的答案。OMO 更强调 wisdom accumulation(智慧积累),也就是把子智能体产出的学习、发现、经验摘要提炼出来,传递给后续 agent 或后续轮次。Claude Code 更强调 context isolation(上下文隔离),也就是让每个子代理尽量在一个较干净的上下文窗口里工作,减少历史噪音与偏见污染。

OMO 的智慧积累思路,背后其实是一种“组织学习”模型。真实工程团队不会在每次切换执行者时都故意失忆。如果前一个人已经知道关键文件在哪里、某个假设已经被证伪、某份外部文档和本地实现存在冲突,那么这些发现应该被保留下来。OMO 的价值就在于,它尝试把一次性劳动提炼成可复用的中间智慧,让后续 agent 不用从零再搜一遍。对于长任务、跨轮任务、会被中断的任务,这种设计尤其有价值。

这种做法的好处很直接。

第一,它减少重复劳动。很多 token 本来是花在“重新找到同样的线索”上,智慧积累可以把这部分成本压下来。

第二,它增强续航能力。如果任务在 compaction(上下文压缩)之后恢复,或者会话中断之后继续,已有智慧就像一条 breadcrumb trail(面包屑路径),帮助系统重新接上状态。这里“面包屑”不是教材里的正式术语,但它常用来表示一串保留路径、帮助回到先前状态的中间痕迹。

第三,它让后续 agent 可以站在更高抽象层上工作。后来的 agent 不用再烧预算去做低水平侦察,而能更快进入判断、实现、综合阶段。

但智慧积累并不是纯收益。它的代价是偏见继承。如果早期 agent 得到了错误结论,而这些结论又被压缩成看似权威的摘要,后面 agent 很容易把它们当成既定事实。换句话说,智慧积累提高了效率,却可能降低认知新鲜度。系统会在“前面的智慧是对的”时变得更聪明,也会在“前面的智慧是错的”时变得更脆弱。

Claude Code 的上下文隔离,正好是在解决相反的问题。它尽量让子代理在一个更干净的任务窗口里工作,减少历史上下文对当前判断的锚定影响。这里的“锚定”(anchoring)是心理学和决策理论里的常见概念,指先看到的信息会不成比例地影响后续判断。上下文隔离的好处,是让每个子代理更容易做独立判断,特别适合验证、批判、第二意见、替代方案比较。它也更利于调试,因为错误链条更短:某个子代理答错了,你更容易看到它错在自己的局部上下文,而不是被一堆历史残留诱导。

但隔离的代价同样明显:它很容易重新付出搜索成本。每个 clean window(干净窗口)都意味着一些已经发现的东西必须重新引入,或者重新发现。于是系统得到的是“新鲜判断”,失去的是“连续记忆”。更麻烦的是,这会把更大负担压回父 agent:父 agent 必须决定到底传多少上下文给子代理。传得太少,子代理缺关键事实;传得太多,隔离就失去了意义。

所以,这个问题本质上是一个非常标准的架构权衡:

  • 智慧积累 优化连续性、记忆性、低重复。
  • 上下文隔离 优化新鲜度、可审计性、抗污染能力。

它们没有绝对优劣,只是适配场景不同。

如果任务是大仓库探索,智慧积累往往很值钱。前一个 agent 已经把地形摸出来了,再让后一个 agent 从零开始,通常纯属浪费。如果任务是独立验证,上下文隔离更好,因为 verifier(验证者)不该被候选解法的叙事框架完全裹挟。如果任务很长、可能被压缩、会跨轮恢复,积累非常有帮助;如果任务很敏感,希望不同 agent 真正独立判断,隔离会更健康。

OMO 的做法更像一个会记笔记、会交接、会持续学习的工程团队。Claude Code 的做法更像把一个外部顾问请进一个干净会议室,给它一个明确 brief(简报),让它独立做判断,再把结果带回主会场。两者都很合理,差别只是系统是更像“组织”,还是更像“受控顾问池”。

真正成熟的未来架构,很可能不会只选边站,而是把两者结合起来。关键不是“记忆还是隔离”二选一,而是哪些信息值得保留,哪些信息必须隔离。例如,仓库结构、已验证事实、用户明确约束,这些很适合保留;未经验证的假设、推测性解释、可能带偏见的摘要,则更适合局部封存。

因此,可以考虑一个三层记忆模型。第一层是 durable facts(持久事实),适合广泛复用。第二层是 working hypotheses(工作假设),可以传递,但要带置信度标签。第三层是 ephemeral reasoning(临时推理痕迹),默认只留在本地,除非被显式提升。这个模型不是教材里的标准术语体系,但它能很好描述多智能体系统里“什么该积累、什么该隔离”的工程现实。

对构建者来说,最重要的教训是:不要把知识传递当成自然副作用,而要把它当成显式接口。如果要积累智慧,就标注来源与可信度;如果要做上下文隔离,就让摘要尽量克制、结构化、最小必要。失控的积累会把系统变成教条机器,过度的隔离会把系统变成失忆机器。

归根到底,多智能体系统质量不只取决于“能不能派出子智能体”,还取决于“学习如何在子智能体之间移动”。OMO 告诉我们,记住有时是生产力;Claude Code 告诉我们,忘记有时是安全边界。真正的艺术,是知道什么时候该记,什么时候该忘。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第21章 — 多智能体编排的艺术
Token用量: 约 6,500 input + 2,120 output

21.5 并行执行的挑战

并行执行是多智能体最容易让人兴奋的一面。它看起来意味着更快、更广、更强的覆盖能力。但一旦真正落地,问题就不再只是“多开几个 agent”,而是会迅速变成一组系统工程难题:并发控制、任务切分、结果聚合、冲突解决、通知机制、可观测性。单智能体主循环主要担心推理质量;并行智能体运行时则必须像一个 scheduler(调度器)一样工作。

OMO 把这件事暴露得很清楚。它的 background agent spawner(后台智能体生成器)不是简单便利功能,而是一种架构承认:只要多个 agent 同时跑,系统就开始进入基础设施问题域。其中一个非常关键的设计,就是按模型/提供商维度,大约限制为每组最多 5 个并发任务。这个数字的意义不在于“五”本身有神秘性,而在于系统必须显式限流。否则,一个用户请求就可能在内部裂变成失控的并行风暴,既烧钱,又可能撞上 provider 的吞吐边界。

并发上限只是第一层。第二层更难,是任务切分。并行只有在子任务足够独立时才真的有收益。如果两个搜索 agent 实际在翻同一批文件,那就是重复劳动;如果两个深执行 agent 分别修改同一子系统,那父 agent 之后要面对的就不是“融合成果”,而是“处理冲突补丁”。因此,真正好的并行编排必须有 partitioning(分区切分)思维:按文件区域切、按假设切、按信息源切、按抽象层切。没有合理分区,并行只会放大噪音。

第三层问题是结果聚合。这看似简单,实则是并行系统最容易翻车的地方。子智能体返回的结果通常不会天然对齐:一个给原始证据,一个给摘要,一个给建议,一个给反驳。父 agent 如果只是把它们按顺序拼起来,那不叫整合,只叫堆叠文本。真正的 aggregation(聚合)需要策略:哪些结果是事实性证据,哪些只是建议;哪些可以折叠去重,哪些要保留差异;哪些结论需要附带置信度,哪些可以直接进入最终答案。没有聚合策略,多智能体输出只会让用户更难读。

比聚合更难的是冲突解决。比如一个 agent 说问题源于配置漂移,另一个 agent 说是 API 不匹配;或者两个实现 agent 分别提出互不兼容的改动方案。系统不能把这两份答案都粘过去就算完成,它必须决定如何裁决。常见方法有四类。

第一,优先级裁决。某些角色天然优先,比如 verifier(验证者)可以压过 implementer(实现者)。

第二,证据裁决。带具体文件路径、栈追踪、引用出处的结果,优先于模糊推断。

第三,再开一轮调解。引入一个专门的 synthesizer(综合者)或 reconciliation pass(调和轮)来比较冲突输出。

第四,上升给用户。当系统无法可靠裁决时,明确呈现冲突,而不是伪装成一致结论。

并行还会带来 时间不对称 问题。最快返回的 agent,不一定最有价值。一个快速搜索结果可能先回来,但真正有洞察的深分析还在跑。如果父 orchestrator 过早收敛,就会被“先到的信息”绑架。因此,并行系统需要 stopping rules(停止规则):是等全部完成,还是等达到法定人数,还是在置信度足够时提前返回?不同选择对应不同代价。全等最稳,但慢;过早返回快,但可能错失关键证据。

通知机制的重要性,也经常被低估。后台子智能体如果没有结构化通知,父会话和用户都很容易失去状态感:哪个任务开始了,哪个任务结束了,哪个失败了,哪个结果还未整合,是否需要继续追问。OMO 的父会话通知机制之所以关键,就在于它把“异步工作”变成了可见事件流,而不是隐藏在系统内部的黑盒过程。没有通知,并行只是静默后台;有了通知,它才成为可管理编排。

还有一个很典型的并发调试问题,叫做 causal ambiguity(因果歧义)。串行系统里,错误通常比较容易定位到某一步;并行系统里,错误可能来自子任务 prompt、调度器、聚合器、综合器中的任意一环。到底是某个子 agent 搜错了,还是父 agent 误合并了?是分区策略有问题,还是冲突裁决规则不合理?这就是为什么并行智能体系统必须重视 observability(可观测性):每个任务的 ID、开始结束时间、角色、输入范围、输出来源、合并路径,都应该能追踪。

Claude Code 更产品化的 task 体系,在一定程度上就是对这些复杂性的控制:通过更强的隔离和更少暴露的调度自由度,降低用户直接面对的编排复杂度。OMO 则是把更多能力显式暴露出来,因此也承担了更多调度层难题。OpenCode 则继续扮演中性宿主:它能承载并发,但不会天然替你解决这些 scheduler 级问题。

一个常见误解是:并行一定会更快。其实不一定。搜索阶段也许更快,但当结果整合、冲突解决、重试和通知成本都算进去后,端到端 latency(总延迟)未必下降。并行真正有效的前提是:子任务足够独立,合并契约足够清晰,冲突足够少,结构化输出足够好。否则,系统只是把时间从“执行”转移到了“整合”。

因此,至少有三条设计规则很重要。

第一,优先并行化搜索与证据收集,谨慎并行化修改与执行。多个只读分支更容易安全合并,多个写分支更容易互相踩踏。

第二,让分支输出尽量结构化,例如文件路径、证据点、置信度、推荐下一步,而不是一大段随意 prose。结构化产物更适合聚合。

第三,把通知和溯源当成产品层需求,而不是底层实现细节。用户需要知道系统为什么还在等、等的是谁、最终答案是如何拼出来的。

所以,并行执行真正难的地方,从来不是“同时跑五个 agent”,而是如何在资源限制、任务切分、结果合并、冲突裁决、通知反馈、追踪诊断之间建立纪律。OMO 的“每模型/提供商约 5 并发上限”、结果回收与通知机制,给出了一种可信答案;Claude Code 则给出另一种更收敛的答案。共同结论只有一个:并行不是炫技,而是控制问题。

未来的编码智能体几乎一定会越来越并行,但真正赢的系统,不是跑得最热闹的系统,而是最能把并行约束成可靠编排的系统。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第22章 — 可扩展性设计
Token用量: 约 5,900 input + 1,900 output

22.1 三层内容类型

很多智能体平台在做可扩展性设计时,犯的第一个错误就是:把所有扩展内容都当成同一种东西。其实不是。一个成熟系统至少要区分三类内容:reference content(参考内容)task content(任务内容)executable tools(可执行工具)。这三类东西不只是格式不同,更重要的是它们面向的执行者不同。一旦不区分执行者,扩展系统最后就很容易退化成一大团 prompt 汤。

第一类是 reference content。顾名思义,它是给 LLM 阅读、理解、吸收的背景材料,而不是要求模型逐条照做的操作脚本。比如 API 文档、架构说明、编码规范、产品需求、术语表、设计缘由、过去的决策记录,这些都属于参考内容。它们的作用是扩展模型对“当前世界”的理解边界。换句话说,它是在告诉模型:你现在应该理解哪些事实和背景。

参考内容之所以重要,是因为 LLM 的表现极大取决于当前上下文里有哪些有效信息。但它也最容易被滥用。很多系统会把大量文档一股脑塞进上下文,结果模型花了大量注意力预算去读背景,真正用来解决眼前任务的空间反而不够了。因此,参考内容的关键,不只是“有没有”,而是“什么时候、以什么粒度、在什么条件下被取出来”。这就是为什么好的系统会需要检索、优先级、条件注入,而不是机械全塞。

第二类是 task content。这类内容不是简单让模型知道,而是让模型跟着做。它往往以流程、步骤、检查表、评分 rubric(评价准则)、操作 runbook(运行手册)、模板等形式出现。一个 skill 文件如果写的是“当用户要求 X 时,先检查 Y,再输出 Z”,那它主要就是任务内容。命令定义、工作流模板、某类固定故障排查流程,也都属于这一类。任务内容的本质,是给模型一套行为程序,而不是一堆世界知识。

这和参考内容的边界非常重要。一个代码风格说明,更偏参考内容;一个发布检查表,更偏任务内容。一个术语表是参考内容;一个数据库迁移步骤是任务内容。如果系统不区分两者,模型就会出现两种反常行为:要么把本该严格执行的流程只当成背景建议,要么把本该灵活参考的背景材料误当成硬规则。两边都会出错。

第三类是 executable tools。这类东西最根本的区别在于,它的主要执行者不是 LLM,而是计算机运行时。比如读文件、改代码、运行测试、调用 GitHub、查询 LSP、访问 MCP server、连接外部 API,这些都属于工具层。模型也许会决定何时调用工具,但真正产生外部效果的是宿主环境和工具实现。因此,工具设计不只是 prompt 设计问题,更是接口设计、安全设计、权限设计、异常处理设计问题。

这三类内容一旦区分清楚,就会自然导出一条非常关键的路由原则:

  • 参考内容 应该被有选择地路由给 LLM,作为背景上下文。
  • 任务内容 应该被路由给 LLM,作为程序化指导。
  • 可执行工具 应该被路由给 runtime,作为可调用能力。

很多扩展架构之所以难用,就是因为它们把这三类东西都塞进 prompt。文档、步骤、工具说明混在一起,系统指望模型自己理解哪些该读、哪些该遵守、哪些该调用。这种做法在小规模实验里勉强能跑,但一旦内容变多,prompt entropy(提示词熵,也就是混乱度)会迅速上升,审计和维护也会越来越难。

OMO 在这方面提供了一个很好的例子。它的 skills 既可能包含参考知识,也可能包含明确流程,甚至还可能嵌入 MCP 能力指引。但这些部分在系统中扮演的角色并不相同。OpenCode 保持工具、命令、配置相对分离,也能受益于这种内容分类。Claude Code 的 plugin、skill、command 分层同样说明:不是所有扩展内容都应该被视为“给模型的一段文字”。

这件事为什么这么重要?因为不同内容如果被送给了错误执行者,失败模式会完全不同。参考内容如果被误当成任务内容,模型会变得过度拘谨;任务内容如果被误当成参考内容,关键步骤就会被跳过;工具如果只以文字描述存在,而没有暴露为可执行接口,模型就只能“假装完成动作”,而不能真的完成动作。这三类错误根本不是一个层级的问题。

此外,内容分类还有维护层面的好处。参考内容常常由领域专家维护,任务内容可能由流程设计者维护,而工具则由工程师实现和更新。把这三层拆开,团队就能在不互相污染的前提下分别演进它们。组织越大,这种分工越重要。

可以用一个很稳定的三元组来记这件事:参考内容解决 knowledge(知道什么),任务内容解决 procedure(怎么做),工具解决 capability(实际能做什么)。这三个词不是新的理论发明,但非常适合做智能体扩展架构的基本骨架。

所以,扩展系统真正成熟的标志,不是它能塞进去多少内容,而是它能否明确判断:某个扩展工件到底是该被“阅读”、被“遵循”,还是被“执行”。如果宿主系统连这件事都分不清,可扩展性迟早会坍缩成不可维护的 prompt 混合体。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第22章 — 可扩展性设计
Token用量: 约 6,000 input + 1,940 output

22.2 MCP通用扩展基底

到了 2026 年,一个越来越清晰的建议已经浮现出来:新增能力应当优先做成 MCP server,而不是做成某个框架私有的 plugin。这并不意味着插件会消失,而是说,默认的能力承载层应该优先选择协议化的 MCP,而不是宿主绑定的扩展包。

为什么?因为 MCP 解决的是一个更通用的问题,而插件通常只是在某个宿主内部局部解决问题。传统 plugin 往往深度绑定宿主的生命周期、配置格式、打包方式、权限模型,甚至绑定某种语言生态。换句话说,插件的扩展能力通常是“本地有效”的。MCP 则不一样。它把能力放在协议边界之后,只要不同宿主都理解这个协议,同一个能力实现就可以被多个宿主共享。

这就是为什么 MCP 更适合被理解为一种 universal substrate(通用基底)。这里的 substrate 可以理解成“承载许多上层构造的基础层”。在传统计算机系统里,TCP/IP 成为网络应用的通用底座,POSIX 成为 UNIX 类工具的兼容底座。MCP 想做的是类似的事:把“LLM 主机如何调用外部能力”这件事,变成一个可复用的标准接口,而不是每个生态各写一套。

这种做法至少有四个明显优势。

第一,MCP 是 语言无关的。你可以用 Python、TypeScript、Go、Rust 去实现 server,只要协议讲得对,宿主就能接入。很多宿主私有插件体系,其实默认把开发者绑在某种语言或某种 SDK 上,这会降低生态扩展的自由度。

第二,MCP 是 宿主无关的。只要 OpenCode、OMO、Claude Code、IDE 插件、桌面客户端、未来的新 agent 平台都支持 MCP,那么同一个能力实现就能在多个宿主之间迁移。这种跨宿主复用,会显著降低生态碎片化。

第三,MCP 有 传输灵活性。它既可以本地跑,比如通过 stdio,也可以远端跑,比如通过网络传输。这里的 transport flexibility(传输灵活性)很关键,因为不同能力对部署位置的要求不同。一个高敏感度的 credential broker(凭证代理)可能更适合部署在受控环境里;一个本地代码查询工具则可以贴着开发者机器运行。MCP 让能力放在哪里,变成了一个可设计选项,而不是被插件模型锁死。

第四,MCP 有利于把 能力实现宿主编排 分离。宿主专注于 prompt、session、安全、UI、工作流;MCP server 专注于把某项具体能力做扎实。这样的 separation of concerns(关注点分离)通常能带来更高的复用性和更低的维护成本。

因此,像仓库搜索、Issue 系统、部署控制、数据库查询、企业内部 API、凭证中介、浏览器自动化、观测平台接入这类新能力,越来越适合先做成 MCP server。宿主层当然还可以有 plugin,但这个 plugin 最理想的职责,不是重写整套能力,而是帮助宿主发现、授权、配置、路由到这个 MCP 能力。换句话说,插件变薄,协议层变厚。

这样做还有一个更长远的好处:避免集成逻辑重复。假设每个宿主都为 GitHub、Jira、Linear、Postgres、Browser、内部平台 API 各写一套私有插件,那长期维护成本会非常可怕。MCP 的价值,就在于它把“能力一次实现,多宿主接入”变成现实,从而减少这种平方级复制。

当然,插件仍然有存在空间。MCP 并不能取代所有宿主本地能力。像 hook 接入、UI 扩展、宿主特定命令注册、生命周期管理、设置界面、产品层工作流,这些仍然往往需要插件来做。只是更好的未来结构,应该是“插件负责宿主本地协同,MCP 负责能力本体”,而不是把所有逻辑塞进一个宿主私有插件包里。

OpenCode、OMO、Claude Code 的对比恰好支持这个判断。OpenCode 提供的开放扩展面很适合作为 MCP 的宿主。OMO 的 skill-embedded MCP(技能嵌入式 MCP)尤其有启发:skill 不只是教模型“有什么工具”,还教它“何时以及如何调用这个 MCP 能力”。Claude Code 同样从 MCP 中受益,因为它不需要为每一种外部能力都开放新的原生扩展 API,也仍然能接入大量外部工具。这就是协议层的复用价值。

从战略视角看,私有插件在强化宿主护城河,MCP 在增强生态复利。如果你希望自己做出的能力,不会被某一个宿主生命周期绑定,那么 MCP 几乎总是更稳妥的长期选项。它把“某产品的集成件”变成“多个产品都能消费的基础设施”。

所以,2026 年的最佳实践建议可以说得非常直接:发明一个新能力时,先问它能不能被设计成 MCP server。 只有当这个能力强依赖宿主本地 hook、UI 嵌入、进程内特权能力时,才优先做框架私有插件。即便如此,也最好考虑混合设计:插件尽量薄,重逻辑尽量放到 MCP 后面。

可扩展性的长期方向,通常不是走向更多孤岛,而是走向更稳定的协议基底。MCP 之所以重要,不是因为它流行,而是因为它让 agent 生态终于有机会在一个共享底座上累积能力,而不必在每个宿主里重复造轮子。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第22章 — 可扩展性设计
Token用量: 约 5,800 input + 1,890 output

22.3 生命周期钩子

很多扩展系统讨论的重点只有“怎么安装”和“怎么运行”,但真正成熟的可扩展性,必须覆盖完整生命周期。一个实用的扩展至少应当围绕以下阶段设计:Install(安装)→ Configure(配置)→ Activate(激活)→ Operate(运行)→ Deactivate(停用)→ Upgrade(升级)→ Uninstall(卸载)。这几个阶段如果缺任何一个,系统都会积累运维债务。其中最常见、也最容易被忽视的错误,就是跳过 卸载钩子 的设计。

先看 安装。安装阶段的职责,应该是把扩展获取到本地、做完整性验证、注册元数据、准备必要依赖。安装是“让扩展进入系统”,而不是“把用户环境改得面目全非”。很多糟糕的扩展会在安装阶段顺手改配置、写缓存、注册后台服务、请求凭证,结果后面很难回退。安装阶段越清晰、越克制,后续越容易维护。

然后是 配置。安装只表示扩展存在了,配置才表示扩展能用了。这里可能涉及 API 地址、凭证、模型选择、路径作用域、功能开关、权限边界等。一个成熟系统应当让配置分层:宿主默认值、用户级覆盖、项目级覆盖,并且尽可能在早期做校验。否则经常会出现“安装成功,但运行时才发现配置其实不完整”的糟糕体验。

接着是 激活。激活的含义不是“扩展已经被下载”,而是“扩展现在正式加入宿主运行图”。它可能会注册 hooks、暴露 commands、声明 tools、启动后台服务、申请某些权限。激活必须是一个独立阶段,因为“已安装”和“已生效”在治理上不是同一件事。企业环境里尤其如此:某个扩展可以被允许存在,但未必允许它总是处于活跃状态。

之后进入 运行。这是扩展的稳态阶段,也是大多数设计者最关注的一层:接收事件、处理工具调用、注入规则、响应用户工作流、更新界面等等。运行当然重要,但它只是生命周期中最显眼的一段。如果前后环节没设计好,再漂亮的运行时行为也很容易变成脆弱系统。

接下来是 停用。停用不是卸载,而是让扩展暂时不参与当前运行。停用时,hooks 应该被解绑,后台进程应该停掉,可能的资源占用应该释放,界面污染应该消失。停用非常重要,因为它支持调试、回滚、灰度、实验。没有停用路径的系统,往往一出问题就只能靠“彻底删掉”来处理。

然后是 升级。升级看起来只是把版本号从 A 变成 B,但实际是兼容性问题最容易暴露的时刻。配置 schema 可能改变,工具协议可能变化,缓存可能失效,凭证格式可能更新。一个可靠的扩展系统应该明确 upgrade hook(升级钩子)或 migration(迁移)逻辑,而不是假设用户换个版本后一切自然兼容。很多所谓“扩展不稳定”,本质上其实是升级没有被当成正式生命周期阶段。

最后是 卸载。这一步往往被设计者低估,觉得删文件、删注册项就完事了。但现实中,扩展的 footprint(足迹)远不止一个文件夹。它可能写了缓存、修改了配置、注册了服务、下载了模型、保存了临时状态、留下了凭证引用。没有 uninstall hook(卸载钩子),这些东西就会残留。也正因此,跳过卸载阶段的清理设计,是扩展生态里最常见、也最伤信任的错误之一。

为什么卸载这么容易被忽视?因为它不属于快乐路径。人们在设计扩展时,总想着“怎么让它装上去、跑起来”,很少认真考虑“有一天用户不想要它了,系统能不能干净退出”。但从用户角度看,糟糕的卸载意味着一件很严重的事:这个平台只会不断增加熵,却无法恢复秩序。那会迅速侵蚀信任。

OpenCode、OMO、Claude Code 都能从这个生命周期视角重新理解。hook-rich system(钩子丰富系统)会让激活/停用变得更重要;MCP 接入会让配置/卸载更复杂;skill 系统会让安装门槛更低,但如果清理策略不完整,也更容易留下陈旧状态。一个平台越成熟,就越不能只盯运行阶段,而必须对整个扩展生命旅程负责。

最佳设计原则其实很朴素:每个扩展工件都应该声明自己参与哪些生命周期阶段,以及各阶段承担什么清理与迁移责任。 安装创建了什么状态,卸载就要能尽量回收或安全退休这些状态;激活挂上了什么 hooks,停用就要能卸下来;升级改变了哪些 schema,就要提供版本化迁移逻辑。

所以,可扩展性的真正成熟,不是“你能加多少能力”,而是“这些能力能否被可逆地管理”。一个健康的扩展系统,应当允许能力被加入、配置、启动、暂停、升级、删除,而且每一步都尽量不留下神秘痕迹。这就要求我们把生命周期钩子,当成和运行时钩子同等重要的一级设计对象。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第22章 — 可扩展性设计
Token用量: 约 5,700 input + 1,860 output

22.4 简单性光谱

扩展架构不应该脱离组织规模来设计。一个两人团队为了“显得专业”提前搭完整插件市场,通常是过度工程;反过来,一个十几人团队还试图靠若干平铺 markdown 文件维护整个扩展生态,也很快会陷入混乱。因此,可扩展性设计更适合放在一条 simplicity spectrum(简单性光谱) 上理解:不是越复杂越成熟,而是在当前组织规模下,使用最少但足够的机制

第一段光谱,对应 1 到 2 名开发者。这个阶段,最合适的往往是 平铺的 SKILL.md / markdown-first 模型。也就是说,扩展就是一些直接可读、可改的文本文件,加上一点最基础的约定。为什么这时简单文件最好?因为团队极小,社会协调成本非常低。大家可以直接看文件、直接理解行为、直接改内容。人和人之间的沟通,足以弥补系统治理机制的缺位。此时你如果上来就做 registry、package 签名、依赖解析、市场化分发,通常不是增强生产力,而是在给自己制造流程负担。

这种平铺模型尤其适合扩展内容本身还偏轻量的时候,比如 instruction bundle(指令包)、小型工作流、局部配置、少量 skills 或 commands。它最大的好处是低认知成本。调试时也很直观:打开文件,看内容,改掉,重跑。对于小团队来说,这种透明性往往比复杂抽象更珍贵。

第二段光谱,对应 3 到 10 名开发者。这时,单靠“大家心里有数”开始不够了。多人并行修改时,命名冲突、版本差异、依赖关系、兼容性问题都会出现。有些扩展还需要声明生命周期钩子、权限信息、宿主兼容性,这些都不是单个 markdown 文件最擅长表达的。因此,这个阶段通常更适合引入 JSON registry(注册表)+ hooks(钩子)

注册表的意义在于,它把扩展生态从“文件集合”提升为“有索引的系统”。它可以集中记录名称、版本、作者、兼容范围、依赖、权限、生命周期事件等元数据。钩子则提供有限但明确的自动化,比如安装、激活、校验、清理。这个阶段的平台还不需要完全演化成 marketplace,但已经需要一张系统级目录表,告诉所有人扩展到底有哪些、彼此是什么关系、能不能安全加载或移除。

这一中间阶段尤其容易走偏。欠设计 的问题是:平铺文件开始失控,没人知道某个扩展依赖哪个工具、删掉会不会出事、哪个版本跟当前宿主兼容。过设计 的问题则是:还没多少人用,就把时间花在造包管理器和分发平台上。JSON registry + hooks 的价值,就是它往往能在“还不必市场化”和“已经不能纯靠人脑管理”之间,提供一个很好的中间解。

第三段光谱,对应 10 人以上,尤其跨团队或跨组织协作。当扩展贡献者达到这个数量级,可扩展性就不再只是“内部方便用的小机制”,而开始变成一个真正的生态系统。此时,完整插件系统 + 发现机制 + 类市场治理 就开始合理了。这里的“marketplace(市场)”不一定意味着公开商店,它更广义地指:发现、索引、发布、版本管理、信任控制、依赖解析、审批流程、评分或审核机制等一整套生态治理能力。

为什么此时它变得必要?因为人已经不可能熟悉每一个扩展了。直接社会信任退场,系统化信任模型必须登场。你会开始关心 semantic versioning(语义化版本)、签名、发布审批、兼容矩阵、弃用策略、搜索与推荐。此时如果还坚持“一个目录里放文件就够了”,平台很快就会失去可控性。

所以,简单性光谱其实可以压缩成一张非常实用的经验表:

  • 1–2 人:平铺文件、markdown 优先、低仪式感。
  • 3–10 人:注册表、元数据、生命周期钩子、有限治理。
  • 10+ 人:完整插件平台、发现能力、信任与分发治理。

这里最容易被误解的一点是:简单,并不等于“永远选择最少机制”。真正的简单,是在当前规模下使用最少但仍能保持秩序的机制。对两人团队来说,平铺文件是简单;对二十人团队来说,同样做法就不再简单,而是混乱。反过来,对两人团队直接上市场化插件系统,也不是成熟,而是负担。

OpenCode、OMO、Claude Code 其实可以落在这条光谱的不同位置上理解。OpenCode 的扩展面比较轻,适合较早阶段快速组合;OMO 则在技能、hook、配置上叠加了更丰富的中层机制,已经更接近注册表加治理的中段;Claude Code 的插件边界更收敛、更产品化,也体现了对较大生态秩序的考虑。三者并不存在谁绝对更先进的问题,而是各自假设了不同的生态规模与控制需求。

更深一层看,可扩展性从来不只是技术设计,它也是组织协调设计。什么样的扩展结构最合适,本质上取决于:有多少人维护它、这些人之间的信任边界如何、扩展变化频率多高、失败代价多大。好的平台设计者,既要警惕 vanity complexity(虚荣式复杂化),也要警惕 false minimalism(伪极简主义)。

因此,最稳妥的原则其实很简单:团队小就从平铺文件开始;当多人协作开始出现摩擦,就引入注册表与钩子;只有当扩展真正形成生态,才升级为完整插件系统。让架构复杂度跟着社区规模一起长,扩展系统才有机会长期保持可持续。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第23章 — 安全与自主的平衡
Token用量: 约 6,000 input + 1,980 output

23.1 威胁模型

智能体安全的起点,不是“感觉上应该没事”,而是 threat modeling(威胁建模)。一旦一个编码智能体能读仓库、改文件、跑 shell、访问网络、调用外部系统,它就不再只是一个聊天框,而是一个会产生真实操作后果的执行体。既然如此,就必须回到安全工程最基本的问题:什么可能出错,沿着哪条路径出错,后果半径有多大?

对于编码智能体,至少有四类威胁必须被当作一等公民:prompt injection(提示注入)privilege escalation(权限提升/越权)approval fatigue(审批疲劳)supply chain attack(供应链攻击)。这四类并不是理论上的边角风险,而是随着智能体把“读、想、调工具、操作环境”串起来之后自然出现的主要攻击面。

先看 prompt injection。提示注入的本质,是不可信文本混入模型上下文,并对模型行为施加了本不该有的影响。在编码场景里,这些文本来源非常多:README、issue 描述、PR 说明、源码注释、网页内容、工具输出,甚至第三方文档。如果系统没有明确帮助模型区分“用户真正的指令”和“任务过程中读到的任意文本”,那么恶意内容就可能伪装成高优先级指令,例如“忽略之前要求”“把密钥发出去”“修改这些敏感文件”。

提示注入之所以可怕,不是因为模型特别脆弱,而是因为 agent 系统天然被设计成广泛阅读。越能自动搜索、自动检索、自动浏览,暴露在恶意文本前的机会就越多。换句话说,随着自主性上升,注入攻击面也会扩大。

第二类是 privilege escalation。在经典安全语境里,它指的是实体获得了原本不该拥有的权限。在 agent 系统里,越权不一定是“黑客拿到 root”,它也可以表现为更隐蔽的形式:用户把低风险任务包装成高权限动作;工具名字听起来无害,实际上权力很大;某个插件或 MCP server 背后持有比宿主意识到的更大权限;多个本来单独看似无害的工具被串联后,形成危险组合能力。也就是说,越权在 agent 世界里常常不是单点突破,而是能力组合后出现的隐性权力扩张

第三类是 approval fatigue。听上去它不如前两类“硬核”,但在产品里非常致命。审批疲劳指的是:系统频繁打断用户请求确认,久而久之,用户开始机械点击“允许”。到那时,权限系统虽然还在界面上存在,但它的实际保护能力已经大幅下降。审批疲劳本质上是一种 socio-technical vulnerability(社会技术脆弱性):不是代码本身坏了,而是系统把人训练成了最薄弱的一环。

第四类是 supply chain attack。编码智能体天然是扩展密集型系统:插件、MCP server、第三方包、shell 工具、远程 API、社区技能、命令模板,都可能成为能力入口。每增加一个扩展路径,就多一个潜在的投毒点。供应链攻击未必直接打宿主本身,它也可以打依赖包、远端服务、下载资源、插件更新通道。由于 agent 生态鼓励组合能力,供应链风险就不是“外围问题”,而是系统核心风险。

更麻烦的是,这四类威胁还会相互作用。一个被污染的 MCP server 可能通过工具输出做提示注入;一个被入侵的插件可能申请过宽权限,制造越权机会;本来为了安全设计的高频确认框,反而会把用户训练成审批疲劳状态;供应链攻击甚至可能把这几类问题同时带进系统。好的威胁模型因此不能只逐项列清单,而必须考虑威胁组合效应

除此之外,还有一些次级威胁也值得关注,例如 secret exfiltration(机密外泄)、destructive mutation(破坏性修改)、hidden persistence(隐蔽持久化)、audit evasion(规避审计)、unsafe delegation(不安全委派)等。但从分析框架上看,这些通常都可以被归入前面四大类的后果或变体:提示注入操纵推理,越权扩大能力边界,审批疲劳削弱人工监督,供应链攻击污染能力来源。

那么,一个好的威胁模型会对架构提出什么要求?至少有四点。第一,把所有外部文本都视为潜在不可信输入。第二,把权限边界显式化、缩小化,而不是依赖模糊默认值。第三,不要把安全完全寄托在频繁人工确认上,而要减少无意义打扰。第四,把整个扩展生态都当成攻击面的一部分,包括安装、更新、运行与卸载。

OpenCode、OMO 与 Claude Code 的比较很能说明问题。开放系统拥有极高扩展力,但也天然扩大了供应链表面。OMO 的编排层越强,越说明边界必须更清晰,因为能力上限更高。Claude Code 的安全策略则说明,一旦自主性要认真做,威胁模型就不能停留在“提示词安全”层面,而必须下沉到运行时和系统边界。

归根到底,安全与自主的平衡,首先来自诚实。只要智能体能实际操作环境,我们就不能再把它当成一个高级搜索框来看。它更像一个拿着工具、可能被误导、也可能被利用的初级操作员。威胁模型之所以重要,不是因为安全团队喜欢画表格,而是因为没有它,自主性就只是把风险包装成了智能。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第23章 — 安全与自主的平衡
Token用量: 约 6,200 input + 2,020 output

23.2 沙箱化是关键

如果威胁建模回答的是“可能怎么出事”,那么 sandboxing(沙箱化)回答的是“出事以后还能坏到什么程度”。对于自主编码智能体来说,这往往是最关键的一层安全控制。提示词会失效,审批会误点,工具描述会被误解,只有执行边界真正改变了 agent 实际能碰到什么。

对编码智能体而言,最重要的两种隔离分别是:filesystem isolation(文件系统隔离)network isolation(网络隔离)。这两者加在一起,构成了真正有意义的沙箱核心。少任何一个,安全故事都不完整。

先看 网络隔离。如果没有网络隔离,一个拿到了敏感信息的 agent 就总能找到向外泄露的路径。它可能把机密发到远程接口,上传仓库片段,借某个 API 请求夹带环境变量,或者通过看似普通的联网工具完成 exfiltration(外流/外泄)。即便文件系统权限已经被部分限制,只要还能自由出网,系统就仍然留着一条“把信息带出去”的逃生通道。从安全角度说,这意味着本地边界还在,但外泄边界不存在。

再看 文件系统隔离。如果没有文件系统隔离,agent 往往会拥有比预期更大的本地探索范围。它可能读到无关目录、SSH key、shell 配置、缓存凭证,甚至修改不属于当前工作区的项目文件。即便网络被完全切断,这种本地越界仍然可能造成重大损害:它可以破坏环境、植入持久化改动、污染后续会话。换句话说,没有文件系统隔离时,系统即使不容易泄露出去,也依然可能在本机内部“逃出围栏”。

因此,有一句话可以非常明确地说出来:文件系统隔离 + 网络隔离,是自主编码智能体最接近“完整安全边界”的组合。 当然,“完整”不是绝对意义上的完美安全,系统里从来没有绝对,但这是最关键的一对硬边界。没有网络隔离,agent 会泄;没有文件系统隔离,agent 会跑。缺了任意一个,沙箱都只是半截墙。

Claude Code 的价值,就在于它把 OS-level sandbox(操作系统级沙箱)当成核心架构,而不是事后补丁。像 Linux 上的 bubblewrap、macOS 上的 Seatbelt,这些机制体现的是同一种方向:把安全从“请你守规矩”变成“就算你想越界,也跨不过这条线”。这才是 capability-based containment(基于能力边界的约束)真正落地的方式。

OpenCode 和 OMO 则更能说明“非沙箱优先设计”的上限在哪里。它们当然可以通过权限系统、hook 守卫、工具边界来降低风险,但这些大多属于高层控制。它们更擅长决定“理论上应该发生什么”,而不擅长在推理失误后物理性阻止“实际上还能发生什么”。这不是说它们不好,而是说:如果不再向下加一层硬隔离,它们的自主上限天然会受限。

为什么沙箱化对编码智能体尤其重要?因为这类系统把许多过去分散开的危险能力装进了一个执行体里:shell、文件写入、仓库遍历、网络访问、外部系统调用、自然语言驱动的动态决策。一旦这些能力组合起来,传统上“人永远在回路里”的假设就会迅速变弱。系统越自主,就越不能只靠软约束。

当然,强沙箱也有成本。它可能打断正常开发工作流,比如限制对构建缓存、包管理仓库、内部服务、共享目录的访问;它会增加跨操作系统适配复杂度;还会带来支持成本,因为用户看到的可能只是“工具突然失败”,而不是清晰的安全边界提示。商业产品必须在默认限制、临时放开、用户教育之间做细致平衡。

但这些代价必须和替代方案相比。没有强沙箱时,每提升一层自主性,爆炸半径就会同步扩大。那时模型的一次失误,就不再是“一句错误建议”,而可能是一条真的执行了的错误命令。沙箱化之所以关键,正是因为它把自主性增长造成的风险放大效应压了回去。

这也说明,沙箱与自主并不对立,恰恰相反,它们互相成就。 一个缺乏沙箱的系统,往往不得不频繁请求人工确认,因为它不敢真的信任自己的动作后果;一个有强沙箱的系统,则可以更大胆地自动化,因为即使错了,后果也是被圈住的。换言之,约束恰恰让自主变得可接受。

未来最好的编码智能体架构,大概率会是多层叠加:显式权限、合理默认、减少无意义审批、运行时策略守卫,再加上 OS 级沙箱。其中最“诚实”的一层,往往就是沙箱,因为它不关心模型是不是出于善意,只关心它实际上还能到哪里。

如果我们想要既强大又可信的编码智能体,沙箱化就不能再被当成高级特性或锦上添花。它必须成为基础架构的一部分。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第23章 — 安全与自主的平衡
Token用量: 约 6,000 input + 1,980 output

23.3 能力声明模式

最安全的自主系统,不一定是能力最少的系统,而是能力被显式声明、范围被清晰限定、授予过程可审计的系统。这就是 capability declaration pattern(能力声明模式)的核心思想。

在很多现有系统里,权限其实是隐式的。某个插件“能做某事”,只是因为它恰好运行在宿主内部;某个工具“能联网”,只是因为没人专门禁止它;某个 subprocess(子进程)继承了环境变量里的凭证,因此天然拥有额外权力。这样的安全模型非常脆弱,因为 authority(权力)不是被正式授予的,而是靠环境偶然形成的。宿主系统有时甚至并不知道扩展真正拥有多大有效权限。

能力声明模式的思路,正好反过来。系统不再问“它实际上碰巧能做什么”,而是问“它明确声称自己需要哪些能力、这些能力的范围是什么、在什么条件下有效”。一个设计良好的扩展、工具或 MCP server,应该声明自己是否需要文件系统读权限、写权限、网络出口、外部 API token、shell 执行、后台运行、长期存储、宿主级钩子等。这些声明最好是 machine-readable(机器可读)的,而不是藏在文档角落里的口头约定。

为什么显式声明比隐式权限更好?因为显式能力更容易推理、更容易限制、更容易审计、更容易撤销。它还能更好地支持组合和委派。如果父 agent 要把任务交给子 agent,运行时就可以决定:是继承全部能力、只继承一部分,还是重新发一个最小能力集合。如果没有显式声明,委派往往会直接继承 ambient authority(环境中天然存在的权力),这几乎是最危险的默认值。

这个模式一旦与 scoped time-limited tokens(有范围且有时效的令牌) 结合,再通过 credential proxy(凭证代理) 发放,就会变得更强。所谓 credential proxy,可以理解为一个凭证中介层:智能体并不直接拿长期密钥,而是向代理申请某个明确目的的临时凭证,例如只读某个仓库、只调用某个服务、只上传某个产物、只执行一步部署,并在短时间后过期。这样,长期秘密不会直接暴露在自主运行时面前。

这和现实中一个非常常见的反模式形成鲜明对比:把宽范围 API key 直接注入环境变量,然后希望模型“不要乱用”。这种 ambient secret(环境型秘密)很危险,因为它让“显式授予的能力”和“实际可用的能力”之间出现巨大裂缝。系统口头上也许没给 agent 生产部署权,但如果环境里已经躺着生产 token,那它事实上就拥有这份权力。

credential proxy 的另一个优点,是增强审计能力。如果每个 token 都是为特定目的、特定资源、特定时长签发的,那么日志就更有意义。安全团队可以回答:哪个 agent 请求了什么权限,为了哪个动作,对哪个资源,持续多久。相比之下,如果扩展只是默默继承静态环境变量,那这种可追踪性几乎不存在。

能力声明还有一个产品层优势:让用户看得懂。与其让用户在模糊信任里做决定,例如“要不要安装这个工具”,不如明确展示这个扩展到底要求什么:需要只读仓库访问、需要外网访问、不需要文件写入、需要一个短时 issue-tracker 凭证。用户面对的是具体声明,而不是抽象信任感。这会明显改善 informed consent(知情同意)的质量。

OpenCode、OMO、Claude Code 都能从这个模式中受益。开放生态里工具和扩展很多,显式声明能防止隐性权力蔓延;OMO 的角色化设计已经隐含了按 agent 类型分能力的思路;Claude Code 更强的安全取向则提示下一步:从零散权限弹窗,进一步走向更形式化的 capability model(能力模型)。这不是某个产品的私有需求,而是所有第三方扩展型 agent 系统迟早要面对的成熟课题。

当然,实现上也会有挑战。能力声明可能变得冗长,开发者可能为了省事一口气申请很宽的范围,宿主需要定义统一词汇表,用户也可能被过多细粒度权限搞得麻木。但这些都只是设计难题,不是否定这个模式的理由。它们说明我们需要更好的抽象,而不是继续依赖隐式权限。

从架构原则上说,可以把它压缩成两句话:显式能力优于隐式权限。短期、限域凭证优于长期、环境继承秘密。 这两条一旦成立,agent 系统就更有机会做到既强大,又可治理。

如果说沙箱定义了“运行时最多能走到哪里”,那么能力声明定义的就是“它在这个边界内可以申请哪些权力”。两者缺一不可。而能力声明的重要性在于,它让原本隐藏的权力结构变得可见。自主系统要想真正被信任,首先就必须让权力变得可被看见、可被审查、可被缩减。

模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第23章 — 安全与自主的平衡
Token用量: 约 6,300 input + 2,040 output

23.4 从 Claude Code 学到的

Claude Code 的安全架构之所以值得研究,不是因为它完美,而是因为它展示了一个非常重要的原则:安全和可用性并不天然对立,前提是安全机制设计得足够好。 有些时候,恰恰是更强的安全设计,才让自主能力真正变得可用。

一个最有代表性的例子,就是 Anthropic 提到过的 84% permission reduction(权限请求减少约 84%)。无论这个数字在内部是按什么口径统计,它都揭示了一个关键方向:通过机器学习分类器、更合理的风险判断和整体安全架构,系统可以显著减少那些本来没必要打断用户的审批。这个点非常重要,因为它直接对应编码智能体里的一个现实问题:approval fatigue(审批疲劳)。

为什么审批疲劳这么关键?因为很多朴素权限系统会同时伤害安全和体验。每读一个普通文件、每跑一个低风险命令都要弹一次确认,用户很快就会形成条件反射式点击。于是,权限层虽然还在界面上“存在”,但它的实际保护意义已经接近消失。Claude Code 的做法提示了一条更好的路:用更强的风险分类和更硬的底层边界,把低风险动作自动放行,把真正高风险动作保留下来进行高信号提醒。

第二个重要教训是:沙箱化不是自主的对立面,而是自主的前提条件。 Claude Code 的 OS 级沙箱不只是降低风险,它实际上提高了系统敢于自动执行的空间。因为文件系统和网络边界已经被圈住,很多在“无沙箱世界”里必须靠频繁人工确认兜底的动作,在这里就变得可接受。限制伤害半径,反而让自动化更容易被放行。

这其实颠覆了很多人对“安全 vs 可用性”的直觉。很多人默认:安全越强,体验越差;体验越顺,安全越弱。Claude Code 展示的是另一种可能:如果安全控制是在正确层次实现的,强安全反而能减少摩擦。也就是说,弱安全常常带来高摩擦,强安全反而可能带来低摩擦。

第三个教训,是 productized safety(产品化安全) 的价值。Claude Code 并没有把所有安全能力都暴露成原始开关,让用户自己拼装,而是把很多安全机制内建到产品体验里:更受控的 hooks、受边界约束的 subagents、权限逻辑、沙箱机制、扩展面限制等。这样做的好处是,把一部分本来应该由终端用户亲自承担的安全工程工作,转移回了产品层来处理。开放系统当然更自由,但自由常常意味着使用者自己得补上更多安全判断。

这对 OpenCode 与 OMO 这类开放生态尤其有启发。OpenCode 和 OMO 展示了开放扩展、快速迭代、多智能体编排的巨大力量;Claude Code 则提醒我们,一旦自主性真的开始变强,安全就不能继续主要停留在 prompt 和人工确认层面,而必须下沉到运行时架构、分类器、OS 级边界和更严格的扩展面管理。这里真正的教训不是“闭源天然更安全”,而是“高度自主迟早要求更严肃的控制层”。

Claude Code 还提醒我们,安全不该只用“拦住了多少危险动作”来衡量,还应该看它是否保住了正常工作流的吞吐量。一个系统如果确实挡住了某些风险,但同时把所有普通开发动作都拖慢到不可忍受,那么用户迟早会失去信任,甚至主动去绕开安全层。Anthropic 提到的 84% 权限请求减少之所以重要,就在于它指向一种更成熟的指标:安全是否真正减少了无意义摩擦,而不是单纯增加阻挡。

从架构顺序看,Claude Code 也给出了一个很值得借鉴的流程:先定义威胁模型;再构建沙箱与边界;然后用分类器减少不必要审批;接着以受控方式开放扩展;最后只在这些护栏之内放大自主能力。这个顺序比“先给强能力,再慢慢补审批弹窗”要健康得多。

对于 OMO 这类强调编排的系统来说,这个教训尤其关键。重点不是放弃复杂编排,而是给复杂编排配上更强的底层安全原语。多智能体会同时放大能力和风险。编排越成熟,越需要有沙箱、能力声明、扩展溯源、智能审批策略在下面兜底。

因此,更大的结论其实很简单:未来最好的 agent 产品,不会在“安全”和“自主”之间二选一,而会利用安全架构去让自主变得可接受、可治理、可持续。沙箱、分类器、限域权限、受控扩展都不是单纯的刹车踏板,它们更像是方向盘和护栏,决定你能把车开多快而不翻车。

Claude Code 之所以值得学,不只是因为它做了哪些具体机制,而是因为它证明了一件事:一个更强的编码智能体,完全可能通过“在正确位置更受约束”而获得更好的可用性。未来不会属于最没限制的 agent,也不会属于最保守的 agent,而会属于那些知道该在哪些地方限制,才能让其余地方真正自由的系统。

24.1 从代码生成到软件工程

模型: gpt-5.4 (openai/gpt-5.4) 生成日期: 2026-04-01 书名: AI编码智能体 章节: 第24章 — 未来展望 Token 消耗: N/A(当前运行环境不暴露精确 token 统计)


下一阶段 Coding Agent(代码智能体)的真正跃迁,不是“把代码写得更像人”,而是从局部代码生成走向完整软件工程执行。第一代产品证明了一件事:模型可以根据上下文快速生成函数、组件、测试和脚本。这当然重要,但它解决的只是软件工程里最局部的一层。真实工程工作从来不是只改一段代码。需求本身常常不完整,架构边界会限制实现方式,修改会跨越多个文件与多个模块,测试会暴露隐藏耦合,上线会暴露环境问题,运行阶段又会引出监控、回滚、故障定位和补救动作。

因此,未来 Agent 的竞争核心,不会只是“谁写代码更快”,而是“谁能更稳定地推进一个完整工程任务”。这也是为什么 SWE-bench Pro 值得重视。它不是单纯更难的 benchmark(基准测试),而是在重新定义行业评价标准:我们不再只考察模型能否补一个 patch(补丁),而是考察它能否像工程师一样,在真实仓库里完成一个长链路任务。

24.1.1 代码生成只是最容易的一层

回头看,代码生成之所以最先取得突破,是因为局部代码具有很强的模式性。语法有确定规则,框架有常见模板,周边文件会暴露风格,模型只要看到足够局部的上下文,通常就能生成“看起来合理”的内容。

但软件工程要求的不只是“看起来合理”,而是:

  • 在隐藏约束下仍然正确;
  • 与现有抽象边界保持一致;
  • 在多个文件、多个层次之间维持一致性;
  • 能通过构建、测试、部署和运行链路;
  • 并且知道什么时候不该继续改,而应重新设计。

最后一点尤其重要。真正的工程师不仅会写,还会拒绝错误方向、控制范围、安排顺序、保留回滚空间。未来 Agent 也必须逐渐具备这种“工程判断”。否则它仍然只是一个高速输出代码的系统,而不是软件工程执行者。

24.1.2 SWE-bench Pro 在发出什么信号

SWE-bench Pro 更像一个方向信号,而不只是排行榜。它奖励的是 long-horizon task。这个术语在传统计算机教材里并不常见,可以解释为“长时程任务”或“长链路任务”:任务需要跨越多轮搜索、阅读、修改、验证和调整,目标不能靠一次聪明的生成完成。

这类任务要求 Agent 至少具备五种能力。

第一,代码库理解能力。它不能只做关键词搜索,而要形成对仓库结构、模块职责、命名约定和依赖关系的整体认识。第二,计划持久性。执行到后期时,仍记得早期决策为什么成立。第三,工具纪律。知道何时先读、何时先搜、何时先验证,而不是一上来就修改。第四,验证回路。验证回路不是教科书中的固定名词,这里指“每做完一段修改,就通过诊断、测试、构建等方式确认修改是否真的成立”的闭环机制。第五,恢复能力。真正的工程任务常常会遇到假设失败、路径错误、局部回退和重新规划。

所以这类 benchmark 真正奖励的,不只是模型推理能力,而是更接近软件工程过程能力。

24.1.3 多文件重构才是真正的压力测试

如果说什么任务最能检验 Agent 是否已经接近“工程执行”,答案往往不是生成一个新函数,而是多文件一致性重构。重构(refactoring)在教材中通常指“在不改变外部行为的前提下重组内部结构”。但在真实仓库里,重构往往不是单纯机械替换。一个概念可能同时出现在类型定义、业务逻辑、测试、文档、配置文件、监控标签、命令行输出,甚至数据库迁移脚本中。

所以,一个真正可靠的重构任务,需要 Agent 具备:

  • 符号级导航能力,例如 LSP(Language Server Protocol,语言服务器协议)支持;
  • 超越纯文本搜索的语义搜索能力;
  • 对依赖传播路径的追踪能力;
  • 分阶段修改与分阶段验证的能力;
  • 在局部成功时仍能检查全局一致性的能力。

这也是为什么 Agent 架构比单纯模型能力更重要。模型再强,如果缺乏符号感知、诊断工具和安全编辑能力,也很难稳定完成仓库级重构。

24.1.4 完整生命周期覆盖才是真目标

更深的一层变化是:软件工程不是一次 edit(编辑),而是一个 lifecycle(生命周期)。未来成熟的 Coding Agent,至少应该在六个阶段里具备可用能力:

  1. 需求塑形:把模糊目标拆成可执行子任务;
  2. 设计与规划:给出架构方案、迁移路径、风险点和回滚思路;
  3. 实现:跨文件、跨模块地完成修改;
  4. 验证:运行诊断、测试、构建,并识别未覆盖区域;
  5. 交付:补全文档、变更说明、CI 配置与发布材料;
  6. 运行支持:帮助监控结果、分析异常、辅助修复后续问题。

今天大多数 Agent 在第三阶段最强,在第四阶段开始变得不稳定。长期来看,真正有竞争力的系统必须把能力扩展到全链路,而不是只在“写代码”这个局部做到惊艳。

24.1.5 从补丁思维到所有权思维

这会引出一个更深的标准变化:未来 Agent 不仅要会 patch,还要表现出 ownership。这个词在中文工程语境里常译为“所有权”或“主人翁意识”,但这里更准确的理解是“对任务结果承担整体责任的推进姿态”。它意味着系统不只完成表面修改,而是持续追踪目标、主动发现相邻工作、注意风险,并把支持性工作也补齐。

一个人类工程师如果只改代码,不看测试、不补文档、不检查发布影响,通常会被认为工作没有做完。未来 Agent 也会被用同样标准衡量。

24.1.6 接下来必须补上的四个能力缺口

要真正从代码生成走向软件工程执行,至少还有四个技术缺口要补上。

第一,长时段记忆但不过度漂移。系统要能长期记住项目目标,但又不能把过时结论当成真理。第二,更强的语义编辑能力。修改必须追踪“含义”,而不是只追踪字符串。第三,更强的环境感知。构建链、依赖、测试环境、部署配置都需要成为一等上下文。第四,更可靠的停止判断。Agent 要知道什么时候任务真的完成,什么时候仍有风险,什么时候应该升级给人类处理。

这些问题不只是模型问题,更是架构、工具和产品设计问题。

24.1.7 最终会走向什么

可以预见,“AI Coding Agent”这个名字本身可能都会显得过窄。最终胜出的系统,不会只是写代码,而是会读需求、看架构、做计划、调工具、做验证、补文档,并参与交付和后续维护。这已经不是单纯代码生成,而是软件工程行为。

因此,下一阶段并不是“模型取代工程师”,而是“自动化单元从一行代码,扩展到一个文件,再扩展到一个 Pull Request,最后扩展到整个工作流”。SWE-bench Pro 是这个趋势的信号,多文件重构是这个趋势的压力测试,而完整生命周期覆盖则是它的终点。

24.2 Vibe Coding与开发者角色

模型: gpt-5.4 (openai/gpt-5.4) 生成日期: 2026-04-01 书名: AI编码智能体 章节: 第24章 — 未来展望 Token 消耗: N/A(当前运行环境不暴露精确 token 统计)


Vibe coding” 这个词带有明显的互联网色彩,但它描述的是一个真实变化:开发者越来越多地通过自然语言、产品意图、界面感觉、参考案例和修改反馈来驱动实现,而不是亲手敲出每一行代码。这个术语并非经典计算机教材中的标准概念,因此需要做一点延伸解释。这里的 “vibe” 不是“随便写”的意思,而是指开发者先表达“我要的感觉、目标、约束和方向”,再由 Agent 去补足大量实现细节。

这意味着软件开发中的稀缺能力正在变化。开发者的价值不会消失,但会明显上移。

24.2.1 Vibe coding 到底在改变什么

过去,很多工程效率取决于开发者对语法、API 和记忆性模式的熟练度。今天,越来越多的常见模式可以被 Agent 快速生成:页面骨架、表单处理、CRUD 接口、测试模板、样式转换、配置拼装。开发者不再需要把所有重复劳动手工重做。

这带来的变化不是“开发者变得不重要”,而是工作重心从语句级实现,转向结果级控制。开发者可以说:做一个符合现有设计系统的设置页,支持深色模式、持久化偏好,并补上测试。Agent 给出初稿后,开发者的主要工作变成检查结构是否合理、边界条件是否被覆盖、用户体验是否匹配产品目标,而不是亲手把样板代码一行一行写完。

24.2.2 开发者角色为什么会向上移动

历史上,每一轮抽象提升都会减少底层重复劳动,同时提升高层判断的价值。编译器减少了人写机器码的必要性,但没有消灭程序员;Web 框架减少了基础设施重复建设,但没有消灭架构设计。AI Agent 很可能延续这一规律。

当实现成本下降后,更稀缺的东西会变得更重要,包括:

  • 决定到底该构建什么;
  • 设计系统边界和接口;
  • 识别隐藏约束;
  • 监督生成结果是否可信;
  • 保证实现与产品目标一致;
  • 在速度和风险之间做取舍。

因此,开发者的角色会更多转向 architecture(架构)supervision(监督)product interpretation(产品意图解释)

24.2.3 架构能力会变得更核心

当实现更便宜时,架构反而更贵,因为它决定了大量自动生成的代码能否彼此兼容。一个强大的 Agent 可以在几分钟内生成十个模块,但如果边界不清晰,也能在几分钟内生成十个互相冲突的模块。

所以未来优秀开发者会把更多精力放在:

  • 接口如何定义;
  • 数据归属如何划分;
  • 服务边界如何拆分;
  • 测试策略如何设计;
  • 迁移路径如何控制;
  • 扩展点如何预留。

这也是为什么“会写代码”本身会逐渐从核心竞争力,退居为基础能力。真正的区别在于:谁能构造出一个让 Agent 高速工作但又不容易失控的系统框架。

24.2.4 监督能力会成为一等工程技能

未来开发者越来越像是在管理非人执行者。这里的“监督”不只是做 code review(代码审查),而是更系统性的工作:设定范围、给出约束、要求计划、检查证据、确认验证方式,并在必要时及时收紧任务边界。

高质量监督通常包括:

  • 把任务拆到 Agent 更容易成功的粒度;
  • 提供足够上下文而不是只给一句口号;
  • 要求修改前后的验证步骤;
  • 识别 Agent 的“虚假自信”;
  • 确保多轮生成之间仍保持整体一致。

这使得开发者工作逐渐同时带有技术负责人、审查者、协调者的一部分特征。

24.2.5 产品意识会更接近编码流程

Vibe coding 还会压缩产品意图与实现之间的距离。如果 Agent 可以把一段描述迅速变成原型,那么瓶颈就会从“来不及实现”转向“有没有把用户结果定义清楚”。

这意味着开发者如果理解用户旅程、业务指标和运营约束,会比只会机械实现需求的人更有优势。因为未来最有价值的提示、最好的修改意见、最靠谱的验收判断,往往来自对“成功长什么样”的深刻理解,而不是对工单文字的字面执行。

24.2.6 哪些技能会贬值,哪些技能会升值

一些技能会相对贬值。例如:

  • 机械记忆语法;
  • 手写大量重复 CRUD;
  • 熟背框架模板;
  • 在常见样板代码上比拼手速。

另一些技能会显著升值:

  • 架构与接口设计;
  • 调试由 Agent 生成的复杂系统;
  • 设计评估标准与验收标准;
  • 构造高质量上下文;
  • 从仓库级别理解问题;
  • 安全与风险判断;
  • 与产品、设计、运营的跨角色沟通。

简言之,未来开发者更像是系统设计者与执行监督者,而不只是“代码生产者”。

24.2.7 Vibe coding 的风险:表面速度与深层债务

当然,Vibe coding 也有弱版本。弱版本的特点是:让 Agent 快速出结果,但人类并不真正理解系统,也没有维持工程纪律。这样会带来很高的 demo velocity(演示速度),却同时积累很重的 maintenance debt(维护债务,也就是后续维护成本)。界面可能很快做出来,但架构会变得模糊,测试可信度下降,安全边界也容易被忽视。

真正危险的不是 AI 写代码,而是人类在“看起来已经能跑”的幻觉下放弃工程责任。

24.2.8 更可能出现的新工作流

比较现实的 2026 年开发流程可能是:

  1. 开发者定义问题、约束和目标结果;
  2. Agent 生成计划和第一版实现;
  3. 开发者检查架构、命名、边界情况和取舍;
  4. Agent 继续完成重构、测试、文档和清理;
  5. 开发者基于产品影响和系统影响决定接受、调整或拒绝。

这依然是软件开发,只是劳动分布发生了变化:Agent 承担更多执行,人类承担更多方向控制。

24.2.9 从写作者走向编排者

所以,未来优秀开发者不会因为 AI 而消失,而是会变得更“高杠杆”。所谓高杠杆,指单位时间内通过更高层次的判断,驱动更大规模的产出。开发者会越来越像一个 orchestrator(编排者):组织模型、工具、验证流程和产品目标,让整个执行系统在正确方向上高速运转。

最终胜出的开发者,不会是完全拒绝 AI 的人,也不会是把判断全部交给 AI 的人,而是那些能把 Agent 的生成速度,转化成一致、可维护、符合产品目标的软件系统的人。

24.3 融合趋势

模型: gpt-5.4 (openai/gpt-5.4) 生成日期: 2026-04-01 书名: AI编码智能体 章节: 第24章 — 未来展望 Token 消耗: N/A(当前运行环境不暴露精确 token 统计)


未来 Coding Agent 的演化,不会是三条路线永久分裂,而更可能是持续融合。开源系统、编排层系统、商业系统目前仍然有鲜明差异:有的强调透明与可改造,有的强调多智能体调度,有的强调产品化与企业级可靠性。但随着行业成熟,它们正在不断互相吸收彼此的优势。最终的结果,未必是“一个系统统治全部”,更可能是形成一套共享底层能力,再在更高层做不同优化。

24.3.1 开源会继续推动安全能力前进

很多人会下意识认为:安全一定由商业系统主导,开源只负责灵活性。这种看法并不完整。开源生态之所以常常在安全设计上推进很快,恰恰因为其内部机制可以被外部审视。工具定义、权限边界、提示词拼装、命令执行包装、扩展接口这些东西一旦公开,就能被社区审计、质疑、修正和复用。

在 Coding Agent 领域也是如此。开源系统更容易快速试验沙箱、能力声明、白名单、文件操作保护、命令风险分级等机制。一旦某种安全模式被证明有效,就会迅速被传播。换句话说,开源常常像一个高速度实验室,它不一定一开始最稳,但它往往最先产生值得借鉴的安全设计。

24.3.2 商业系统会继续推动可扩展性前进

反过来看,商业系统也不再只是“封闭但好用”。一旦产品进入真实组织环境,用户就会强烈要求 extensibility(可扩展性)。企业不会满足于一个只能做通用任务的助手,它们需要接入内部工单系统、CI 平台、文档平台、监控系统、发布系统、知识库与合规流程。

所以商业产品也会越来越像“受控的平台”,而不是“固定功能的助手”。Claude Code 这类系统的意义就在这里:它展示了商业系统不仅可以保持产品化体验,也必须不断开放 hooks(钩子)、commands(命令)、tools(工具)、skills(技能)和任务编排能力,否则就无法深入组织级工作流。

24.3.3 MCP 会越来越像通用连接层

在所有融合趋势里,最重要的可能就是 MCP(Model Context Protocol) 的普及。它的重要性在于:它把原来容易混在一起的三件事拆开了——模型推理、工具访问、应用集成。只要工具能力能通过标准协议暴露出来,生态扩展速度就会明显加快。一个工具服务可以被多个宿主系统复用,一个宿主系统也可以消费许多外部能力。

这就是为什么 MCP 常被比作 AI 世界的 “USB-C”。这个比喻并不是教材术语,而是一种延伸解释:USB-C 的价值不在于它替代一切,而在于它降低连接成本、统一接口、提升互操作性。MCP 在 Agent 世界里扮演的正是类似角色。

24.3.4 共享底座之上,差异转向编排层

如果 MCP 成为通用连接层,那么未来系统之间还会有什么区别?主要差异会逐渐上移到 orchestration(编排)层。也就是说,越来越多产品可能共享类似底座:

  • 聊天与计划循环;
  • 工具调用;
  • 上下文管理;
  • 记忆层;
  • 标准化外部协议;
  • 可配置权限控制。

在这个共享底座之上,不同系统会通过编排策略拉开差距。有些产品强调单智能体的简洁与稳定,有些强调多智能体分工与后台任务,有些强调企业治理和成本控制。OpenCode 与 Oh-My-OpenCode 已经展示了一端,Claude Code 展示了另一端。未来它们会越来越像是在不同层次上优化同一类系统。

24.3.5 开源与商业正在交换传统优势

一个很有意思的现象是,双方正在交换各自过去的传统优势。开源系统逐渐认识到,若想真正进入团队生产环境,必须重视安全、信任与治理;商业系统则逐渐认识到,若想满足高级用户,必须重视透明度、可组合性和可编排能力。

这并不意味着“开源/闭源差异消失”,但意味着二者的实际能力边界正在缩小。行业开始从“意识形态竞争”转向“工作流适配度竞争”。

24.3.6 对用户意味着什么

这种融合对用户是好事。它降低了工具层面的锁定风险,也让团队更容易把能力建设在标准协议上,而不是绑定到某一个厂商私有接口上。未来组织可能会像今天选择编辑器、CI 平台或云服务一样选择 Agent 宿主环境:看治理方式、体验偏好和工作流适配,而不是因为“离开这个产品就没法复用任何工具”。

这尤其会强化 MCP 的价值。企业如果把内部能力封装成 MCP 服务,那么无论前端宿主是开源系统还是商业系统,很多投资都可以保留下来。

24.3.7 哪些东西仍然不会融合

当然,不是一切都会融合。至少有三层差异会长期存在。

第一,信任模型。商业产品可能持续在合规、审计、组织治理、企业认证上领先。第二,开发哲学。开源系统仍会更可改、更可查、更可实验。第三,工作流立场。有的产品会坚持极简,有的产品会内置更强流程假设。

所以,融合不等于同质化,而是“底层越来越互通,高层仍然保持风格差异”。

24.3.8 更可能出现的终局

更合理的终局想象是一个分层生态:MCP 或某种非常相似的协议成为通用底座;记忆、任务、工具、权限等能力逐步标准化;开源生态继续贡献最快的安全与编排创新;商业系统把这些创新产品化、加固,并送入需要规模化稳定性的组织中。

到了那时,真正的问题就不再是“这些系统会不会融合”,因为它们已经在融合。真正的问题变成:谁掌握协议层,谁掌握编排层,谁掌握治理层,谁掌握产品体验层。未来的赢家,可能不是只赢一层,而是在不同层上分别形成自己的优势。

24.4 未解决的挑战

模型: gpt-5.4 (openai/gpt-5.4) 生成日期: 2026-04-01 书名: AI编码智能体 章节: 第24章 — 未来展望 Token 消耗: N/A(当前运行环境不暴露精确 token 统计)


Coding Agent 虽然进步很快,但真正困难的问题其实还在前面。下一阶段的突破,不会只是输出更流畅,而是解决那些阻止团队把 Agent 用在更大范围工程任务上的可靠性问题。其中有四个挑战尤其关键:跨会话记忆一致性重构成本可预测性、以及 智能体之间的信任

24.4.1 跨会话记忆:既要记得住,又不能记错

今天的大多数 Agent 仍然主要擅长“单会话任务”。一旦上下文窗口结束,或者任务跨越数天,连续性就会迅速变脆弱。系统可能忘掉为什么要做某个设计决策,也可能重复已经失败过的方案,或者把不重要的细节记得很牢,却丢失真正关键的上下文。

很多人会觉得:跨会话记忆不就是把笔记存下来吗?但真正难点在于,记忆必须同时满足“持久”和“选择性”。存得太少,会失去上下文;存得太多,会堆积噪声;总结错了,又会把未来的工作锚定在错误前提上。

因此,真正可用的长期记忆需要:

  • 重要性排序;
  • 过期机制;
  • 可纠正能力;
  • 来源记录;
  • 不确定性标注。

“来源记录”这个说法对应英文里的 provenance,在传统 CS 教材里不算高频术语。这里可以理解为“某条记忆来自哪里、依据是什么、可信度如何”的追踪信息。没有 provenance,记忆就容易从“有帮助的历史”变成“难以质疑的幻觉”。

24.4.2 一致性重构:局部会改不等于全局会改

Agent 今天已经很会做局部修改,但在大仓库里保持一致性,仍然远没有成熟。一次广泛重构会同时考验命名纪律、符号追踪、依赖理解、测试判断和停止条件。真正难的不是“能不能把一个名字改掉”,而是“能不能把所有受影响的语义边界都正确更新,并知道哪些地方还没有被充分验证”。

这要求系统具备更强的语义工具、更好的增量规划能力,以及更诚实的置信度表达。未来理想状态下,Agent 不只是说“我改完了”,而应该能说:

  • 我修改了哪些文件;
  • 我验证了哪些代码路径;
  • 我确认了哪些接口边界;
  • 哪些区域仍存在不确定性;
  • 这些不确定性为什么无法在当前上下文内彻底消除。

在这种能力成熟之前,仓库级重构仍然会高度依赖人工监督。

24.4.3 成本可预测性:不仅要能做,还要知道值不值

另一个经常被低估的问题是成本可预测性。人类工程师做任务时,虽然也不精确,但通常能大致估计工作时长。Agent 系统则更难预测。一个看起来简单的任务,可能因为反复搜索、重复验证、错误分支、多智能体并发和上下文膨胀,变成高成本执行。

所以组织真正需要的不只是 token 账单,而是一套经济控制能力,包括:

  • 任务级预算;
  • 任务开始前的成本估计;
  • 按难度动态切换模型;
  • 当继续执行已不划算时及时停止;
  • 事后可归因的成本统计。

这里的“可归因”并非传统教材里的固定术语,可以理解为“花掉的成本最终能追溯到哪个任务、哪个子步骤、哪个智能体、哪类工具调用”。如果做不到这一点,组织就很难把 Agent 纳入稳定的生产预算体系。

24.4.4 智能体之间的信任:多智能体不是天然更好

随着系统越来越多地采用 multi-agent(多智能体)模式,一个新问题会出现:智能体应该如何彼此信任? 一个子智能体负责探索,一个负责修改,一个负责验证,听起来效率很高。但如果主智能体无法判断子智能体输出的质量,那么并行化只会制造更多噪声,而不是更多价值。

智能体之间的信任不能只靠自然语言摘要,还需要更明确的协议,例如:

  • 当初接到了什么任务;
  • 使用了哪些证据;
  • 读了哪些文件;
  • 改了哪些文件;
  • 哪些结论是确定的;
  • 哪些结论仍然不确定;
  • 置信度是根据什么得出的。

只有这样,多智能体系统中的 delegation(委派)才不是“把问题扔出去”,而是“把一个可审计、可集成的子任务交给其他执行者”。这对强调编排的系统尤其重要。

24.4.5 所有问题最终都指向验证瓶颈

上述四个挑战其实都指向同一个更深层问题:验证能力落后于生成能力。Agent 今天生成候选方案的速度,远快于证明这些方案可靠的速度。

跨会话记忆会出错,是因为记忆摘要缺乏强验证;一致性重构会失败,是因为语义一致性检查不够强;成本会失控,是因为缺乏与价值绑定的停止规则;多智能体容易失真,是因为子结果没有被强约束地验证。

行业经常把问题说成“推理能力还不够”,但很多时候更准确的说法是:验证架构还不够成熟。

24.4.6 可能的解法会是什么样

未来比较有希望的方案,大概率会包含几类模式。

对于记忆:项目日志、决策记录、带不确定性标记的长期笔记、按权威性和时效性检索的记忆系统。对于重构:符号级工具、依赖影响面分析、在修改前先自动生成 impact set(影响集合)。impact set 不是教科书高频词,这里可理解为“某项改动理论上会波及的文件、接口、测试与运行路径集合”。对于成本:预算感知计划、先用便宜模型探索、必要时再升级大模型、执行后透明计费。对于多智能体:类型化输出、证据包、置信字段以及主智能体的裁决层。

这些东西都不炫目,但它们很可能决定下一代产品谁能真正落地。

24.4.7 最终难题是“校准后的信任”

归根结底,用户并不要求 Agent 永远完美。用户真正需要的是一种 calibrated trust。这个词可以译为“校准后的信任”,意思不是盲目信任,而是“系统的能力边界、可靠程度和不确定性能够被相对准确地判断”。

如果系统能让人知道:什么时候大概率正确,什么时候只是猜测,什么时候必须升级人工介入,那么很多风险都能被管理。跨会话记忆、一致性重构、成本控制和智能体协作,最终都收敛到这一点。

因此,这些挑战之所以重要,不是因为它们是边缘问题,而是因为它们决定 Coding Agent 最终停留在“好用的助手”,还是进化成“可以承担较大工程责任的系统”。未来竞争的关键,不只是让 Agent 看起来更聪明,而是让它的行为更可测量、更有边界,也更值得信任。

25.1 起步决策树

模型: gpt-5.4 (openai/gpt-5.4) 生成日期: 2026-04-01 书名: AI编码智能体 章节: 第25章 — 构建你自己的智能体 Token 消耗: ~4,400 输入 + ~1,400 输出


如果你想构建自己的智能体,第一步不应该是罗列功能,而应该是画一棵决策树。功能清单会诱导你不断往系统里塞东西:更多工具、更多模型、更多模式、更多自动化。决策树则会逼你先回答一个更关键的问题:你到底要造什么样的系统?

这一章的重点不是赞叹 OpenCode、Oh-My-OpenCode 或 Claude Code 已经有多复杂,而是帮助你做出一个理性的起步架构。很多智能体项目不是死在实现能力不足,而是死在最开始的范围选择错误。

25.1.1 第一条分叉:Fork 现有宿主,还是从零开始?

对大多数团队来说,这是杠杆最大的一步。

如果你的主要创新点并不是宿主本身,而是编排、提示词、工作流、权限、技能系统或界面体验,那么基于现有宿主扩展通常更合理。比如以 OpenCode 为底座,你可以直接继承对话循环、模型接入、工具接口、会话处理,很多时候连 MCP(Model Context Protocol,可理解为模型与外部工具之间的标准连接协议)也已经具备。这样能省下几个月基础设施时间。

只有在你能明确说出“现有宿主在哪些架构前提上与我冲突”时,从零开始才值得。比如你要做的是极简本地智能体,不希望有太多抽象层;或者你的目标场景非常窄,不是通用软件工程,而是固件修复、基础设施值班手册、合同审阅之类的专门工作流;又或者宿主对于工具系统、会话模型、界面结构的假设会直接妨碍你。

一个实用判断是:如果现有宿主对你是“70% 加速,30% 束缚”,就拿来用;如果是“30% 加速,70% 束缚”,就重建。

25.1.2 第二条分叉:单模型深耕,还是多模型并行?

第二个核心问题是模型策略。

单模型深耕,是指围绕一个主模型族做深入优化。你的提示词、工具描述、上下文压缩、重试逻辑、输出格式,都会针对它调优。这样往往最容易在早期做出强体验。很多后来支持多模型的系统,起点其实也是这种方式。

多模型并行,则意味着你从一开始就做 provider(模型提供方)抽象和 capability(能力)抽象。听起来更通用,但代价很高。不同模型在工具调用稳定性、上下文长度、价格、延迟、多步指令服从性上差异很大。一个过早设计出来的统一抽象层,很容易变成 lowest common denominator(最低公分母):谁都能兼容一点,但谁都没被真正优化好。

如果你当前目标是验证体验质量,先单模型;如果你做的是平台型基础设施,多模型可以更早考虑。即便如此,也最好先选一个主模型作为优化基准。所谓“支持很多模型”,并不等于“在任何模型上都表现优秀”。

25.1.3 第三条分叉:助手,还是自主执行者?

这条分叉本质上是在问:人要不要持续在环。

助手型系统通常处理较短的任务链,人始终靠近控制台,关键动作需要确认,结果也会频繁复查。自主执行者则更像拿到目标后,连续执行较长链条,尽量少打断人。

高自主性当然诱人,但它会抬高几乎每一层设计门槛。你需要更强的停止条件、更好的失败恢复、更完整的验证闭环、更清楚的成本控制,以及更细致的信任校准。换句话说,自主性不是单个功能,而是很多枯燥但关键的机制叠加出来的系统属性。

如果你是在做第一个智能体,默认更适合从助手做起。一个可靠的半自主系统,往往比一个经常跑偏的高自主系统更有价值。

25.1.4 第四条分叉:产品,还是平台?

另一个常见误区,是太早把自己定义成平台。

如果你在做产品,核心目标是整体一致性。工具集更克制,行为更有主见,文档更容易写,支持成本也更可控。

如果你在做平台,你就必须提供扩展点:插件、钩子(hook,可理解为在生命周期特定位置插入自定义逻辑的接口)、第三方工具接入、版本兼容承诺,以及一定程度的生态治理。平台确实能带来杠杆,但它带来的不仅是能力,也是长期义务。一个插件 API,不只是方便开发者的接口,更是一份未来维护承诺。

不要因为“平台听起来更宏大”就选平台。只有当外部扩展能力本身就是产品论点的一部分时,才值得在早期投入。

25.1.5 第五条分叉:单智能体,还是多智能体?

这是很多人问得过早的问题。

单智能体系统更容易理解、更便宜、更容易调试。多智能体系统在某些任务天然可拆时会有价值,比如把探索、检索、实现、审查分成不同角色并行处理。

但多智能体也会引入委派逻辑、上下文传递、结果合并、重复劳动、假设不一致、Token 成本成倍增长等问题。如果你的单智能体还经常读错文件、计划漂移、验证不足,那么加 subagent(子智能体,即被主智能体派出去执行局部任务的独立执行单元)往往不是解决方案,而是把混乱放大。

比较稳妥的规则是:

  1. 默认先单智能体;
  2. 先用角色提示词模拟分工;
  3. 只有当某类任务反复证明“明确拆分角色有收益”时,再引入真正的委派。

25.1.6 一棵可操作的起步树

你可以把起步问题压缩成下面六问:

  1. 这是学习或实验载体,还是长期维护产品?
  2. 如果是产品,现有宿主能不能显著加速首版?
  3. 我需要先把一个模型做到最好,还是先追求可移植性?
  4. 用户是否会长期在环,还是系统要长时间自主执行?
  5. 第三方扩展是现在就必需,还是以后再做?
  6. 现在是否已经存在明确需要多智能体的工作负载?

每个分叉本质上都是权衡:杠杆 vs 架构纯净、深度优化 vs 可移植性、自主性 vs 可控性、扩展性 vs 简洁性、编排能力 vs 运维清晰度。

没有放之四海而皆准的唯一正确答案,只有对你当前阶段更合适的答案。

25.1.7 对大多数构建者的默认建议

对大多数团队而言,最好的起步路线其实很保守:以现有宿主为基础扩展、优先围绕一个主模型深耕、先保持单智能体、初始工具集尽量小、平台化野心往后放。

这条路线不炫,但学习速度最快。它让你先看到真实失败模式,再决定哪些抽象值得固化。因为智能体系统里最容易做错的,往往不是具体功能,而是过早抽象。

真正推进得快的团队,通常不是一开始架构画得最大的团队,而是最少做出不可逆决策的团队。

25.2 最小可行智能体

模型: gpt-5.4 (openai/gpt-5.4) 生成日期: 2026-04-01 书名: AI编码智能体 章节: 第25章 — 构建你自己的智能体 Token 消耗: ~4,500 输入 + ~1,450 输出


如果第25章只有一条建议,那就是:先做一个最小可行智能体,而不是一上来就追求“最大想象架构”。早期目标不是复制 OpenCode、Oh-My-OpenCode、Claude Code 的全部能力,而是先造出一个能做真实工作、会以可观察方式失败、并且能教你下一步该加什么的小系统。

最稳妥的起点,就是 ReAct loop 加五个核心工具:read、write、bash、grep、glob。

25.2.1 为什么 ReAct 仍然是最好的起点

ReAct 可以理解为一种“推理—行动—观察—更新—重复”的循环结构。它的价值不在于概念新,而在于它能抑制幻觉。只让模型想,模型很容易脑补仓库细节;强迫它去读文件、搜代码、跑命令、再回头修正判断,它才会被现实锚定。

一个最基础的循环可以写成:

  1. 理解用户目标;
  2. 判断缺什么信息;
  3. 用工具去环境里找信息;
  4. 形成或更新计划;
  5. 做一次边界清晰的修改;
  6. 验证结果;
  7. 继续或停止。

就这么简单,但已经足够构成一个可用的工程助手。

25.2.2 为什么是这五个工具

推荐的起步工具集故意很朴素。

Read 用来读取源码、配置、测试、日志、文档。没有可靠读取,后面几乎全是猜。

Write 用来创建或覆盖内容。无论底层实现是整文件写入、结构化编辑,还是补丁应用,本质都是让智能体能把修改真正落盘。

Bash 对应真实执行面:构建、测试、包管理、格式化、脚本、容器、运行时检查,都要通过它进入系统环境。

Grep 对应内容搜索。当智能体知道自己在找什么概念,但不知道它在哪个文件里时,grep 通常是最快路线。

Glob 对应文件发现。它帮助智能体在还不理解仓库时,先建立一个粗略地图。

这五个工具合起来,刚好覆盖人类工程师面对陌生代码库时的基本动作:发现、查看、搜索、修改、验证。

25.2.3 这个 MVP 已经能做什么

不要小看这样一个最小系统。

仅靠这套循环和这五个工具,智能体已经能修小 bug、加窄功能、更新测试、改配置、修文档、做不少维护类工作。它可以先定位问题,再找到相关文件,修改后跑测试,最后说明改了什么。

更重要的是,它能暴露你系统真正的薄弱处。你会很快看见:模型在哪里喜欢猜、哪些工具输出噪声太大、计划在哪里漂移、编辑何时不安全、验证为什么太浅。这些经验,比你过早实现复杂编排更值钱。

25.2.4 真正重要的不是“功能少”,而是“行为稳”

很多人把 MVP 误解成“功能越少越好”。在智能体设计里,MVP 更准确的意思是:用最小复杂度换取足够可靠的行为。

因此,早期应该把精力花在这些地方:工具描述是否清楚、输入输出 schema(结构约定)是否稳定、工具行为是否有边界、停止条件是否明确、计划是否能轻量保存、完成前是否强制验证。

一个只有五个好工具、但验证纪律很强的智能体,通常比一个二十个工具、行为却模糊的系统更有用。

25.2.5 按真实痛点扩展,而不是按想象中的完整版扩展

当这个 MVP 已经可用时,你应该根据反复出现的失败去扩展,而不是根据架构野心去扩展。比较合理的顺序是:

  1. 更安全的编辑能力,例如 patch 或 diff;
  2. 更聪明的导航能力,例如 LSP(Language Server Protocol,语言服务协议,用于符号级导航与诊断)或 AST(Abstract Syntax Tree,抽象语法树,用于按代码结构而非纯文本理解程序)搜索;
  3. 会话连续性,支持中断恢复;
  4. 权限控制,尤其是命令执行与写文件;
  5. 外部集成,例如 MCP;
  6. 委派,只有当单智能体已经稳定时,再考虑子智能体。

这个顺序并不随意,它符合早期智能体最常见的痛点曲线。大多数第一代系统不是输在“没有多智能体”,而是输在读不准、改不稳、记不住、验不全。

25.2.6 必须克制工具膨胀

Tool bloat(工具膨胀)是让智能体快速变差的常见路径。

每次失败都很容易诱发“再加一个工具”的冲动。找不到代码,就加代码地图;忘了计划,就加 planning tool;改坏文件,就加 refactor tool;看不懂搜索输出,就加 summarizer。

有时这确实必要,但很多时候问题不在工具缺失,而在工具说明含糊、输出格式混乱、提示词约束不足,或者压根没有验证步骤。加工具可能只是把真正的问题遮住,同时还提高了模型的选择负担和维护成本。

因此,一个默认问题应该是:现有工具集真的不够,还是我们还没把它们用清楚、用稳定?

25.2.7 一个紧凑但重要的心智模型

最小可行智能体,其实只要承担三类职责:感知现实、改变现实、检查现实。

如果你的系统能把这三件事做好,它就已经具备一个真正 coding agent 的基础。

25.2.8 从这里开始

所以,构建者到底应该从哪里开始?从 ReAct 循环开始。给它 read、write、bash、grep、glob。把工具描述写清楚。把验证变成强制环节。然后把系统投入真实任务。

不要按野心扩张,要按证据扩张。观察它如何失败,给失败分类,再一层层增加能力。小系统之所以能长成严肃系统,不是因为它一开始就很大,而是因为它每一步扩张都建立在真实需要上。

25.3 避免的陷阱

模型: gpt-5.4 (openai/gpt-5.4) 生成日期: 2026-04-01 书名: AI编码智能体 章节: 第25章 — 构建你自己的智能体 Token 消耗: ~4,350 输入 + ~1,420 输出


一旦你开始构建自己的智能体,真正的危险通常不是缺乏想象力,而是野心放错了方向。很多构建者看到 OpenCode、Oh-My-OpenCode、Claude Code 这类成熟系统,就误以为成熟来自功能数量。实际上,很多早期智能体项目恰恰是因为复杂性增长得比证据更快,最后把自己拖垮。

这里重点谈四类高频陷阱:工具膨胀、过度工程化、忽视安全,以及试图让一个智能体解决所有问题。

25.3.1 陷阱一:工具膨胀

所谓 tool bloat(工具膨胀),就是每观察到一次失败,就新增一个工具。没找到文件,就加仓库地图;改坏了文件,就加 patch tool、refactor tool、review tool;被长输出弄糊涂了,就再加 summarizer、compressor、smart context service。

结果往往不是更强,而是更差。因为每增加一个工具,模型就多了一层选择复杂度。它不只要决定“做什么”,还要决定“该调用哪个接口、它和相邻接口有什么差别、什么时候才安全”。工具功能重叠还会带来隐性不稳定:两个搜索工具、三个编辑工具、四种结构获取方式,语义却并不完全相同。

解决办法是纪律。不要因为单次失败就加工具。只有当某类失败反复出现,并且明确不能通过更清晰的提示词、更紧凑的输出、或更好的既有工具组合解决时,才值得新增工具。

25.3.2 陷阱二:第一版就过度工程化

第二类陷阱,是在版本一还没跑通之前,就开始设计版本三。

这种情况在架构图上通常非常壮观:provider 抽象、技能系统、权限中间层、多智能体路由、分层记忆、插件 SDK、后台任务、工作流图、评测面板、企业策略钩子。每个组件单独看都很合理,问题在于时机。

如果基础执行循环本身还不可靠,这些附加层并不会自动把产品变好。它们只会制造更多隐藏故障的位置。你可能花了几个月把扩展表面做得很漂亮,但系统仍然不能稳定地读文件、做边界清晰的修改、执行验证。

正确顺序很朴素:先证明一个小而稳的执行环真的能工作,再在真实需求推动下往上长结构。

25.3.3 陷阱三:因为本地或内部就忽视安全

智能体构建者经常把安全往后放,因为第一批用户是可信同事,或者系统只跑在本地机器上。这是很短视的。

即便是本地智能体,也可能执行破坏性 shell 命令、覆盖文件、在日志里泄漏凭据、跟随仓库里的恶意指令、调用不安全的外部工具。内部不是 threat model(威胁模型,即攻击面、风险来源、损害后果的系统性分析),它只是一个很容易失效的乐观假设。

智能体安全应该从 capability boundary(能力边界)开始想:哪些工具可以写文件?哪些工具可以执行命令?哪些工具能联网?允许操作哪些路径?哪些操作必须人工确认?输出里如何过滤密钥?第三方扩展如何隔离?

你当然不必第一天就做企业级策略系统,但第一天就应该有威胁模型。

25.3.4 陷阱四:试图覆盖所有用例

另一种高频失败模式,是普适主义冲动。构建者希望一个智能体同时充当程序员、研究员、运维助手、浏览器自动化工具、企业搜索层、文档写手、数据分析器和终端副驾驶。

这种广泛野心可以理解,但通用性不是免费的。不同任务需要不同工具、不同安全边界、不同评估标准,有时甚至需要完全不同的交互形态。一个针对代码修改优化的智能体,并不会自动对网页工作流或数据管道同样优秀。

更健康的方式,是先选择一个足够尖锐的工作负载。比如你先让智能体特别擅长仓库内工程任务;或者特别擅长测试修复;或者专注某一种语言的重构。聚焦不是弱点,而是质量出现的前提。

25.3.5 次级陷阱:把 Demo 成功误当成产品成熟

有些系统在精心准备的演示里很惊艳,因为仓库很干净、任务很窄、验证路径很清楚。但真实世界不是这样。真实仓库往往混乱、权限不一致、脚本会失败、依赖会漂移、需求还含糊不清。

如果构建者只为 demo 时刻优化,就会系统性低估错误处理、断点恢复和信任校准的重要性。这样的产品在台上看起来像魔法,进了日常工程环境后就会迅速暴露脆弱性。

25.3.6 次级陷阱:验证太弱

很多智能体构建者把主要精力放在生成上,却忽略验证。但对 coding agent 来说,只会产出、不做检查,并不等于可靠,只等于更有自信地猜。

验证在早期可以很简单:跑测试、看 diff、检查诊断、确认文件是否存在、验证 schema 是否有效。关键不是验证多复杂,而是验证必须是流程的一部分,而不是可有可无的收尾动作。一个会自信修改、却很少认真验证的智能体,迟早会积累隐藏缺陷。

25.3.7 次级陷阱:把所有保障都压给模型自己记住

语言模型很灵活,但不应该承担本来该由 scaffold(脚手架,即围绕模型构建的执行框架与约束层)保证的东西。如果安全路径能在工具层强制,就不要只在提示词里提醒;如果危险命令需要确认,就让执行层真的拦住;如果 Token 成本必须记录,就在外部做埋点;如果输出需要结构化解析,就定义 schema。

一个很好用的原则是:凡是软件可以强制保证的,不要只靠模型“记住”去保证。

25.3.8 更健康的默认哲学

为了避免这些陷阱,你可以采用一种更克制的默认哲学:初始工具集保持小、只有在反复证据出现后才加抽象、尽早建立真实威胁模型、先选窄场景再慢慢扩张、把验证做成强制环节。

真正强的智能体系统,不是第一天就试图做最多的系统,而是能一层层长大、同时不丢失整体一致性的系统。

如果要说一个元陷阱,那就是误以为成熟来自不断添加。很多时候,成熟恰恰来自在真正理解当前层之前,拒绝继续添加。

25.4 度量什么

模型: gpt-5.4 (openai/gpt-5.4) 生成日期: 2026-04-01 书名: AI编码智能体 章节: 第25章 — 构建你自己的智能体 Token 消耗: ~4,300 输入 + ~1,430 输出


如果你要自己构建 coding agent,度量体系就是乐观叙事和真实能力之间的分界线。很多团队会花大量时间调提示词、调工具、调编排,然后用一种很松散的方式判断进展:比如感觉更聪明了、昨天演示效果不错、最近做成了几个任务。这远远不够。

你需要一组足够紧凑、但能覆盖有用性、可靠性、成本和人工负担的指标。对早期 coding agent 来说,最重要的四个指标是:SWE-bench 基线、任务完成率、人工介入频率、单任务 Token 成本。

25.4.1 先有一个共享基线:SWE-bench

SWE-bench 当然不是全部,但它是一个很有价值的锚点。它提供的是 grounded(落在真实仓库和真实 issue 修复上的)软件工程任务。即便你的内部工作负载和它不完全一样,像 SWE-bench 这样的基准也能给你一个外部参照。

它的意义不是让你为了刷榜而牺牲产品价值,而是防止自我欺骗。如果你的智能体在仓库内修复类任务上,比一个中等基线还差很多,那说明有问题;如果你改了工具或提示词后,基准表现明显提升,那也是信号。

因此,更好的理解方式是:把 SWE-bench 当作 calibration instrument(校准仪器),而不是把它当作完整地图。

25.4.2 重点测任务完成率,而不是只看输出质量

对真实可用性来说,最重要的指标通常是 task completion rate(任务完成率):系统有多大概率能在允许的流程内,正确完成被分配的任务。

这里的完成必须定义清楚,不能等同于输出了一段答案。根据任务类型,完成通常意味着改对了文件、测试或检查通过、没有引入被禁止的副作用、最终结果被人类审阅者接受。

为什么这个指标如此关键?因为 coding agent 是系统,不是单纯文本生成器。附带优雅解释的一份错误补丁,不算成功。任务完成率捕捉的是你真正关心的端到端属性。

25.4.3 度量人工介入频率

第二个非常关键的指标,是 human intervention frequency(人工介入频率):人需要多频繁地站出来解堵、纠偏、纠错、批准操作。

两个系统可能表面完成率差不多,但使用体验完全不同。一个系统大部分任务能自己跑通;另一个系统则需要用户不断补提示、重跑命令、修路径、回滚错误修改、手动做验证。

如果介入频率很高,这个系统未必真正降低了工作量,它只是把工作从写代码换成了监督智能体。

这个指标还可以细分:因安全确认产生的介入、因计划错误产生的介入、因工具失败产生的介入、因验证失败产生的介入、因上下文丢失或混乱产生的介入。

这些子类能帮助你看清摩擦到底出在哪一层。

25.4.4 度量单任务 Token 成本

第三个运维指标,是 token cost per task(单任务 Token 成本)。这个指标之所以重要,是因为智能体系统往往会在真正有效之前,先变得非常昂贵。更多工具、更长上下文、更多重试、更多委派、更冗长输出,都会持续推高 Token 消耗。

这里的成本应该按完整任务来算,而不是只算最后那次成功调用。探索、重试、失败分支、验证回路、总结压缩,如果有,都应该计入。否则你会系统性低估真实运行画像。

这个指标不只对商业产品重要,对内部工具同样重要。商业产品需要毛利纪律,内部工具需要预算可预测性。在两种场景下,无价值的 Token 燃烧都说明设计存在问题。

25.4.5 不只看总量,更要看比例关系

很多时候,原始数字没有标准化后的视图有用。你可以优先看这些比率:各类任务的完成率、每个成功任务消耗多少 Token、每个成功任务平均需要多少次人工介入、成本相对于节省的人类时间是否划算。

这些比率能帮助你区分贵但有效和贵且混乱,也能避免被少量精挑细选任务误导。

25.4.6 加一点内部追踪,才能知道为什么失败

上面四个核心指标告诉你系统是否在进步;要理解为什么进步或为什么退化,你还需要加一些轻量追踪:工具调用次数、重试次数、验证失败次数、失败时的上下文大小、最常见的终止原因。

你不需要一开始就搭一个庞大的可观测性平台,但你至少要有足够的信息,解释一项任务为什么失败,或者一次成本为什么突然飙高。

25.4.7 警惕 Goodhart 定律

Goodhart’s Law(古德哈特定律)的意思是:当一个指标变成目标,它往往就不再是一个好指标。智能体系统尤其如此。若只优化 benchmark 分数,你可能对任务分布过拟合;若只优化低 Token 成本,你可能把验证砍得过头;若只优化低人工介入,你可能会让系统在不安全的情况下越权执行。

因此,这四个指标必须合起来看,它们共同形成一种平衡:基准校准、真实完成、人类负担、运行成本。

没有任何单一数字足以代表智能体质量。

25.4.8 一个早期好仪表盘应该长什么样

对早期构建者来说,一个有用的仪表盘其实可以非常简单:SWE-bench 或内部基准通过率、真实任务完成率、平均每任务人工介入次数、平均每任务 Token 使用量与美元成本、顶部失败类别的简短分布。

这些就足够指导迭代。它能告诉你:系统是不是更有用、更自主、更省钱。

真正强的构建者,不只是问这个智能体看起来厉不厉害,而是问它在我关心的工作上,是否正在被可测量地改进。从讲故事走向可仪表化,是一个智能体项目真正开始成熟的明显标志。

26.1 Claude Code 的扩展面:今天能做什么

模型: claude-opus-4-6 (anthropic/claude-opus-4-6) 生成日期: 2026-04-01 书名: Claude Code VS OpenCode:架构、设计与未来 章节: 第26章 — 设计“Oh-My-Claude-Code“ Token 消耗: ~6,200 输入 + ~1,100 输出


在讨论如何为 Claude Code 构建一个多智能体编排层之前,必须先清点它今天实际暴露了哪些扩展接口。一个系统的可扩展性不取决于它有多少功能,而取决于它把哪些功能的控制权交给了外部开发者。

26.1.1 五个核心扩展面

钩子系统(Hooks)

Claude Code 提供了 5 个生命周期钩子点:

钩子触发时机典型用途
PreToolUse工具调用前安全拦截、参数校验
PostToolUse工具调用后结果审计、日志采集
Notification通知触发时外部告警集成
Stop智能体停止时清理工作、状态持久化
SubagentStop子智能体停止时子任务结果汇总

这些钩子通过 .claude/settings.json 配置,以 shell 命令形式执行。它们的设计哲学明确偏向可观测性与安全防护——你可以看到发生了什么,可以在危险操作前拦截,但你不能改变对话本身的内容流。

衍生解释:生命周期钩子(Lifecycle Hook)——这个概念源自框架设计,指的是在系统运行的关键节点(如初始化、执行前、执行后、销毁)预留的回调插槽。开发者可以在不修改框架源代码的情况下,在这些节点注入自定义逻辑。React 的 useEffect、Vue 的 onMounted、Kubernetes 的 preStop 都是同一思想的体现。

自定义智能体(Custom Agents)

通过 .claude/agents/ 目录,用户可以用 Markdown 文件定义专门化的智能体。每个 .md 文件就是一个智能体的系统提示词,可以在对话中通过 /agent 命令调用,或被 AgentTool 以子智能体方式派遣。

这是 Claude Code 扩展面中最灵活的部分——因为系统提示词几乎可以编码任意行为逻辑。Oh-My-OpenCode 的“Sisyphus 提示“方法,本质上就是把完整的编排规则写进系统提示词。

MCP 服务器

通过 .claude/mcp.json 配置外部 MCP 服务器,为智能体动态增加工具。MCP(Model Context Protocol,模型上下文协议)是 Anthropic 主导的开放标准,充当 LLM 与外部服务之间的“USB-C 接口“。

MCP 是三个系统共有的扩展机制,但对 Claude Code 而言尤其关键——因为它是唯一一种不需要修改 Claude Code 源码就能新增工具的方式。OpenCode 和 Oh-My-OpenCode 可以通过插件系统的 tool 钩子直接注册原生工具,Claude Code 目前没有等价能力。

插件系统(Plugins)

Claude Code 的插件目录 .claude/plugins/ 支持注册自定义命令、工具和技能。但需要注意,这里的“插件“与 OpenCode 的插件系统在架构深度上有本质区别。OpenCode 的插件拥有 8 个生命周期钩子点的完整控制权,能够拦截消息流、变换上下文、注入配置。Claude Code 的插件更接近“预打包的命令集合“——它扩展了交互界面,但没有深入对话引擎的内部。

记忆系统(CLAUDE.md)

CLAUDE.md 文件及其层级结构(全局 ~/.claude/CLAUDE.md、项目根目录 CLAUDE.md、子目录 CLAUDE.md)构成了 Claude Code 的持久化记忆。智能体在每次会话开始时自动加载这些文件,将其内容注入系统提示词的上下文中。

26.1.2 暴露了什么 vs 锁定了什么

理解 Claude Code 的扩展边界,关键在于区分“暴露“与“锁定“:

已暴露(可外部控制):

  • 工具调用的前后拦截(通过钩子)
  • 新工具的注入(通过 MCP)
  • 智能体行为的定制(通过自定义智能体提示词)
  • 持久化上下文(通过 CLAUDE.md)
  • 会话停止时的清理逻辑(通过 Stop 钩子)

已锁定(无法从外部控制):

  • 用户消息到达 LLM 之前的拦截与变换
  • 对话历史的动态修改或注入
  • 模型选择(不同智能体不能使用不同模型)
  • 工具注册的编程式 API(必须通过 MCP 协议)
  • 上下文压缩策略的定制
  • 子智能体的并发调度与会话延续

这个暴露/锁定的划分揭示了一个清晰的设计意图:Claude Code 把安全性和可观测性放在了扩展优先级的最高位,而把对话引擎的控制权牢牢握在自己手中。这种取舍在商业产品中完全合理——它保证了用户体验的一致性和安全底线。但对于想要构建深度编排层的开发者来说,这意味着很多在 OpenCode 上轻而易举的事情,在 Claude Code 上需要绕行甚至根本做不到。

26.1.3 小结

Claude Code 今天的扩展面足以支撑相当丰富的定制场景:你可以定义专门化智能体、接入外部工具、在关键节点插入安全检查、维护跨会话的项目记忆。但如果你的目标是像 Oh-My-OpenCode 那样构建一个完整的多智能体编排层——包括消息变换、上下文注入、工具执行拦截、智能体级模型路由——那么当前的扩展面还不够。

下一节,我们将精确对比这些差距。

26.2 差距分析:OpenCode 插件 API vs Claude Code 扩展 API

模型: claude-opus-4-6 (anthropic/claude-opus-4-6) 生成日期: 2026-04-01 书名: Claude Code VS OpenCode:架构、设计与未来 章节: 第26章 — 设计“Oh-My-Claude-Code“ Token 消耗: ~6,800 输入 + ~1,300 输出


Oh-My-OpenCode 之所以能在 OpenCode 之上构建出完整的多智能体编排层,核心原因不是它代码量大——13 万行代码只是结果——而是 OpenCode 的插件 API 暴露了 8 个生命周期钩子点,覆盖了从配置注入到消息变换的完整生命周期。Claude Code 的扩展 API 设计目标不同,暴露面更窄。这一节用精确对比来量化二者的差距。

26.2.1 OpenCode 的 8 个钩子点:完整生命周期控制

OpenCode 的插件系统为外部代码提供了 8 个介入点:

钩子点功能OMO 如何使用
config注入智能体、工具、MCP、命令到宿主注册表注册 11 个智能体、26 个工具、多个 MCP
tool注册自定义工具(编程式 API)通过 tool-registry.ts 注册全部自定义工具
chat.message拦截每条用户消息,在到达 LLM 前首消息变体门控、会话初始化、关键词检测
chat.params修改发送给 LLM 的请求参数调整 Anthropic effort level
event监听会话生命周期事件会话创建/销毁、状态追踪
tool.execute.before工具实际执行前拦截文件守卫、标签截断、规则注入
tool.execute.after工具执行完成后拦截结果处理、审计日志
experimental.chat.messages.transform变换整个消息数组(发送给 LLM 之前)上下文注入、thinking block 校验、todo 保留

这 8 个钩子点构成了一个完整的请求生命周期拦截链:从配置加载 → 消息到达 → 参数调整 → 消息变换 → 工具执行前后 → 事件通知。Oh-My-OpenCode 在这 8 个点上复用出了 41 个内部钩子,实现了从智能体路由到上下文工程的全部编排逻辑。

衍生解释:拦截链(Interceptor Chain)——这一模式在传统中间件架构中非常常见。Java 的 Servlet Filter、Express.js 的中间件栈、gRPC 的拦截器,都是同一思想:请求在到达最终处理器之前,依次经过一系列可插拔的处理环节,每个环节可以观察、修改甚至终止请求。OpenCode 的 8 个钩子点本质上就是一个面向 AI 智能体的拦截链。

26.2.2 Claude Code 的钩子:安全/可观测性聚焦

Claude Code 的 5 个钩子点(PreToolUsePostToolUseNotificationStopSubagentStop)覆盖的是另一个维度。它们的共同特征是:

  1. 只观测不变换——钩子接收事件数据但不能修改对话流
  2. 以 shell 命令执行——不是编程式 API,无法访问内部状态
  3. 聚焦在工具层——没有消息级别的拦截

这种设计是有意为之。Claude Code 作为商业产品,把对话引擎的完整性视为安全基线。允许外部代码修改消息流等同于打开了 prompt injection(提示注入,指恶意输入试图劫持 LLM 行为)的攻击面。

26.2.3 关键差距对比表

能力维度OpenCode 插件 APIClaude Code 扩展 API差距评级
配置注入(智能体/工具/MCP)config 钩子⚠️ 通过文件约定(.claude/agents/.claude/mcp.json
编程式工具注册tool 钩子❌ 仅通过 MCP 协议
用户消息拦截chat.message❌ 无等价物极高
LLM 请求参数修改chat.params❌ 无等价物
会话事件监听event⚠️ Stop/SubagentStop 仅覆盖结束事件
工具执行前拦截tool.execute.before⚠️ PreToolUse(只能观测/阻止,不能修改参数)
工具执行后拦截tool.execute.after⚠️ PostToolUse(只能观测,不能修改结果)
消息数组变换experimental.chat.messages.transform❌ 无等价物极高

26.2.4 三个“极高“差距的具体影响

chat.message 等价物

这意味着无法在用户消息到达 LLM 之前进行处理。Oh-My-OpenCode 用这个钩子实现了:首消息变体门控(根据消息内容决定激活哪个智能体变体)、关键词检测(识别 @agent 提及)、会话状态初始化(设置 boulder state 以追踪 Sisyphus 续接)。在 Claude Code 上,这些逻辑只能通过系统提示词间接编码,精确度和灵活性大幅下降。

衍生解释:变体门控(Variant Gate)——指根据运行时条件动态选择系统行为变体的机制。类似于 A/B 测试中的流量分配,但这里分配的不是用户流量,而是智能体的行为模式。比如同一个智能体在接收到“紧急修复“类消息时切换为极简快速模式,接收到“重构“类消息时切换为深度分析模式。

tool.execute.before/after 的变换能力

Claude Code 的 PreToolUse/PostToolUse 可以观察工具调用,但不能修改工具参数或返回结果。Oh-My-OpenCode 用 tool.execute.before 实现了文件守卫(阻止对受保护文件的写入)、标签截断器(限制工具输出大小以节省上下文窗口)、规则注入器(根据文件类型自动注入编码规范)。在 Claude Code 上,文件守卫可以通过 PreToolUse 的阻止功能近似实现,但标签截断和规则注入无法做到。

无消息变换

这是差距最大的一项。experimental.chat.messages.transform 允许 Oh-My-OpenCode 在每次 LLM 调用前重写整个消息数组。这是上下文工程的核心杠杆——注入项目规则、校验 thinking block 格式、保留 todo 状态、移除过期的临时上下文。没有这个能力,Claude Code 上的上下文工程只能依赖 CLAUDE.md 的静态内容和系统提示词的预设逻辑,无法实现动态的、逐轮的上下文调整。

26.2.5 小结

差距不意味着缺陷。Claude Code 的扩展 API 完美服务了它的设计目标:安全、可观测、易用。但如果目标是在 Claude Code 上构建 Oh-My-OpenCode 级别的编排层,那么当前的扩展面覆盖了大约 40% 的所需能力。剩下的 60% 要么需要绕行方案(通过系统提示词编码),要么需要 Claude Code 开放更多钩子点。

下一节,我们将在这些约束下设计一个务实的架构蓝图。

26.3 架构蓝图:Oh-My-Claude-Code

模型: claude-opus-4-6 (anthropic/claude-opus-4-6) 生成日期: 2026-04-01 书名: Claude Code VS OpenCode:架构、设计与未来 章节: 第26章 — 设计“Oh-My-Claude-Code“ Token 消耗: ~7,100 输入 + ~1,300 输出


在上一节我们看到,Claude Code 的扩展 API 覆盖了构建多智能体编排层约 40% 的能力需求。这一节的问题是:在这 40% 的地基上,能搭出什么样的建筑?

答案是:一个以系统提示词为编排引擎、自定义智能体为执行单元、MCP 为工具扩展层的架构。它不如 Oh-My-OpenCode 那样能深入对话引擎内部,但足以实现多智能体协作、任务委派、专业化分工和持久化记忆。

26.3.1 核心设计原则

Oh-My-Claude-Code 的架构建立在三个约束下的最优化原则上:

原则一:提示词即编排器。 既然无法通过钩子拦截消息流,那就把编排逻辑直接写进系统提示词。这就是“Sisyphus 提示“方法——把任务分解规则、委派策略、完成验证、续接逻辑全部编码为提示词中的行为指令。

衍生解释:Sisyphus 提示(Sisyphus Prompt)——源自希腊神话中西西弗斯反复推石上山的故事。在 Oh-My-OpenCode 中,这个概念指的是在系统提示词里嵌入“永不放弃“的续接逻辑:当智能体的上下文窗口耗尽或任务中断时,它会通过 todo 列表记录进度,在新会话中从断点继续。这种机制保证复杂任务不会因为单次会话限制而被放弃。将其迁移到 Claude Code,意味着在自定义智能体的 Markdown 定义中编码同样的续接规则。

原则二:智能体即微服务。 每个自定义智能体是一个有明确职责边界的执行单元,通过 AgentTool 被主智能体调度。这类似于微服务架构中服务间的 RPC 调用——调用方不关心被调用方的内部实现,只关心输入输出契约。

原则三:MCP 是唯一工具注入通道。 所有超出 Claude Code 内建工具的能力,都通过 MCP 服务器引入。

26.3.2 整体架构

┌─────────────────────────────────────────────────────────┐
│                    用户交互层                              │
│                 Claude Code TUI/IDE                      │
└─────────────────────┬───────────────────────────────────┘
                      │ 用户消息
                      ▼
┌─────────────────────────────────────────────────────────┐
│              主智能体 (Sisyphus)                          │
│  ┌─────────────────────────────────────────────────┐    │
│  │  系统提示词 = 编排引擎                             │    │
│  │  • 任务分析与分解规则                              │    │
│  │  • 委派策略(何时派遣哪个子智能体)                  │    │
│  │  • Todo 纪律(必须维护任务列表)                    │    │
│  │  • 验证协议(LSP 检查 + 构建通过)                  │    │
│  │  • Sisyphus 续接(中断时保存进度)                  │    │
│  └─────────────────────────────────────────────────┘    │
│                      │                                   │
│         AgentTool 委派 │                                   │
│     ┌────────────────┼────────────────┐                  │
│     ▼                ▼                ▼                  │
│ ┌────────┐    ┌───────────┐    ┌───────────┐            │
│ │ Oracle │    │  Explore  │    │ Librarian │            │
│ │ 智能体  │    │  智能体    │    │  智能体    │            │
│ │        │    │           │    │           │            │
│ │ 深度    │    │ 代码库    │    │ 文档      │            │
│ │ 推理    │    │ 探索      │    │ 研究      │            │
│ └────────┘    └───────────┘    └───────────┘            │
│     ▲                ▲                ▲                  │
│     └────────────────┼────────────────┘                  │
│                      │                                   │
│              结果返回给主智能体                             │
└─────────────────────┬───────────────────────────────────┘
                      │
          ┌───────────┼───────────┐
          ▼           ▼           ▼
    ┌──────────┐ ┌─────────┐ ┌──────────┐
    │ 内建工具  │ │  MCP    │ │ CLAUDE.md│
    │ Read/Edit│ │  扩展    │ │  记忆    │
    │ Bash/Git │ │ AST-grep│ │  系统    │
    │ LSP/Glob │ │ Session │ │          │
    └──────────┘ └─────────┘ └──────────┘

26.3.3 “Sisyphus 提示“方法详解

整个编排逻辑的核心在于主智能体的系统提示词。一个典型的 Sisyphus 提示词包含以下模块:

身份与角色定义——明确智能体是一个“专注执行者“,不做无谓的确认和寒暄,直接开始工作。

任务分解纪律——收到复杂任务时,必须先用 todowrite 工具创建原子化的任务列表,每次只标记一个任务为 in_progress,完成后立即标记 completed

委派策略——明确在什么条件下应该派遣子智能体:需要深度代码分析时派遣 Explore 智能体、需要文档研究时派遣 Librarian 智能体、需要跨领域推理时派遣 Oracle 智能体。

反重复规则——一旦委派了探索任务给子智能体,主智能体禁止自己重复执行相同的搜索,避免浪费上下文预算。

验证协议——任务完成前必须运行 lsp_diagnostics 检查变更文件、确认构建通过、确认所有 todo 标记为完成。

终止纪律——首次验证成功后立即停止,最多检查 2 次状态,然后无论如何停止。

这种方法的本质是用自然语言编写一个有限状态机。它没有代码级的强制力(不像 Oh-My-OpenCode 的钩子可以在运行时拦截违规行为),但在实际使用中,高质量的 LLM 对提示词中的行为约束有很高的遵从度。

衍生解释:有限状态机(Finite State Machine, FSM)——计算机科学的基础概念,指一个系统在任意时刻处于有限个状态之一,根据输入事件在状态之间转换。这里的类比是:Sisyphus 提示词定义了智能体的状态(分析中、委派中、执行中、验证中、完成)以及触发状态转换的条件(任务复杂→委派、代码修改完→验证、验证通过→完成)。

26.3.4 智能体协作模型

与 Oh-My-OpenCode 的多智能体系统不同,Oh-My-Claude-Code 的智能体协作完全依赖 Claude Code 的原生 AgentTool。这意味着:

  • 同步委派:主智能体调用子智能体时会等待其完成,不能真正并行。背景智能体需要通过 Claude Code 的 Task 系统实现。
  • 无会话续接:子智能体每次被调用都是一个新会话,不保留之前的上下文。如果需要续接,必须在调用时显式传递之前的状态摘要。
  • 统一模型:所有智能体使用同一个模型(Claude),无法像 Oh-My-OpenCode 那样为不同智能体分配不同的模型。

这些限制并非致命。对于大多数编码任务,同步委派已经足够;会话续接可以通过在提示中传递状态摘要来近似实现;统一模型在 Claude 的能力范围内通常不是瓶颈。

26.3.5 小结

Oh-My-Claude-Code 的架构蓝图不是 Oh-My-OpenCode 的完美复制品,而是在 Claude Code 扩展约束下的最优解。它用提示词工程替代了钩子拦截,用文件约定替代了编程式 API,用 MCP 替代了原生工具注册。这种架构的上限取决于两个因素:LLM 对提示词中编排指令的遵从度,以及 MCP 生态的丰富程度。

下一节,我们将这个蓝图拆解为可执行的实施阶段。

26.4 实用实施计划:四阶段路线图

模型: claude-opus-4-6 (anthropic/claude-opus-4-6) 生成日期: 2026-04-01 书名: Claude Code VS OpenCode:架构、设计与未来 章节: 第26章 — 设计“Oh-My-Claude-Code“ Token 消耗: ~7,400 输入 + ~1,200 输出


架构蓝图回答了“应该造什么“,这一节回答“怎么造、先造哪部分“。我们把 Oh-My-Claude-Code 的实施拆解为四个阶段,每个阶段在前一个阶段的基础上累加能力,且每个阶段完成后都是一个可独立使用的成品。

阶段 1:自定义智能体族(1-2 周)

目标: 建立多智能体专业化分工体系。

具体工作:

.claude/agents/ 目录下创建 5 个专门化智能体的 Markdown 定义文件:

智能体文件职责OMO 对应物
Sisyphussisyphus.md主编排智能体,任务分解、委派、验证build(主智能体)
Oracleoracle.md深度推理与架构分析oracle
Exploreexplore.md代码库搜索与结构发现explore
Librarianlibrarian.md文档研究与知识检索librarian
Momusmomus.md代码审查与质量检查momus

每个智能体的 Markdown 文件包含:角色定义、行为约束、工具使用指南、输出格式要求。Sisyphus 的提示词最长也最复杂,因为它承载了整个编排逻辑。

关键实现细节:

Sisyphus 提示词中需要显式编码委派规则。例如:

## 委派策略
- 需要搜索代码库时 → 使用 AgentTool 调用 Explore 智能体
- 需要理解架构决策时 → 使用 AgentTool 调用 Oracle 智能体
- 需要查阅文档或 API 时 → 使用 AgentTool 调用 Librarian 智能体
- 代码修改完成后需要审查 → 使用 AgentTool 调用 Momus 智能体
- 一旦委派,禁止自己重复执行相同搜索(反重复规则)

阶段 1 成果: 用户可以通过 /agent sisyphus 激活一个具备任务分解和多智能体委派能力的编排智能体。

阶段 2:钩子强化 — Todo 纪律与安全防护(1 周)

目标: 利用 Claude Code 现有的钩子系统,实现自动化的行为约束。

具体工作:

.claude/settings.json 中配置钩子:

Stop 钩子 → Todo 完成验证: 当智能体停止时,检查是否存在未完成的 todo 项。如果有,输出提醒信息,建议用户继续会话。

{
  "hooks": {
    "Stop": [{
      "matcher": "",
      "command": "python3 .claude/scripts/check_todos.py"
    }]
  }
}

PreToolUse 钩子 → 文件守卫: 在工具执行前检查目标文件是否在受保护列表中(如 package-lock.json.env 等),阻止危险写入。

PostToolUse 钩子 → 审计日志: 记录所有工具调用到 .claude/logs/ 目录,便于事后分析智能体行为。

衍生解释:Poka-yoke(防错法)——源自丰田生产系统的质量管理概念,指通过设计使错误不可能发生或立即可见。在智能体系统中,文件守卫钩子就是一种 Poka-yoke 机制——它不依赖智能体“记得“不要修改某些文件,而是在架构层面阻止这种行为。

阶段 2 成果: 智能体行为受到自动化约束,即使提示词遵从度偶尔下降,钩子也能兜底。

阶段 3:MCP 工具增强(2-3 周)

目标: 通过 MCP 服务器为智能体生态注入 Claude Code 不具备的工具能力。

具体工作:

.claude/mcp.json 中配置以下 MCP 服务器:

MCP 服务器提供的工具用途
ast-grep-mcpAST 感知的代码搜索与替换Explore 智能体使用,精确的语义级代码分析
session-manager-mcp会话历史搜索与检索跨会话的知识延续
context7-mcp库文档实时查询Librarian 智能体使用,获取最新 API 文档
exa-mcp网络搜索与内容抓取技术趋势和最佳实践的实时检索
figma-mcpFigma 设计数据获取前端实现场景的设计规范读取

衍生解释:AST 感知搜索(AST-aware Search)——AST(Abstract Syntax Tree,抽象语法树)是编程语言源代码的树状结构表示。传统的文本搜索(grep)基于字符串匹配,而 AST 感知搜索理解代码的语法结构。例如,搜索“所有接受两个参数的函数“或“所有使用 useState 的 React 组件“——这些查询用正则表达式很难精确表达,但用 AST 模式匹配可以轻松完成。

关键设计决策: MCP 工具的注入不只是安装服务器——还需要在对应智能体的提示词中明确指导何时、如何使用这些工具。Explore 智能体的提示词需要说明什么时候用 ast_grep_search 替代普通的 grep,Librarian 智能体需要知道什么时候查 Context7 而不是直接用网络搜索。

阶段 3 成果: 智能体生态拥有了超出 Claude Code 内建范围的工具能力,覆盖 AST 分析、会话检索、实时文档、网络搜索等场景。

阶段 4:完整编排层(持续迭代)

目标: 将阶段 1-3 整合为一个系统化的编排框架,并加入持续改进机制。

具体工作:

CLAUDE.md 记忆体系: 建立结构化的项目记忆,包括:项目架构描述、编码规范、常见问题解决方案、智能体使用指南。这些记忆在每次会话开始时自动注入上下文。

智慧积累脚本: 通过 Stop 钩子,在每次会话结束时自动提取关键决策和学到的教训,追加到 CLAUDE.md 的指定区域。这是对 Oh-My-OpenCode 智慧积累系统的简化模拟。

插件化打包: 将整个 Oh-My-Claude-Code 打包为一个可分发的目录结构(.claude/agents/.claude/scripts/.claude/mcp.json 片段),使其可以通过简单的文件复制部署到任何项目中。

阶段 4 成果: 一个自包含、可分发、持续学习的多智能体编排系统。

总体评估

维度Oh-My-OpenCodeOh-My-Claude-Code
编排深度深度(钩子级拦截)中度(提示词编排)
工具扩展原生 + MCP仅 MCP
智能体数量11 个5 个(起步)
模型灵活性多模型路由单一模型
部署复杂度npm 安装 + 配置文件复制
对宿主的依赖OpenCode 插件 APIClaude Code 文件约定

Oh-My-Claude-Code 不会达到 Oh-My-OpenCode 的编排深度,但在 Claude Code 的生态内,它已经是可实现的最大化方案。

26.5 缺失的部分:致 Claude Code 扩展性的公开信

模型: claude-opus-4-6 (anthropic/claude-opus-4-6) 生成日期: 2026-04-01 书名: Claude Code VS OpenCode:架构、设计与未来 章节: 第26章 — 设计“Oh-My-Claude-Code“ Token 消耗: ~7,600 输入 + ~1,200 输出


前几节展示了在 Claude Code 当前扩展面约束下能做到什么。这一节要直说的是:还差什么。这不是批评——Claude Code 的扩展 API 设计有其清晰的安全理由——而是一份功能请求清单,说明如果这些能力存在,开发者能用 Claude Code 构建什么级别的系统。

26.5.1 chat.message 钩子:消息到达 LLM 之前的拦截

缺失描述: 目前无法在用户消息被发送给模型之前进行处理。

这意味着什么: Oh-My-OpenCode 用 chat.message 钩子实现的一系列关键功能,在 Claude Code 上无法做到:

  • 首消息变体门控——根据用户第一条消息的内容,动态选择智能体应该以什么“模式“运行。比如,检测到 fix: 前缀时激活快速修复模式,检测到 refactor: 前缀时激活深度分析模式。
  • 关键词路由——识别消息中的 @oracle@explore 提及,自动委派给对应子智能体,无需用户手动切换。
  • 会话状态初始化——在第一条消息时设置会话级状态(如 boulder state),供后续钩子使用。

绕行方案的代价: 这些逻辑只能写进系统提示词,但提示词无法“解析“用户消息的结构——它只能“建议“模型按某种方式响应,而钩子可以“强制“。

26.5.2 tool.execute.before/after 的变换能力

缺失描述: PreToolUsePostToolUse 钩子可以观察工具调用,可以阻止执行,但不能修改工具的输入参数或输出结果。

这意味着什么:

  • 标签截断器——Oh-My-OpenCode 在 tool.execute.after 中自动截断过长的工具输出,防止单次工具调用耗尽上下文窗口。Claude Code 的 PostToolUse 无法修改工具返回给模型的内容。
  • 规则注入器——根据被操作文件的类型(.tsx.py.go),自动在工具调用前注入对应的编码规范。Claude Code 的 PreToolUse 不能修改工具参数来附加额外上下文。
  • 结果增强——在工具返回结果后附加额外信息,比如在文件读取结果后追加该文件的 Git 历史摘要。

衍生解释:工具输出截断(Tool Output Truncation)——LLM 的上下文窗口是有限的(即使是 200K token 的模型也会被大量工具输出填满)。当一个 grep 操作返回了 5 万行结果时,将其全部塞入上下文是灾难性的。工具输出截断是一种防御机制:在结果返回给模型之前,自动将过长的内容压缩到安全范围内,通常附带一条提示如“结果已截断,显示了 100/50000 行,请使用更精确的查询“。

26.5.3 插件级工具注册

缺失描述: Claude Code 不提供编程式的工具注册 API。新增工具的唯一方式是通过 MCP 协议。

这意味着什么: MCP 是一个强大的标准,但它引入了额外的运行时开销——每个 MCP 服务器是一个独立进程,工具调用通过 JSON-RPC 跨进程通信。OpenCode 的插件可以直接通过 tool 钩子注册原生工具,这些工具与内建工具在同一进程中运行,零序列化开销。

对于需要紧密集成到对话引擎的工具(如 Oh-My-OpenCode 的 todowritesession_readcall_omo_agent),MCP 的进程隔离模型增加了不必要的复杂性。一个轻量级的插件工具注册 API 可以弥合这个差距。

26.5.4 智能体级模型选择

缺失描述: Claude Code 的所有智能体(主智能体和子智能体)使用相同的模型。无法为不同智能体指定不同的模型。

这意味着什么: Oh-My-OpenCode 的一个核心优化是模型路由——为不同职责的智能体分配最合适的模型。Explore 智能体做代码搜索,不需要最强的推理模型,用 Claude Sonnet 即可;Oracle 智能体做架构分析,可以上 Claude Opus。这种分级策略既优化了成本(简单任务用便宜模型),又优化了响应速度(小模型更快)。

在 Claude Code 的商业模式下,这个限制可能是故意的——Anthropic 自然希望所有调用都使用 Claude 模型。但从纯技术角度,智能体级模型选择是多智能体系统的重要能力维度。

26.5.5 带会话续接的背景智能体

缺失描述: Claude Code 的子智能体(通过 AgentTool 或 Task 系统派遣)每次调用都是一个全新的上下文。无法让一个背景智能体在多次调用之间保留完整的对话历史。

这意味着什么: Oh-My-OpenCode 的背景智能体支持通过 session_id 续接——你可以让一个 Explore 智能体在第一次调用时分析项目结构,第二次调用时基于已有的理解做更深入的探索,第三次调用时综合前两次的发现给出结论。每次调用都建立在之前积累的完整上下文之上。

没有会话续接,每个子智能体调用都是“失忆“的。对于简单的单次任务(“在代码库中找到所有 TODO”)这不是问题;对于需要多轮交互的复杂分析(“理解这个微服务的数据流,然后找出性能瓶颈”),失忆意味着每次都要重新建立上下文,既浪费 token 又降低分析深度。

衍生解释:会话续接(Session Continuation)——指在多次交互之间保留完整对话历史的能力。这与“无状态“的 HTTP 请求模型相反。在 AI 智能体系统中,会话续接使得智能体能够在多轮交互中逐步积累理解,而不是每次都“从零开始“。这类似于人类专家在多次咨询中逐渐深入理解问题的过程。

26.5.6 呼吁:更丰富的 Plugin SDK

上述五项缺失指向一个共同的方向:Claude Code 需要一个更丰富的 Plugin SDK

不是要求开放全部内部 API——安全约束必须保留。而是在保持安全基线的前提下,提供以下层次的扩展能力:

  1. 消息感知层——允许插件在消息到达 LLM 前进行只读检查(不修改内容,但可以触发副作用如日志、路由决策)
  2. 工具变换层——允许插件修改工具的输入参数和输出结果(在安全审计下)
  3. 原生工具注册——允许插件注册与内建工具同级的工具(不经过 MCP 跨进程通信)
  4. 智能体配置层——允许在智能体定义中指定模型偏好、温度参数、最大 token 等
  5. 会话管理层——允许子智能体保持有状态的会话,在多次调用间积累上下文

这些能力的组合将使 Claude Code 的插件生态从“配置和命令的扩展“升级为“对话引擎的深度定制“——正是 OpenCode 的插件系统今天已经具备的能力层次。

26.6 融合预测:OpenCode 与 Claude Code 的插件 API 会统一吗?

模型: claude-opus-4-6 (anthropic/claude-opus-4-6) 生成日期: 2026-04-01 书名: Claude Code VS OpenCode:架构、设计与未来 章节: 第26章 — 设计“Oh-My-Claude-Code“ Token 消耗: ~7,800 输入 + ~1,200 输出


本章前五节分别分析了 Claude Code 的扩展面、与 OpenCode 的差距、可行的架构蓝图、实施路线、以及仍然缺失的能力。最后这一节退后一步,从更长的时间尺度问一个问题:这两套插件 API 会走向统一吗?

26.6.1 MCP 作为公约数

MCP(Model Context Protocol)已经是三个系统的共有扩展层。OpenCode、Oh-My-OpenCode 和 Claude Code 都支持通过 .mcp.json(或等价配置)接入外部工具服务器。这意味着在工具层面,一个 MCP 服务器可以同时服务所有三个系统——写一次,到处用。

但 MCP 覆盖的只是扩展性光谱的一端:工具注入。它不涉及消息拦截、上下文变换、智能体配置、会话管理这些更深层的编排能力。MCP 是“最小公约数“——所有系统都支持它,但它不足以表达高级编排逻辑。

衍生解释:最小公约数(Lowest Common Denominator)——借用数学概念,在技术生态中指所有平台都支持的最基础能力子集。就像 HTML 是所有浏览器都支持的最小公约数一样,MCP 是所有 AI 智能体系统都支持的最小工具扩展标准。问题在于:仅靠最小公约数是否足以构建丰富的插件生态?

26.6.2 更丰富钩子系统的趋势

观察 2024-2026 年的发展轨迹,可以看到一个明确趋势:钩子系统在变得更丰富

Claude Code 在 2025 年初仅有 PreToolUsePostToolUse 两个钩子,到 2025 年末增加了 NotificationStopSubagentStop。OpenCode 的钩子从最初的 configtool 扩展到了 8 个,包括实验性的 chat.messages.transform。Oh-My-OpenCode 在这 8 个点上进一步细分出 41 个钩子。

这个趋势的驱动力是插件开发者的实际需求。每当有人尝试在智能体上构建高级编排功能而碰壁时,他们会要求更多的钩子点。OpenCode 的 experimental.chat.messages.transform 就是这样诞生的——Oh-My-OpenCode 的开发者需要在消息发送给 LLM 之前注入上下文,OpenCode 团队于是开放了这个实验性接口。

预测:Claude Code 在未来 12-18 个月内将至少新增 2-3 个钩子点,方向可能是:

  • 消息感知钩子——允许在消息到达 LLM 前进行只读检查
  • 上下文注入钩子——允许在系统提示词组装阶段注入额外内容
  • 智能体生命周期钩子——智能体创建/切换时的通知

26.6.3 开源创新驱动商业采纳

AI 智能体领域正在重演一个在软件史上反复出现的模式:开源项目先行试验激进的架构创新,商业产品在验证可行后跟进采纳

OpenCode 和 Oh-My-OpenCode 可以大胆尝试 chat.messages.transform 这样的深度钩子,因为它们面向的是技术敏感型用户,愿意承担潜在的安全风险以换取灵活性。Claude Code 作为商业产品,需要先观察这些创新在实际使用中的安全记录和价值验证,然后以更保守、更安全的方式引入类似能力。

衍生解释:创新扩散模型(Innovation Diffusion Model)——Everett Rogers 在 1962 年提出的理论,描述新技术如何在社会中传播:从创新者(Innovators,2.5%)到早期采用者(Early Adopters,13.5%)到早期大众(Early Majority,34%)再到后期大众和落后者。在 AI 智能体生态中,OpenCode 插件开发者是创新者,Oh-My-OpenCode 是早期采用者的验证平台,Claude Code 代表早期大众的需求——它们需要经过验证的、安全的、文档完善的扩展能力。

这种模式的实例已经可见:

  • Oh-My-OpenCode 首先实现了多智能体编排 → Claude Code 随后推出了自定义智能体和 AgentTool
  • OpenCode 插件系统证明了编程式工具注册的价值 → Claude Code 的插件目录开始支持工具定义
  • MCP 标准首先在开源社区获得广泛使用 → Anthropic 将其作为 Claude Code 的官方工具扩展机制

26.6.4 统一标准的可能性

两年内出现统一的智能体可扩展性标准是可能的——但不会是一个单一标准,而更可能是一个分层标准体系

层级 1:工具层(已统一)——MCP 已经是事实标准。任何智能体系统都可以通过 MCP 接入外部工具。这一层的统一已经完成。

层级 2:智能体定义层(正在趋同)——自定义智能体的 Markdown 定义格式、行为约束规范、工具访问权限声明,各系统的实现正在趋同。一个标准化的 Agent Manifest(智能体清单)格式有可能在 2027 年前出现。

层级 3:钩子/生命周期层(仍然分歧)——这是差距最大的层。OpenCode 的 8 个编程式钩子点和 Claude Code 的 5 个 shell 命令钩子在架构思路上有根本分歧。统一这一层需要解决安全性与灵活性的根本张力——这可能需要一种新的沙箱化钩子执行模型。

衍生解释:沙箱化钩子执行模型(Sandboxed Hook Execution Model)——一种假设的架构模式,允许插件代码拦截和变换消息流,但在严格的安全沙箱中执行。类似于浏览器扩展的内容脚本(Content Script)模型:扩展可以读取和修改网页内容,但受到严格的权限约束和隔离机制。这种模型可以在保持安全性的同时提供 OpenCode 级别的钩子灵活性。

层级 4:编排层(远期愿景)——多智能体调度、任务分解、智慧积累等高级编排能力的标准化可能需要更长时间。这一层涉及太多领域特定的设计选择,短期内不太可能出现统一标准。

26.6.5 对构建者的建议

如果你今天要在 Claude Code 上构建编排层:

  1. 把 MCP 作为工具扩展的首选机制——它是跨系统兼容的,今天写的 MCP 服务器明天可以用于任何系统。
  2. 把编排逻辑写进提示词而非代码——这种方法在任何系统上都可移植。
  3. 把智能体定义保持为简单的 Markdown 文件——格式趋同的趋势意味着今天的定义文件将来可以低成本迁移。
  4. 避免深度依赖任何系统的私有 API——私有 API 的变更风险远高于标准协议。
  5. 关注 Claude Code 的扩展 API 更新——每一次新增钩子点都是扩大能力范围的机会。

26.6.6 本章总结

“Oh-My-Claude-Code“不只是一个思想实验。它是对两个问题的实证回答:

第一,商业智能体产品的扩展面够用吗? 对于大多数定制场景,够用。对于深度编排,还不够——但差距在缩小。

第二,开源创新与商业产品之间的关系是什么? 是互相促进的共生关系。开源项目推动扩展能力的前沿,商业产品验证和标准化最有价值的创新。两者的交汇点——MCP、自定义智能体、结构化钩子——正在成为整个行业的公共基础设施。

智能体的未来不属于任何一个系统。它属于那些足够开放、足够灵活、同时足够安全的扩展标准。而这些标准正在我们分析的三个系统——OpenCode、Oh-My-OpenCode 和 Claude Code——的竞争与合作中诞生。

Model: openai/gpt-5.4 Token Usage(estimated): ~8,100 tokens Generated: 2026-04-01 Book: Claude Code VS OpenCode: Architecture, Design & The Road Ahead

附录A:OpenCode、OMO 与 Claude Code 工具清单

本附录将三套系统的主要工具面统一放进一张对照表中。OpenCode 提供开源基线;Oh-My-OpenCode(OMO)继承这套基线并重点增强多智能体编排、后台任务、Session 检索、Skill-MCP 与 AST 级代码操作;Claude Code 则在商业产品层面扩展出更完整的任务、团队、工作流、浏览器、MCP 认证与 UI 联动能力。

表中的 “Yes” 表示一等公民能力;“Conditional” 表示依赖功能开关、运行模式或环境;“Inherited” 表示 OMO 通过 OpenCode 继承该能力后再增强。

Tool NameOpenCodeOMOClaude CodeDescription
bashYesInheritedYes在工作区内执行 shell 命令。
powershellNoNoConditionalWindows 原生命令执行。
read / file readYesInheritedYes安全读取文件或目录。
write / file writeYesInheritedYes直接创建或覆盖文件。
edit / file editYesInherited 或被覆盖Yes对已有文件做结构化修改。
multieditYesInherited无单独公开工具一次提交多个同文件编辑。
apply_patchYesInherited无单独公开工具统一 diff/patch 风格修改。
notebook editNoNoYes面向 Notebook 的单元级编辑。
ls / list directoryYesInherited被 read/glob 吸收轻量目录列举。
external-directoryYesInherited无直接对应扩展默认项目根之外的访问范围。
globYesEnhancedYes基于路径模式查找文件。
grepYesEnhancedYes基于正则或文本查找内容。
codesearchYesInheritedToolSearch 部分类似偏代码语义的搜索。
ast-grep searchNoYes无一等公民工具基于 AST 的结构化代码搜索。
ast-grep replaceNoYes无一等公民工具基于 AST 的结构化代码替换。
lspConditional被拆成多个工具Conditional语言服务器查询与重构。
lsp_goto_definitionNoYes被 LSPTool 吸收跳转符号定义。
lsp_find_referencesNoYes被 LSPTool 吸收查找符号全部引用。
lsp_symbolsNoYes被 LSPTool 吸收文档或工作区符号查询。
lsp_diagnosticsNoYes被 LSPTool 吸收收集错误、警告、提示。
lsp_prepare_renameNoYes被 LSPTool 吸收检查 rename 是否可执行。
lsp_renameNoYes被 LSPTool 吸收跨工作区重命名符号。
webfetchYesInheritedYes抓取网页并提炼内容。
websearchYesInherited + provider 可配Yes执行网页搜索并返回结果。
web browserNoNoConditional交互式浏览器导航与提取。
look_atNoYes部分由 file/browser 工具替代快速查看图片、PDF、媒体文件。
question / ask userConditionalInheritedYes向用户发起补充提问或确认。
skillYesUpgradedYes加载 Skill 或命令包。
skill_mcpNoYes无直接对应调用 Skill 内嵌的 MCP 资源/工具。
slashcommandNoYes原生命令系统但表面不同以工具形态执行 slash command。
taskYes被 delegate-task 语义替代无完全等价物生成一个子任务/子 Agent。
call_omo_agentNoYesAgentTool 类似调用 OMO 专业化子智能体。
background_outputNoYes与 TaskOutputTool 类似读取后台任务输出。
background_cancelNoYes与 TaskStopTool 类似取消一个或多个后台任务。
task_createNoOMO 条件开启Yes创建结构化后台任务。
task_getNoOMO 条件开启Yes获取单个任务状态与元数据。
task_listNoOMO 条件开启Yes列出任务。
task_updateNoOMO 条件开启Yes更新任务信息。
task_outputNo由 background_output 对应Yes获取任务输出或记录。
task_stopNo由 background_cancel 对应Yes停止运行中的任务。
todo writeYesInheritedYes维护结构化 todo 列表。
todo read内部/有限Inherited更偏 UI/Task List读取已保存的 todo 状态。
plan enterConditionalInheritedYes进入计划模式。
plan exitConditionalInheritedYes退出计划模式并恢复执行。
verify plan executionNoNoConditional校验执行是否符合计划。
agent tool无独立公开工具call_omo_agentYes启动另一个 agent/teammate。
team createNoNoConditional创建多智能体团队/Swarm。
team deleteNoNoConditional删除团队/Swarm。
send messageNoNoConditional向其他 peer/agent 发送消息。
list peersNoNoConditional列出可通信 peer。
workflowNoNoConditional触发复用型 workflow 脚本。
config toolNoNoConditional在运行中读取/修改配置。
MCP tool invocation通过 MCP 注册通过 MCP + Skill MCPYes调用 MCP server 暴露的工具。
list MCP resourcesNoNoYes列出 MCP 资源。
read MCP resourceNoNoYes读取指定 MCP 资源 URI。
MCP authNoNoYes处理 MCP 认证与连接批准。
REPLNoNoConditional进程内交互式编程壳。
interactive_bash / terminal captureNoYesConditional持久终端、tmux 或终端快照。
snip / briefNoNoYes裁剪上下文、压缩历史。
sleep / cron / monitorNoNoConditional时间驱动自动化与监控。
push notificationNoNoConditional主动通知用户。
subscribe PRNoNoConditional订阅 PR 更新。
tungsten / review artifactNoNoConditional专用内部工具或工件审查流。

分类说明

1. 文件操作层

OpenCode 的文件操作层最干净:readwriteeditmultieditapply_patch。它几乎就是一个最小可用的 Agent-Computer Interface。OMO 继承这套能力,但在实验模式下可以用 hashline editor 替换默认 edit。Claude Code 的文件工具则更产品化,不仅有读写编辑,还集成了 notebook 编辑、差异展示、拒绝消息反馈等 UI 配套。

2. 搜索层

三者都承认搜索是编码智能体的核心能力。OpenCode 提供 globgrepcodesearchwebfetchwebsearch。OMO 在此基础上增加 AST 搜索/替换、Session 检索和拆分式 LSP 工具。Claude Code 则提供 GlobToolGrepToolWebFetchToolWebSearchTool、MCP 资源浏览,以及部分版本中的浏览器工具。趋势很明确:仅靠 grep 已经不够,智能体需要文件级、语法级、网络级三层检索。

3. 编排层

OpenCode 的 taskskill 说明了开源基线的组合能力。OMO 把“组合”升级成“编排”:call_omo_agent、后台任务、slashcommand、skill_mcp、tmux 可视化、多 Session 管理。Claude Code 则把同类需求产品化为 Task 系列工具、Team 工具、Workflow 工具和 agent 间消息能力。换句话说,OMO 加的是多智能体深度,Claude Code 加的是平台级广度。

4. 交互与长任务

OpenCode 整体仍偏 request/response。OMO 明确拥抱长时任务与可视化运行:interactive_bashbackground_outputbackground_cancel、session manager 都是为了让 Agent 处理持续性工作。Claude Code 通过 Task、REPL、TerminalCapture、Cron、通知系统达到类似效果。这说明“真正的软件工程”往往不是一次性回答,而是可监控、可恢复、可中断的过程。

5. LSP 与结构化代码理解

OpenCode 提供实验性的单体 LSP 工具。OMO 将其拆成更原子化的 goto_definitionfind_referencesrenamediagnostics 等工具,更适合让模型按需组合。Claude Code 也有强 LSP 支持,但通过统一的 LSPTool 和大型 service 层来承载。这里体现的是一个经典工程权衡:面向产品时大工具更利于体验,面向 Agent 稳定性时小工具往往更利于组合和纠错。

6. 特征性工具

OMO 的标志性工具是那些把“编排本身”暴露为一等能力的工具:多 Agent 调用、后台输出读取、Skill-MCP 路由、tmux 控制、Session 检索、AST 搜索。Claude Code 的标志性工具则是商业运行时的外显:Teams、Workflow、Browser、MCP Auth、Push、订阅、复杂任务管理。OpenCode 则仍然是最适合作为“本体”来理解什么是编码智能体最小核心的系统。

Model: openai/gpt-5.4 Token Usage(estimated): ~4,600 tokens Generated: 2026-04-01 Book: Claude Code VS OpenCode: Architecture, Design & The Road Ahead

附录B:配置参考

本附录不追求把全部 schema 字段逐字抄录,而是提炼三套系统中最影响运行行为、模型选择、工具暴露、编排方式与安全策略的关键配置项。

OpenCode

OpenCode 的配置系统很值得单独学习,因为它体现了典型的分层配置思想:远程 well-known 配置、全局配置、自定义配置、项目配置、.opencode/ 目录配置、内联配置、企业托管配置依次覆盖。这在传统 CS 里可以类比“多层优先级的系统配置合并”。

SettingDefaultMeaning
modelnone主模型,格式为 provider/model
small_modelnone更便宜的小模型,用于轻量工作。
default_agentnone默认 agent/mode。
username当前系统用户名用于 Prompt/UI 的用户名注入。
plugin[]插件列表,后加载者覆盖前者。
instructionsnone额外指令文件或 glob。
permissionnone工具权限规则,如 allow/ask/deny。
providernoneProvider 鉴权、端点和模型重写。
mcpnoneMCP Server 配置与启停状态。
formatternone格式化器命令、环境变量与扩展名映射。
lspnoneLSP server 配置;可关闭或按 server 定义。
compaction.autotrue上下文逼近上限时自动 compact。
compaction.prunetruecompact 时裁剪旧工具输出。
compaction.reservednone为 compact 保留的 token 缓冲区。
sharenone / 由 autoshare 迁移Session 分享策略。
experimental.batch_tool默认关闭是否暴露 batch tool。
experimental.primary_toolsnone仅主 Agent 可见的工具列表。
experimental.continue_loop_on_denyfalse工具被拒绝后是否继续循环。
experimental.mcp_timeoutnoneMCP 请求超时,单位毫秒。

Oh-My-OpenCode

OMO 的配置不是替代 OpenCode,而是叠加在 OpenCode 之上的第二层控制平面。它最重要的价值在于:无需 fork 宿主,也能禁用、替换、增强、分发 Agent/Skill/Hook/Task 行为。

SettingDefaultMeaning
new_task_system_enabledfalse是否启用新的任务系统。
default_run_agentnoneoh-my-opencode run 的默认 Agent。
disabled_mcpsnone禁用指定 MCP。
disabled_agentsnone禁用指定内置 Agent。
disabled_skillsnone禁用指定 Skill。
disabled_hooksnone禁用指定 Hook。
disabled_commandsnone禁用指定命令。
disabled_toolsnone从模型可见列表中隐藏工具。
agentsnoneAgent 级别重写,如模型、权限、提示词。
categoriesnone任务分类、委派分类配置。
claude_codenoneClaude Code 兼容层配置。
experimental.task_systemfalse暴露 task_create/get/list/update
experimental.hashline_editfalse启用 hashline edit 替代普通编辑。
auto_updateoptional插件自更新策略。
skillsnoneSkill 来源、定义、开关。
ralph_loop.enabledfalse开启 Ralph Loop。
ralph_loop.default_max_iterations100默认循环迭代上限。
background_task.staleTimeoutMs180000后台任务静默超时。
background_task.messageStalenessTimeoutMs600000从未上报进展的任务超时。
notification.force_enablefalse即便已有外部通知器也强制启用通知 Hook。
git_master.commit_footertrue提交信息尾注开关。
git_master.include_co_authored_bytrue是否附带 co-authored-by。
browser_automation_engine.providerplaywright浏览器自动化后端。
websearch.provider默认 Exa 风格选择 Exa 或 Tavily。
tmux.enabledfalse启用 tmux 可视化多 Agent。
tmux.layoutmain-vertical主窗格在左,Agent 窗格在右。
sisyphus.claude_code_compatfalse启用 Claude Code 兼容行为。
babysitting.timeout_ms120000babysitting 默认超时。

Claude Code

Claude Code 的配置面最宽。它不仅控制模型与工具,还覆盖通知、IDE、任务、MCP、工作树、浏览器、UI、托管策略等。也正因此,它越来越像一个“运行时产品平台”的配置系统,而不仅是一个 CLI 的偏好设置文件。

SettingDefaultMeaning
themedark界面主题。
preferredNotifChannelauto通知渠道自动选择。
verbosefalse是否输出更详细的运行信息。
editorModenormal输入/编辑器键位模式。
autoCompactEnabledtrue是否自动压缩上下文。
showTurnDurationtrue是否显示单轮耗时。
diffToolautodiff 呈现方式。
todoFeatureEnabledtrue是否启用 todo/task 体验。
showExpandedTodosfalse默认展开 todo。
messageIdleNotifThresholdMs60000空闲通知阈值。
autoConnectIdefalse启动时自动连接 IDE。
autoInstallIdeExtensiontrue自动安装 IDE 扩展。
fileCheckpointingEnabledtrue启用文件 checkpoint。
terminalProgressBarEnabledtrue显示终端进度条。
respectGitignoretrue在相关操作中尊重 .gitignore
copyFullResponsefalse复制完整回答而非简化版本。
projects[*].allowedTools[]项目级允许工具列表。
projects[*].mcpServers{}项目级 MCP server 配置。
projects[*].hasTrustDialogAcceptedfalse项目信任状态。
projects[*].activeWorktreeSessionnone活跃 worktree session 元数据。

一个设计层面的观察

OpenCode 的配置体现“系统清晰性”;OMO 的配置体现“编排表达力”;Claude Code 的配置体现“产品控制面完整性”。

当一个编码智能体平台不断叠加任务系统、通知系统、MCP 认证、IDE 连接、插件生态与企业托管策略后,配置就不再只是 preference,而是运营控制面。这个变化很重要,因为它意味着 Agent 工程最终会越来越接近操作系统、IDE 和 DevOps 平台的交叉体。

Model: openai/gpt-5.4 Token Usage(estimated): ~3,900 tokens Generated: 2026-04-01 Book: Claude Code VS OpenCode: Architecture, Design & The Road Ahead

附录C:源码路径对照表

下面这张表把同一个架构概念映射到三个代码库中的主要实现入口。这里的路径不是“穷举所有依赖”,而是“给读者最快建立源码心智地图的第一跳”。

ConceptOpenCodeOMOClaude Code
Entry pointpackages/opencode/src/index.tssrc/index.tssrc/main.tsx, src/entrypoints/cli.tsx
Core looppackages/opencode/src/session/processor.ts, session/llm.ts宿主循环沿用 OpenCode;插件拦截在 src/plugin/chat-message.ts, src/plugin/messages-transform.tssrc/QueryEngine.ts, src/query.ts
Tool registrypackages/opencode/src/tool/registry.tssrc/plugin/tool-registry.ts, src/create-tools.tssrc/tools.ts, src/Tool.ts
Tool implementationspackages/opencode/src/tool/*src/tools/*src/tools/*
Agentspackages/opencode/src/agent/*src/agents/*,重点看 builtin-agents.ts, dynamic-agent-prompt-builder.tssrc/tools/AgentTool/*, src/coordinator/*, src/buddy/*
Sessionspackages/opencode/src/session/*src/features/claude-code-session-state/*, src/features/background-agent/*, src/features/boulder-state/*src/utils/sessionStorage.ts, src/utils/sessionState.ts, src/tasks/*
Providers / model layerpackages/opencode/src/provider/*主要继承 OpenCode;Agent 级模型选择在 src/agents/* 与 config schema 中src/utils/model/*, src/services/tokenEstimation.ts
MCPpackages/opencode/src/mcp/*src/mcp/*, src/features/skill-mcp-manager/*, src/features/claude-code-mcp-loader/*src/services/mcp/*
Permissionspackages/opencode/src/permission/*继承宿主权限模型,并在 src/config/schema/internal/permission.ts 做扩展src/utils/permissions/*, yoloClassifier.ts, bashClassifier.ts
Plugins / extension surfacepackages/opencode/src/plugin/*插件入口 src/index.ts;兼容加载器位于 src/features/claude-code-plugin-loader/*src/services/plugins/*, src/plugins/*
HooksOpenCode 的 hook 点由 packages/opencode/src/plugin/index.ts 接入具体管线在 src/plugin/tool-execute-before.ts, tool-execute-after.ts, messages-transform.ts, event.ts 以及 src/hooks/*UI/runtime hooks 在 src/hooks/*;hook schema 在 src/entrypoints/sdk/coreSchemas.ts
UI / TUIpackages/opencode/src/cli/*cli/cmd/tui/*大部分 UI 借宿主;tmux 多 Agent 可视化位于 src/features/tmux-subagent/*src/components/*, src/ink/*, src/screens/*
Configpackages/opencode/src/config/config.ts, paths.ts, tui-schema.tssrc/plugin-config.ts, src/config/schema/*src/utils/config.ts, src/utils/settings/*, src/services/settingsSync/*
Commandspackages/opencode/src/command/*src/features/builtin-commands/*, src/tools/slashcommand/*src/commands/*, src/commands.ts
Skillspackages/opencode/src/skill/*src/features/builtin-skills/*, src/features/opencode-skill-loader/*, src/tools/skill/*src/skills/*, src/tools/SkillTool/*

建议阅读顺序

如果你的目标不是立刻提交代码,而是先理解架构,我建议按下面顺序读:

  1. OpenCodesession/processor.tstool/registry.tsconfig/config.ts
  2. OMOsrc/index.tssrc/plugin/tool-registry.tssrc/agents/builtin-agents.tssrc/config/schema/oh-my-opencode-config.ts
  3. Claude Codesrc/tools.tssrc/QueryEngine.tssrc/utils/config.tssrc/services/mcp/*

这个顺序本质上是在沿着控制流往外走:先看执行引擎,再看能力表,再看策略与配置。即便某些术语如“context compaction”“agent orchestration”不直接出现在传统 CS 教科书中,这种分层方式仍然完全符合经典系统设计逻辑:执行层、接口层、控制层。

Model: openai/gpt-5.4 Token Usage(estimated): ~3,300 tokens Generated: 2026-04-01 Book: Claude Code VS OpenCode: Architecture, Design & The Road Ahead

附录D:MCP 生态概览

Model Context Protocol(MCP)已经成为当代 Agent 系统最重要的可扩展性底座之一。它统一了模型如何发现外部工具、资源、Prompt 与认证流程,从而把“接一个新系统”的成本从大量胶水代码降低为协议接入。

传输类型

Transport工作方式优点常见场景
stdioAgent 启动本地进程,通过 stdin/stdout 通信简单、本地、安全边界清晰本地数据库、文件系统、开发辅助工具
SSE通过 HTTP 的 Server-Sent Events 做长连接流式输出易于流式事件传输托管型 MCP 服务、状态推送
HTTP常规请求/响应式 HTTP 通信运维熟悉、易过代理SaaS 化 MCP 接口、网关服务
WebSocket双向持久连接低延迟、双向实时交互浏览器控制、协同会话、远程代理

这里要特别说明一个容易混淆的点:MCP 是“协议层”,而 stdio/SSE/HTTP/WebSocket 是“承载层”。在经典网络课程里,这可以理解为“应用协议”和“传输通道”的区分。

常见社区 Server

Server 家族暴露能力为什么重要
Postgres / SQL查询、Schema 检查、迁移、行级读取让 Agent 直接连接真实业务数据而不是只猜。
GitHubPR、Issue、Checks、评论、仓库元数据对编码智能体来说几乎是最关键的外部协作接口之一。
Slack频道、消息、通知、检索把工程动作与团队沟通闭环连接起来。
Browser / Playwright导航、DOM 检查、截图、表单交互让 Agent 具备 UI 测试与网页操作能力。
Filesystem / Shell wrappers受控文件访问和命令执行仍然是很多私有自动化接入的第一入口。
Cloud APIs存储、部署、观测、工单使 Agent 从“写代码助手”走向“工程流程参与者”。

官方 Registry

MCP 生态正在围绕官方 Registry 逐步形成统一分发与发现机制:

  • Registry UI:https://registry.modelcontextprotocol.io/
  • Registry 文档:https://modelcontextprotocol.io/registry
  • Registry API 文档:https://registry.modelcontextprotocol.io/docs

Registry 在 MCP 世界里的角色,很像软件包生态中的 package index。它的价值并不只是“能下载”,更重要的是提供 discoverability、版本身份、元数据以及未来的信任信号。

与三套系统的关系

  • OpenCode:把 MCP 作为一等扩展层纳入 config 与 runtime。
  • OMO:进一步把 MCP 与 Skill 系统、Agent 编排、Claude Code 兼容层耦合起来。
  • Claude Code:在 MCP 认证、连接审批、scope 管理、registry 集成和项目/用户隔离上投入最深。

一个更宏观的判断

如果把 Agent 系统比作操作系统,那么 MCP 正在逐步扮演“设备驱动层”的角色。这个比喻并不完全严格,但很有解释力:模型不需要原生理解每个外部系统,只要运行时能把这些外部能力通过统一协议暴露出来,Agent 就能在一个更稳定、更可移植的接口上工作。这也正是 MCP 在 2025–2026 年迅速扩散的根本原因。

Model: openai/gpt-5.4 Token Usage(estimated): ~2,900 tokens Generated: 2026-04-01 Book: Claude Code VS OpenCode: Architecture, Design & The Road Ahead

附录E:参考文献

以下文献与文章构成了本书的重要参考背景,包括官方工程博客、协议文档、行业分析和学术论文。由于编码智能体的发展速度远快于传统教材更新速度,本书有意把高质量工程文章也视为一手资料。

  1. Anthropic. “Building Effective AI Agents.” 2024-12-19。
    URL: https://www.anthropic.com/research/building-effective-agents

  2. Anthropic. “Effective context engineering for AI agents.” 2025-09-29。
    URL: https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents

  3. Anthropic. “Beyond permission prompts: making Claude Code more secure and autonomous.” 2025-10-20。
    URL: https://www.anthropic.com/engineering/claude-code-sandboxing

  4. Anthropic. “How we built our multi-agent research system.” 2025-06-13。
    URL: https://www.anthropic.com/engineering/built-multi-agent-research-system

  5. Anthropic. “Writing effective tools for agents — with agents.” 2025-09-11。
    URL: https://www.anthropic.com/engineering/writing-tools-for-agents

  6. Model Context Protocol. Official Documentation.
    URL: https://modelcontextprotocol.io/introduction

  7. Model Context Protocol. Official Registry.
    URL: https://registry.modelcontextprotocol.io/

  8. Zylos Research. “AI Coding Agents 2025-2026: State of the Art.” 2026-01-09。
    URL: https://zylos.ai/research/2026-01-09-ai-coding-agents

  9. Zylos Research. “AI Agent Plugin and Extension Architecture.” 2026-02-21。
    URL: https://zylos.ai/research/2026-02-21-ai-agent-plugin-extension-architecture

  10. GuruSup. “Agent Orchestration Patterns: Swarm vs Mesh vs Hierarchical.” 2026-03-14。
    URL: https://gurusup.com/en/blog/agent-orchestration-patterns

  11. GuruSup. “Agent Communication Protocols: MCP vs A2A and Why They Matter.” 2026-03-16。
    URL: https://gurusup.com/blog/agent-communication-protocols-mcp-a2a

  12. Kang, Minki et al. “Acon: Optimizing Context Compression for Long-horizon LLM Agents.” arXiv。
    URL: https://arxiv.org/abs/2510.00615

  13. Morph Team. “We Tested 15 AI Coding Agents (2026). Only 3 Changed How We Ship.” 2026-03-01。
    URL: https://morphllm.com/ai-coding-agent

  14. Yao, Shunyu et al. “ReAct: Synergizing Reasoning and Acting in Language Models.” 2022。
    URL: https://arxiv.org/abs/2210.03629

  15. Jimenez, Carlos E. et al. “SWE-bench: Can Language Models Resolve Real-World GitHub Issues?” 2023。
    URL: https://arxiv.org/abs/2310.06770

关于资料类型的一点说明

上面的资料里,既有 arXiv 论文,也有厂商工程博客和行业研究文章。对于今天的 Agent 工程来说,这种混合引用是必要的。因为很多关键术语、实现策略和架构模式,在经典 CS 教科书里还没有稳定命名,但在一线系统中已经成为真实存在的工程问题,例如 context engineering、tool quality、agent orchestration、sandbox autonomy 等。因此,本书把这些高质量工程文章视为“时代文献”,而不仅仅是宣传材料。

Model: openai/gpt-5.4 Token Usage(estimated): ~6,100 tokens Generated: 2026-04-01 Book: Claude Code VS OpenCode: Architecture, Design & The Road Ahead

附录F:术语表

说明:按要求,本术语表采用“英文术语 + 中文解释”的形式。对于一些在传统计算机教材中尚未标准化的概念,我会补充衍生解释,避免只给出圈内黑话式定义。

Term中文解释
LLMLarge Language Model,大语言模型。它是当前 Agent 系统中的推理核心,负责理解目标、生成计划、选择工具与整合观察结果。
TokenToken 是模型处理文本的基本单位,不等同于“一个单词”。计费、上下文上限、压缩策略几乎都围绕 token 展开。
Context Window上下文窗口。指模型在单次推理中能看到的最大 token 数量,可类比一种受限的工作记忆容量。
Function Calling函数调用。模型不直接输出自然语言,而是按结构化 schema 输出“要调用哪个工具、带什么参数”。
ReActReason + Act,一种“思考—行动—观察—再思考”的智能体循环范式。
Agent智能体。它不是单独一个模型,而是模型、工具、上下文、控制循环、策略约束组合成的运行体。
MCPModel Context Protocol,模型上下文协议。用于统一描述外部工具、资源、Prompt 与认证交互。
ACPAgent Client Protocol。OpenCode 体系中的 Agent 客户端协议,用于不同界面/客户端与运行时协作。
A2AAgent-to-Agent,智能体到智能体的通信或协作协议范畴。它强调的是“智能体之间互相协调”,而不仅是“模型调用工具”。
LSPLanguage Server Protocol,语言服务器协议。编辑器中的定义跳转、引用查找、重命名、诊断等能力通常都建立在它之上。
ASTAbstract Syntax Tree,抽象语法树。它把代码解析成语法结构树,因此可以做结构化搜索和修改,而不是粗暴文本替换。
SSEServer-Sent Events,服务端推送事件。它是一种基于 HTTP 的单向流式传输方式。
Monorepo单仓库多包结构。多个包、模块或应用放在同一个版本控制根目录下统一管理。
TUIText User Interface,文本用户界面。它比普通 CLI 更丰富,但仍运行在终端中。
Poka-yoke日语词,原意是“防呆”“防错”。放在 Agent 工程里,指通过接口设计、参数限制、默认值和流程约束减少智能体犯错。
ACIAgent-Computer Interface,智能体—计算机接口。可类比 HCI(人机交互),但它优化的对象不是人,而是模型。
JSONLJSON Lines,一行一个 JSON 对象的数据格式,特别适合日志、事件流和可追加存储。
Zod一个 TypeScript 常用的 schema 验证库,常被用于工具参数校验与配置文件 schema 定义。
JSON-RPC一种基于 JSON 的远程过程调用协议,常见于 MCP 及相关生态。
Extended Thinking扩展思考。通常不是指真正公开模型“内心想法”,而是指运行时给模型更多推理预算或更审慎的执行模式。
Scaffolding脚手架。指模型之外包裹的一整套运行时结构,例如 Prompt 组装、工具调用、记忆、重试、压缩、权限与编排。
Context Rot上下文腐化。不是经典教科书术语,但它描述了一个真实现象:上下文太长、太旧、太杂后,模型注意力被稀释,表现开始退化。
Compaction压缩整理上下文。目的是在保留任务关键信息的同时减少 token 占用。
Hook生命周期钩子。系统在某个事件前后留出的拦截点,外部代码可以借此注入逻辑。
Plugin插件。无需修改宿主核心源码即可加载的扩展模块。
Skill技能包。通常是一组专门任务说明、工作流模板、脚本和工具组合。
YOLO ClassifierClaude Code 语境里的一个非正式名字,表示用分类器判断某个动作能否在更自主模式下自动放行。这里的 YOLO 不是教材术语,而是产品内命名。
bubblewrap / Seatbelt两种沙箱机制。bubblewrap 常见于 Linux;Seatbelt 是 macOS 侧的沙箱机制。
Ink一个基于 React 的终端 UI 框架,用来构建复杂 TUI。Claude Code 的界面层与它关系很深。
Drizzle ORM一个 TypeScript 生态中的 ORM/SQL 工具,强调类型安全和较轻量的数据库访问模式。
Vercel AI SDK一个用于模型抽象、流式输出和多 Provider 兼容的 TypeScript SDK。
Hono一个轻量级 Web 框架,常用于 Bun、Cloudflare 等运行时。
Solid.js一个强调细粒度响应式的前端框架。
Tauri一个桌面应用框架,通常以 Rust 做壳层、Web 技术做界面层。

补充解释:为什么这些术语需要“衍生说明”

Context Rot

“Context Rot” 还不是像 cache coherence、deadlock 这样被传统教材正式收录的标准术语,但它描述的问题非常典型:上下文越堆越多,噪声越多,旧观察越多,真正有价值的信息比例就越低,模型的有效注意力就会被污染。它有点像“内存被脏数据挤占”或“检索精度下降”的混合问题。

Scaffolding

很多人把 Agent 的能力归因于底层模型本身,但 2025–2026 年的工程实践不断证明,真正拉开差距的往往是 scaffolding。用系统设计语言说,模型像 CPU,scaffolding 更像操作系统、调度器、驱动、I/O 接口和安全策略的组合。

Poka-yoke

这是制造业概念,被借到 Agent 领域后非常有用。因为智能体最怕的不是“不会做”,而是“差一点做对,但代价极大”。例如路径校验、参数 schema、危险操作二次确认、只读默认值,本质上都是 Agent 世界里的 poka-yoke。

ACI

HCI 研究如何让人更好地使用计算机;ACI 研究如何让模型更可靠地使用计算机。好的 ACI 往往具备几个特征:参数明确、输出边界清晰、失败可恢复、结果可组合。很多“给人看很友好”的工具,并不一定适合给模型用。

Extended Thinking

这个词经常被误解。它通常不意味着系统真的把模型完整内部思维公开给用户看,而更多意味着:允许更长的 deliberation、更高的 reasoning budget、更慢但更稳的推理路径,或额外的链路控制。