Hermes 与 Claude CodeHermes 与 Claude Code第 1 章 · 14 章Chapter 1 of 14
全文目录Contents
  1. 这个网页怎么用
  2. 1 · 零基础前置知识
    1. 1.1 大语言模型是什么
    2. 1.2 token 是什么
    3. 1.3 上下文与上下文窗口是什么
    4. 1.4 智能体与聊天机器人的区别
    5. 1.5 工具调用是什么,它到底怎么工作
    6. 1.6 什么是流式输出
    7. 1.7 什么是 API
    8. 1.8 提示词缓存 —— 全文最重要的技术概念
    9. 1.9 还会遇到的几个词
  3. 2 · 两个系统的宏观定位与架构总图
    1. 2.1 用一句话说清各自的定位
    2. 2.2 架构总图
    3. 2.3 关键数字对照
    4. 2.4 第一个值得记住的洞察
  4. 3 · 垂直分层与水平分区
    1. 3.1 垂直分层:六层模型
    2. 3.2 水平分区:同一层内部怎么切
    3. 3.3 一个反直觉的观察:巨型文件
    4. 3.4 分层之外:穿透所有层的四类逻辑
  5. 4 · 智能体主循环与错误恢复状态机
    1. 4.1 教科书版本的循环,以及它会死在哪
    2. 4.2 Claude Code 的做法:写成显式状态机
    3. 4.3 错误扣留:可恢复的错误不能立刻往外发
    4. 4.4 中断的正确处理姿势
    5. 4.5 切换备用模型:一个想不到的坑
    6. 4.6 Hermes 的做法:预算驱动的循环
    7. 4.7 Hermes 独有的能力:轮次中途插话
    8. 4.8 两家对照与取舍
  6. 5 · 工具抽象层与工具执行编排
    1. 5.1 Claude Code 的工具接口:一个教科书级抽象
    2. 5.2 渐进式工具加载:工具搜索机制
    3. 5.3 工具清单的装配:一个只有深度用过缓存才知道的坑
    4. 5.4 执行编排:并发分区
    5. 5.5 流式工具执行器:边流边执行
    6. 5.6 Hermes 的工具层:中心分发 + 参数强制矫正
    7. 5.7 两家对照与取舍
  7. 6 · 上下文治理阶梯 ★ 全文核心
    1. 6.1 Claude Code 的做法:五级流水线
    2. 6.2 第 ① 级:工具结果预算与落盘
    3. 6.3 第 ③ 级:缓存编辑 —— 全文最精彩的一处
    4. 6.4 第 ⑤ 级:自动摘要压缩的工程细节
    5. 6.5 上下文真的超了之后:三级恢复瀑布
    6. 6.6 Hermes 的做法:把整条阶梯抽象成一个插座
    7. 6.7 两家横向对照
  8. 7 · 权限模型与安全边界
    1. 7.1 Claude Code 的做法:十级决策级联
    2. 7.2 自动模式:用模型判断安全性,加三级快速通道
    3. 7.3 Hermes 的做法:正则红线 + 对抗性解析
    4. 7.4 Hermes 的第二道防线:执行环境隔离
    5. 7.5 一个常被忽略的攻击面:错误消息回灌
    6. 7.6 两家对照与取舍
  9. 8 · 多智能体协作编排
    1. 8.1 子智能体到底解决什么问题
    2. 8.2 Claude Code 的三种子智能体形态
    3. 8.3 分叉子智能体:把提示词缓存用到极致
    4. 8.4 子智能体的工具限制
    5. 8.5 Hermes 的做法:任务委派 + 看板协作
    6. 8.6 一个两家共同的硬约束:中断的级联
  10. 9 · 记忆系统与扩展体系
    1. 9.1 记忆:两种截然不同的答案
    2. 9.2 Hermes 的全息记忆值得单独看
    3. 9.3 Claude Code 的记忆预取:藏在流水线里的优化
    4. 9.4 扩展体系:四种扩展点
    5. 9.5 Hermes 的网关层:Claude Code 完全没有的一层
  11. 10 · 两个系统的横向对照总表
    1. 10.1 机制对照
    2. 10.2 两条架构路线各自的账本
    3. 10.3 两家一致的地方 = 事实上的行业共识
  12. 11 · 可以搬到自己项目里的实现范式
    1. 11.1 骨架一:带恢复状态机的主循环
    2. 11.2 骨架二:上下文治理阶梯
    3. 11.3 骨架三:工具抽象 + 并发分区
    4. 11.4 骨架四:按信任边界配置工具面
    5. 11.5 骨架五:不可绕过的安全底座
    6. 11.6 自建智能体的决策清单
    7. 11.7 一页纸检查清单
  13. 12 · 面试话术卡
    1. Q1 · 说说你理解的智能体架构
    2. Q2 · 上下文满了怎么办
    3. Q3 · 怎么防止智能体执行危险命令
    4. Q4 · 多工具并行怎么保证不出竞态
    5. Q5 · 智能体循环怎么防止无限循环
    6. Q6 · 什么时候该用子智能体
    7. Q7 · 智能体的长期记忆怎么做
    8. Q8 · 你怎么优化智能体的成本和延迟
    9. Q9 · 反问环节可以问的问题
    10. 最后:这份文档的正确用法
  14. 13 · 术语表
    1. 13.1 模型与调用
    2. 13.2 提示词缓存(全文最重要的概念组)
    3. 13.3 智能体与工具
    4. 13.4 上下文治理
    5. 13.5 编程与架构概念
    6. 13.6 两个系统的关键模块名

1 · 零基础前置知识

这一章不讲 Hermes,也不讲 Claude Code。它只做一件事:把后面十二章需要用到的所有概念,从零建立起来

如果你已经知道什么是大语言模型、什么是 token、什么是提示词缓存,可以快速扫过。但如果你对其中任何一个概念不确定,请完整读完这一章 —— 后面所有的设计分析都建立在这些概念之上,跳过会导致后面每一章都似懂非懂。

1.1 大语言模型是什么

「大语言模型」的英文是 Large Language Model,业内常缩写成 LLM。为了不制造理解障碍,这份文档后面一律写「大语言模型」全称,不用缩写。

抛开所有数学细节,一个大语言模型在使用时只做一件事:

你给它一段文字,它预测这段文字之后最可能出现的下一个字。然后把这个字接在后面,再预测下一个。如此反复,直到它认为该停了。

就这么简单。它不是数据库,不会「查询」;它不是搜索引擎,不会「检索」。它是一个极其庞大的、通过阅读海量文本训练出来的「文字续写器」。

这个简单的机制之所以能产生看起来像思考的行为,是因为训练它的文本里包含了大量的推理过程、对话记录、代码和解释。当它续写「问题:1+1 等于几?答案:」的时候,训练数据告诉它接下来最可能出现的是「2」。

最关键的一条性质:它完全没有记忆

这是整份文档最重要的前置认知,请务必理解清楚:

大语言模型在两次调用之间不保留任何信息。它不记得你上一句说了什么,不记得五分钟前的对话,甚至不记得三秒钟前它自己刚说过的话。

每一次调用,对它来说都是人生中第一次也是唯一一次被使用。

可以用一个类比来理解这件事:

想象有一位学识极其渊博的专家,但他患有一种特殊的失忆症 —— 每次谈话结束后,他会彻底忘记刚刚发生的一切

你想和他进行一场持续两小时的深入讨论,唯一的办法是:每说一句新话之前,先把前面已经发生的全部对话,从头到尾重新念给他听一遍。念完之后,再补上你的新问题。他听完全部内容,回答一句。然后他又忘了。你下一句话之前,得把包括他刚才那句回答在内的全部内容,再念一遍。

这个「每次都要重念全部历史」的机制,是理解后面所有设计的钥匙。它直接导致了三个后果,我们接下来逐个解释:

  • 对话越长,每次要念的内容越多,越贵、越慢(见 1.2 和 1.3)
  • 能念的内容有上限,超了就报错(见 1.4)
  • 如果这次念的开头和上次一模一样,可以想办法省掉重念的开销(见 1.8,这是全文最重要的技术点)

1.2 token 是什么

「token」这个词很难翻译,业内通常直接用英文,或者译作「词元」。这份文档保留英文 token,因为它已经是事实上的标准术语。

token 是大语言模型处理文字的最小单位,也是计费的单位。

模型不是按「字」处理文字的,也不是按「单词」。它用一套专门的切分规则,把文字切成一个个 token。大致的规律是:

文字大约几个 token说明
英文单词 hello1 个常见的短单词通常是 1 个 token
英文单词 unbelievable3~4 个长单词会被切成 un + believ + able 这样的片段
中文「你好」2~3 个中文通常一个汉字就占 1 个甚至更多 token,所以中文比英文贵
一段 100 字的中文约 150~200 个粗略估算可以按「汉字数 × 1.5~2」
一段 100 词的英文约 130 个粗略估算可以按「英文单词数 × 1.3」

为什么要关心 token?因为使用大语言模型的费用是按 token 计算的,而且分成两种价格:

  • 输入 token(input token)—— 你念给模型听的那些内容。便宜。
  • 输出 token(output token)—— 模型说出来的内容。贵,通常是输入价格的 3~5 倍。
一个反直觉但至关重要的结论

虽然输出 token 的单价更贵,但在智能体系统里,总花销的大头几乎总是输入 token

原因就是 1.1 讲的「每次都要重念全部历史」。假设一场对话进行了 50 轮,那么第 50 轮要重念前 49 轮的全部内容。整场对话下来,第 1 轮的内容被重复付费了 50 次,第 2 轮被付费了 49 次……而每一轮的输出只付费一次。

所以后面你会看到,两套系统都花了极大的工程力气去压缩「要重念的内容」。这不是吝啬,这是主要成本项。

1.3 上下文与上下文窗口是什么

「上下文」(context)指的就是你这一次念给模型听的全部内容。包括:系统设定、历史对话、工具执行的结果、以及你的新问题。它是一个纯文本序列。

「上下文窗口」(context window)指的是模型一次最多能接受多少 token。这是一个硬性上限,由模型本身决定,用户无法调整。

常见的上下文窗口大小:

  • 较早的模型:8,000 token(大约 4,000~5,000 个汉字)
  • 目前主流:200,000 token(大约 10 万~13 万个汉字,相当于一本中等长度的小说)
  • 特长版本:1,000,000 token

可以把上下文窗口想象成一张固定大小的桌子。你要讨论的所有材料都必须摊在这张桌子上,模型才能看到。桌子摊满了,就再也放不下新东西 —— 这时候你只有两个选择:拿掉一些旧材料,或者把几份材料压缩成一份摘要

这个「桌子满了怎么办」的问题,就是本文档第 6 章的全部内容,也是智能体系统里最难、最能体现工程水平的一块。

超出上限会发生什么

会直接报错。这个错误在两套系统的代码里出现频率极高,它有一个专门的名字:

prompt_too_long(提示词过长),对应的网络错误代码是 413

后面章节会反复出现「413」这个数字,它指的就是这个错误:你念给模型的内容超过了它的上下文窗口,模型拒绝处理。

1.4 智能体与聊天机器人的区别

「智能体」的英文是 Agent,也常被译作「代理」。这份文档统一使用「智能体」,或者在指代具体产品时用英文 Agent(比如 Claude Code 里有一个工具就叫 AgentTool)。

聊天机器人和智能体的区别可以用一句话概括:

聊天机器人只会说话。智能体会动手做事。

更准确地说:

聊天机器人智能体
能做什么 你问一句,它答一句。答完这一轮就结束。 你给一个任务,它自己拆解成多个步骤,调用外部工具去执行,看到执行结果后决定下一步,反复多轮,直到任务完成。
一次请求
调用模型几次
1 次 几次到几百次。每执行完一批工具,就要再调一次模型问「接下来干什么」。
上下文如何变化 基本不变 自己不断膨胀。每次工具执行都往上下文里塞进几千甚至几万个 token 的执行结果。
失败模式 答错了。用户重问一遍就行。 删错了文件、执行了危险命令、陷入死循环烧掉几千次 API 调用、上下文爆掉之后完全失忆。
这张表解释了这份文档为什么存在

做一个聊天机器人,核心工作是写好提示词。
做一个智能体,核心工作是处理上面「上下文如何变化」和「失败模式」这两行

后面的第 4 章讲失败模式(错误恢复),第 6 章讲上下文膨胀,第 7 章讲危险操作。这三章合起来,就是「做过智能体」和「只用过智能体」的分界线。

1.5 工具调用是什么,它到底怎么工作

这一节讲清楚智能体最核心的机制。很多人对这里有误解,所以我们讲得细一点。

第一个要纠正的误解:模型不能执行任何操作

大语言模型只会输出文字。它不能读文件,不能运行命令,不能上网。它被关在一个只有文字进出的盒子里。

那智能体是怎么读文件、跑命令的?答案是:模型写一张「便条」,外面的程序照着便条去执行,然后把执行结果作为文字念给模型听。

继续用 1.1 的那位失忆专家做类比:

这位专家被关在一个房间里,只能通过一个小窗口和外界交流。他不能出来。

但他可以写便条:「请帮我打开 config.json 这个文件,把内容念给我听。

窗口外的助理拿到便条,去打开文件,把文件内容抄下来,从窗口递进去。专家读完,可能又写一张新便条:「请把第 12 行改成这样……

专家自己什么也没做。所有实际操作都是助理做的。专家只是在写便条和读回复。

在技术上,这个「便条」有一个标准格式,叫做 tool_use(工具使用)。助理递回去的执行结果,叫做 tool_result(工具结果)。这两个词在后面章节里会频繁出现。

完整流程逐帧拆解

假设用户说「把 config.json 里的端口号改成 8080」。完整发生的事情是:

【第 1 帧】程序把这些内容拼成一段文字,发给模型: ├─ 系统设定:"你是一个编程助手,你可以使用以下工具……" ├─ 工具清单:read_file(读文件)、write_file(写文件)、bash(跑命令)…… │ 每个工具都附带它需要什么参数的说明 └─ 用户消息:"把 config.json 里的端口号改成 8080" 【第 2 帧】模型返回一张便条(tool_use): { 工具名: "read_file", 参数: { 路径: "config.json" } } 注意:模型自己没有读文件,它只是说"我想读这个文件" 【第 3 帧】程序(不是模型)真的去读了这个文件,拿到内容: { "host": "localhost", "port": 3000 } 【第 4 帧】程序把「全部历史 + 这次的执行结果」重新拼一遍,再发给模型: ├─ 系统设定(和第 1 帧一模一样,重发) ├─ 工具清单(和第 1 帧一模一样,重发) ├─ 用户消息(重发) ├─ 模型上一轮的便条(重发) └─ tool_result:'{ "host": "localhost", "port": 3000 }' ← 唯一的新内容 【第 5 帧】模型返回第二张便条: { 工具名: "write_file", 参数: { 路径: "config.json", 内容: '{ "host": "localhost", "port": 8080 }' } } 【第 6 帧】程序真的去写了文件,返回:"写入成功" 【第 7 帧】程序又把「全部历史 + 写入成功」重发给模型 【第 8 帧】模型这次不写便条了,直接返回一句人话: "已经把端口号改成 8080 了。" 没有便条 = 任务完成 = 循环结束
请注意第 4 帧和第 7 帧

每一轮都要把前面所有内容原封不动重发一遍。这就是 1.1 说的「每次都要重念全部历史」在实际系统里的样子。

这个例子只有 3 轮。真实的编程任务经常有 30 轮、100 轮。到第 100 轮时,你要重发前 99 轮的所有内容 —— 包括那 99 次工具执行的全部输出。如果其中有几次是「把整个文件读出来」,那就是几万个 token。

这就是为什么「上下文治理」是智能体系统里最重要的工程问题。

「没有便条就结束」是唯一的终止信号

请记住第 8 帧:模型这一轮没有写任何便条,只说了人话 —— 这就是任务完成的信号。

后面第 4 章你会看到,两套系统的主循环判断「要不要继续」的依据都是同一件事:这一轮的回复里有没有 tool_use。有就继续,没有就结束。

1.6 什么是流式输出

模型生成文字是一个字一个字往外吐的,不是憋足了一次性给你。这叫「流式输出」(streaming)。

你在使用各类 AI 聊天产品时看到文字一个个蹦出来,就是流式输出。这不是为了好看的动画效果,而是模型真实的工作方式 —— 它确实是一个 token 一个 token 生成的。

流式输出带来一个重要的优化机会,后面第 5 章会讲到:

如果模型这一轮要写三张便条,那么第一张便条写完的时候,第二张还没开始写

聪明的做法是:第一张便条一到手就立刻开始执行它,不用等三张全写完。这样工具执行的时间和模型生成的时间就重叠了。

Claude Code 有一个专门的组件干这件事,叫 StreamingToolExecutor(流式工具执行器)。

1.7 什么是 API

API 是 Application Programming Interface 的缩写,中文叫「应用程序接口」。这个缩写已经完全通用,后面直接用 API。

它的意思是:一个程序向另一个程序提供服务的约定好的方式。

在这份文档里,「调用 API」几乎总是指同一件事:你的程序通过网络,把上下文发送给 Anthropic(或 OpenAI 等)公司的服务器,服务器上的大语言模型处理后把结果通过网络返回给你。

几个后面会用到的相关说法:

  • 「一次 API 调用」 = 把上下文发过去、拿到一次完整回复。这是计费单位,也是延迟的主要来源(通常耗时 2~30 秒)。
  • 「供应商」(provider) = 提供模型服务的公司。Anthropic、OpenAI、Google 等。
  • 「私有能力」 = 某家供应商独有、别家没有的功能。用了就享受不到换供应商的自由,这是第 10 章的核心权衡。

1.8 提示词缓存 —— 全文最重要的技术概念

如果这一章你只能记住一个概念,请记住这个。Claude Code 里超过一半的「奇怪设计」都是为了保护提示词缓存。不理解这一节,后面第 5、6、8 章会有大量内容看起来莫名其妙。

它解决什么问题

回到 1.5 的第 4 帧和第 7 帧:每一轮都要重发全部历史。服务器每次都要把这些内容重新「读」一遍(技术上叫做处理 prompt,即计算注意力)。这个重复处理既慢又花钱。

供应商们注意到一件事:连续两次请求,开头的绝大部分内容是一模一样的。第 100 轮和第 99 轮的区别,只是末尾多了一轮对话。前面 99 轮完全相同。

于是有了「提示词缓存」(prompt cache):

服务器把上一次处理过的内容缓存起来。这一次请求进来时,从头开始逐字比对:只要开头这一段和缓存里的完全一致,就直接复用缓存的处理结果,跳过重新计算。

命中缓存的那部分 token,价格通常只有原价的 10%,而且不消耗处理时间。

还是用失忆专家的类比:

那位专家其实有一个笔记本,记着「上次你念到哪里」。

这次你开始念,他一边听一边对照笔记本。只要你念的和笔记本上记的一字不差,他就快速跳过(因为他已经理解过这部分了)。直到某个字对不上了 —— 从那个字开始,他必须重新认真听。

关键性质:它是「前缀匹配」,一字之差全盘失效

这是最容易被忽略、也是后面所有设计的根源:

缓存的比对是从最开头开始、逐字进行的。一旦某个位置对不上,从那个位置往后的全部内容都必须重新处理。

举例:你的上下文有 10 万个 token。你在第 100 个 token 的位置改了一个字 —— 哪怕只是把一个空格变成两个空格 —— 那么后面 99,900 个 token 全部要重新处理,缓存等于完全没用

这个性质导致了一系列在外行看来非常奇怪的工程决策,你在后面会遇到,现在先预告几个:

看起来很奇怪的做法真实原因在哪一章
给子智能体一堆它根本用不到的工具 工具清单是上下文开头的一部分。少给几个工具就改变了开头,缓存全废。宁可多给。 第 8 章
内建工具和外部工具分别排序后拼接,而不是混在一起统一排序 服务器在「最后一个内建工具」的位置放了缓存分界点。统一排序会让外部工具插进内建工具中间,把这个区间劈开,所有用户的缓存一起失效。 第 5 章
要删掉上下文里的旧内容,却一个字都不改本地数据,而是发一条特殊指令让服务器去删 改本地数据 = 改变了发出去的内容 = 缓存失效。省下的钱不如重建缓存的开销大。 第 6 章
要给日志补充一些字段,却只改一份复制品,绝不碰原件 原件是要发给 API 的。改一个字节,缓存就没了。 第 5 章

缓存有有效期,会「凉掉」

缓存不是永久的。常见的有效期是 5 分钟(也有 1 小时的付费选项)。超过有效期,缓存被清除,下次请求必须全部重新处理。

这引出了一个后面会看到的精妙设计:「缓存现在是热的还是凉的」应该成为决策的输入

  • 缓存是热的(刚刚才请求过)→ 千万不要动上下文的开头,能省一大笔
  • 缓存已经凉了(用户去吃了顿饭才回来)→ 前面反正要全部重新处理,这时候正是大刀阔斧清理旧内容的最佳时机

同一个目标(清理旧内容),根据缓存冷热要走两条完全相反的路。绝大多数自己搭建智能体的团队完全没有「缓存冷热」这个概念,所以只有一套策略,在两种场景下各错一半。

1.9 还会遇到的几个词

这些词在后面章节里出现频率较高,先建立印象,不必现在完全掌握。第 13 章有完整术语表。

意思
系统提示词
system prompt
上下文最开头那一段,给模型设定身份和规则的文字。比如「你是一个编程助手,遵循以下规范……」。因为它在最开头,所以它是缓存最先比对的部分,绝对不能随意改动
轮次
turn
一次「调用模型 → 执行工具」的完整往复。1.5 的例子里有 3 轮。
压缩 / 摘要
compact
上下文快满时,让模型把前面一大段对话总结成一段短摘要,用摘要替换原文。这是有损的、不可逆的操作,所以是最后手段。
状态机
state machine
一种编程模式:把程序的运行状况归纳成有限的几个「状态」,并明确规定「在什么条件下从哪个状态跳到哪个状态」。第 4 章会详细讲。
幂等
idempotent
一个操作执行一次和执行多次的效果完全相同。在这份文档里主要用于「幂等锁」—— 一个标记,确保某个恢复动作在一轮里只做一次,防止无限循环。
沙箱
sandbox
一个被严格限制权限的隔离运行环境。程序在沙箱里跑,就算它想删除系统文件也删不掉,因为它根本没有那个权限。
正则表达式
regular expression
一种用特殊符号描述「文字模式」的写法。比如可以写一个模式来匹配「所有以 rm 开头、后面跟着 -rf 的命令」。第 7 章 Hermes 用了 59 条正则表达式来拦截危险命令。
抽象基类
Abstract Base Class,缩写 ABC
编程里的一种「插座标准」。它规定了「任何想接进来的东西必须提供哪几个功能」,但不规定这些功能怎么实现。这样第三方可以做出自己的实现插进来。Hermes 大量使用这个模式,这是它和 Claude Code 最大的架构差异。
中止信号
AbortController / abort signal
一个可以在程序各处传递的「取消开关」。用户按下 Ctrl+C 时,程序拉一下这个开关,所有正在进行的操作都能感知到并停下来。第 4 章会讲它的正确用法和一个致命陷阱。
这一章的核心,浓缩成五句话
  1. 大语言模型只会续写文字,而且完全没有记忆 —— 每次调用都要把全部历史重发一遍。
  2. 因此成本大头是输入 token,不是输出。压缩「要重发的内容」是核心工程问题。
  3. 模型自己不能执行任何操作,它只能写便条(tool_use)让外部程序去执行,然后读结果(tool_result)。
  4. 上下文窗口是硬性上限,撞上去就报 413 错误。「桌子满了怎么办」是第 6 章的全部内容。
  5. 提示词缓存是前缀匹配的,一字之差全盘失效。这一条解释了后面一半以上的「奇怪设计」。