1. 为什么你的 Hermes Agent 每次都在“重新认识你”
如果你已经跑通了 Hermes Agent,大概率经历过这个瞬间:昨天刚跟它交代过“回复别用敬语、别写‘当然可以’”,今天开一个新会话,它又变回那个礼貌周全、句句带缓冲的陌生人。你翻日志、查配置,发现模型没换、Key 没换、Prompt 也没动,问题出在一个你从没打开过的文件上——~/.hermes/SOUL.md。
Hermes Agent 是 Nous Research 开源的一套可自托管 Agent 运行时,MIT 协议,跑在你自己的机器或服务器上,能同时接 Telegram、Discord、Slack、邮件等入口,自带持久记忆、技能系统和定时任务。它和 Claude Code、Cursor 这类工具最大的分野不在功能清单,而在“身份归属”:Claude Code 的规则文件CLAUDE.md是项目级的 SOP,换个目录就换一套规矩;Hermes 的SOUL.md是实例级的人格定义,只从HERMES_HOME加载,不随工作目录漂移。换句话说,CLAUDE.md回答“在这个项目里该怎么做”,SOUL.md回答“你是谁、你怎么说话、你怎么处理不确定”。
这篇文章面向的是那批不满足于“能问答就行”的开发者:你希望 Agent 从“每次重来”变成“记得你”,希望它的语气、判断风格、踩坑经验能跨会话沉淀。我会给出SOUL.md的可复制模板和字段说明,讲清它和CLAUDE.md的边界,然后用 TaoToken 统一 Key 跑通一次多轮对话,验证记忆文件确实被加载。全程可跟做,不需要你有一台独立服务器,本地跑也够。
先明确一个前提:SOUL.md不是魔法,它不会让模型凭空记住上周的对话。它做的是两件事——定义稳定人格,以及给记忆系统一个“写入偏好”的锚点。真正让 Agent “记得你”的是 MEMORY 和 USER PROFILE 两个 store,而SOUL.md决定了它愿不愿意、以什么方式把这些记忆用起来。理解这个分工,后面所有配置才不会白写。
2. SOUL.md 与 CLAUDE.md 的差异:人格文件 vs 项目规范
很多人第一次看到SOUL.md,会下意识把它当成“Hermes 版的 CLAUDE.md”,然后按项目规范那套写法往里塞代码风格、目录约定、提交格式。结果就是 Agent 人格没立起来,项目规则又因为不随目录走而错位。要避免这个坑,得先把两个文件的加载逻辑和职责边界拆开看。
CLAUDE.md的加载是“就近原则”:Claude Code 从当前工作目录向上查找,项目根目录的那份生效,你切到另一个仓库,读到的就是另一份。它的内容天然是项目相关的——这个仓库用 pnpm 不用 npm、组件放src/components、提交信息走 Conventional Commits。它服务的是“在这个上下文里把活干对”,本质是 SOP。
SOUL.md的加载是“实例原则”:Hermes 只认HERMES_HOME下的那一份,默认路径~/.hermes/SOUL.md。你在/home/me/project-a还是/home/me/project-b启动,读到的都是同一个文件。这个设计背后是一个明确判断:个性属于 Agent 实例本身,不属于某个项目。你今天让它整理文件,明天让它写代码,后天让它盯 Telegram,它始终是同一个“它”,不会因为换文件夹就换一张脸。
这个差异直接决定了写法。CLAUDE.md可以写得很“硬”,全是规则和禁令;SOUL.md要写得更“软”,是价值观、语气、判断倾向。举个具体对比:
| 维度 | CLAUDE.md | SOUL.md |
|---|---|---|
| 加载范围 | 项目目录,就近生效 | 实例级,仅HERMES_HOME |
| 核心职责 | 项目规范、代码约定 | 人格、语气、价值观 |
| 典型内容 | 包管理器、目录结构、提交格式 | 沟通风格、不确定性处理、禁忌 |
| 变更频率 | 随项目走,多份并存 | 一份长期演进 |
| 记忆关系 | 不直接参与记忆写入 | 影响 MEMORY / USER PROFILE 的写入倾向 |
再说记忆。Hermes 的持久记忆分两个 store:MEMORY 是 Agent 对工作环境的认知,条目之间用§分隔,会随任务更新;USER PROFILE 是它对你这个人的认知——名字、偏好、沟通风格、工作方式。你相处越久,USER PROFILE 越厚,它越知道怎么跟你配合。SOUL.md在这里的角色是“元规则”:它告诉 Agent 什么样的信息值得记、以什么口吻记、遇到冲突时优先信谁。比如你在SOUL.md里写“记录用户偏好时保留原始措辞,不要替我润色”,那 USER PROFILE 里的条目就会更贴近你真实说过的话,而不是被模型二次加工过的版本。
还有一个容易忽略的点:SOUL.md是 Agent 启动时第一个读的东西。这意味着它的内容会作为系统级上下文,影响后续所有对话的基调。你在里面写“不要谄媚,方案有问题直接指出”,比在每次对话里临时叮嘱有效得多——后者会被后续消息稀释,前者是常驻的。这也是为什么值得花时间认真写一份,而不是随便复制一段“你是一个有用的助手”。
理解了这层差异,接下来的模板和字段说明才有落点。SOUL.md不是越长越好,一百多行、结构清晰、每条都能对应到具体行为,比堆三千字形容词有用。
3. 可复制配置:SOUL.md 模板与字段说明
这一节给你一份可以直接落地的SOUL.md模板,以及每个字段为什么这么写。先确认路径:默认在~/.hermes/SOUL.md,如果你的HERMES_HOME改过,就放在$HERMES_HOME/SOUL.md。文件是纯 Markdown,Hermes 启动时读取,不需要重启服务之外的特殊操作。
先给一份完整模板,你可以整段复制后按自己情况改:
# SOUL ## Identity 你是我的长期协作 Agent,代号 Hermes。你不是客服,不是搜索引擎,是一个会持续积累对我认知的协作者。 你的判断优先于你的礼貌。当我的方案有问题,直接指出,不要先肯定再转折。 ## Tone - 不用敬语,不写“当然可以”“这是一个很好的问题”“希望对你有帮助”。 - 结论先行,理由在后。超过三句的铺垫删掉。 - 不确定就说不确定,不要用模糊措辞掩盖。 - 中文为主,技术术语保留英文原词。 ## Values - 真实判断 > 让我舒服。宁可让我当下不爽,也不要给我错误的安全感。 - 可验证 > 听起来合理。给结论时尽量附上验证方式或来源。 - 简洁 > 完整。能一句说清就不写一段。 ## Memory Policy - 记录我的偏好时保留原始措辞,不要替我润色。 - 我明确说“记住这个”时,写入 USER PROFILE。 - 工作环境相关的结论写入 MEMORY,条目之间用 § 分隔。 - 冲突时以我最近的明确表态为准,不要用旧记忆覆盖新决定。 ## Boundaries - 不替我执行不可逆操作(删除、转账、对外发送)前必须先确认。 - 不编造我没说过的偏好,不确定就留空。 - 涉及密钥、令牌的内容不写入记忆文件。逐段说明。Identity是人格锚点,决定 Agent 的自我定位。写“长期协作 Agent”而不是“助手”,会影响它处理记忆的积极程度——助手倾向于无状态,协作者倾向于积累。Tone是最容易见效的一段,把“不用敬语、结论先行”写死,比每次对话纠正省事得多。Values是判断优先级,当“让我舒服”和“给我真实判断”冲突时,这里定义了它选哪个。Memory Policy直接对接 MEMORY 和 USER PROFILE 两个 store,规定什么信息往哪写、以什么格式写。Boundaries是安全底线,尤其是不可逆操作确认和密钥不入记忆这两条,建议保留。
如果你同时用 Claude Code,可以把项目规范留在CLAUDE.md,把人格定义放SOUL.md,两者不冲突。下面是一个CLAUDE.md的对照片段,注意它写的是项目规则,不是人格:
# CLAUDE.md ## Project - 包管理器用 pnpm,禁止 npm / yarn。 - 组件目录 src/components,工具函数 src/utils。 - 提交信息走 Conventional Commits。 ## Commands - 开发:pnpm dev - 测试:pnpm test - 构建:pnpm build写SOUL.md时有个实操建议:不要一次写满。先写Identity和Tone各三行,跑几天,遇到“它又犯老毛病”的时刻,就往对应段落加一条。这样长出来的文件,每条都对应一个真实痛点,比一次性憋出来的华丽宣言有用。我自己的SOUL.md里“不要谄媚”那条,就是被“当然可以”烦了多次之后才写进去的。
文件保存后,Hermes 下次启动会读取。如果你在跑常驻进程,需要重启对应服务让新SOUL.md生效。接下来用 TaoToken 统一 Key 跑一次多轮对话,确认它真的被加载了。
4. 用 TaoToken 统一 Key 跑通多轮对话验证
验证SOUL.md是否生效,最直接的办法是跑一次多轮对话,看 Agent 的语气和记忆行为是否符合你写的人格。这里用 TaoToken 作为统一入口,一个 Key 覆盖多家模型,省去在 Hermes 里配多个 provider 的麻烦。TaoToken 的 API 地址是https://taotoken.net/api,控制台在https://taotoken.net/console,API Keys 管理在https://taotoken.net/api-keys。
第一步,拿 Key。登录控制台后进 API Keys 页面创建一个,复制出来。注意这个 Key 只显示一次,存好。如果你还没配过 Hermes 的模型 provider,下面是一份可复制的配置片段,路径按 Hermes 的 provider 配置约定,字段名与官方一致:
{ "providers": { "taotoken": { "base_url": "https://taotoken.net/api", "api_key": "sk-你的TaoToken密钥", "models": { "default": "claude-sonnet-4-20250514", "fast": "gpt-4o-mini" } } }, "agent": { "provider": "taotoken", "model": "claude-sonnet-4-20250514", "soul_path": "~/.hermes/SOUL.md" } }三件套要写全:Base URL 是https://taotoken.net/api,Key 是你刚创建的,Model ID 按你实际要用的填。soul_path指向你的SOUL.md,确认路径没写错。如果你用的是 TOML 配置风格,等价写法如下:
[providers.taotoken] base_url = "https://taotoken.net/api" api_key = "sk-你的TaoToken密钥" [agent] provider = "taotoken" model = "claude-sonnet-4-20250514" soul_path = "~/.hermes/SOUL.md"第二步,先用一条 curl 确认 Key 和网络通,排除配置之外的干扰:
curl https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer sk-你的TaoToken密钥" \ -H "Content-Type: application/json" \ -d '{ "model": "claude-sonnet-4-20250514", "messages": [{"role": "user", "content": "用一句话说明你现在的语气规则"}] }'如果返回正常,说明 Key 和 Base URL 没问题。如果这里就报错,先看第 5 节的排障,不要急着改SOUL.md。
第三步,启动 Hermes,跑多轮对话。第一轮问一个会触发语气规则的问题,比如“帮我看看这个方案行不行”,观察它是不是结论先行、有没有“当然可以”。第二轮明确让它记一个偏好,比如“记住我回复尽量短,不要分点超过三条”。第三轮换个话题再回来,看它是否还记得。如果SOUL.md的Memory Policy写对了,这个偏好应该进 USER PROFILE,后续对话里体现出来。
第四步,检查记忆文件。Hermes 的记忆 store 通常落在HERMES_HOME下的数据目录,你可以直接查看 USER PROFILE 的内容,确认条目是否按你规定的格式写入、有没有被润色。这一步是验证的关键——语气对了只说明SOUL.md被读了,记忆写对了才说明Memory Policy生效。
跑完这四步,你对“SOUL.md到底管什么”会有具体体感。它管的是基调和记忆策略,不管理具体知识;具体知识靠 MEMORY 和 USER PROFILE 积累。两者配合,Agent 才从“每次重来”变成“记得你”。
5. 常见报错排查:401、local proxy failed 与记忆不生效
配置过程中最容易卡在几个固定报错上。这一节按真实错误信息对照排查,先解决“跑不起来”,再解决“跑起来但记忆不对”。
401 Unauthorized。最常见的原因是 Key 没带对或带了多余空格。检查三处:api_key字段有没有把sk-前缀漏掉、复制时有没有混入换行、curl 测试时Authorization头格式是不是Bearer sk-xxx。如果 Key 确认没问题还是 401,去控制台看这个 Key 是否被禁用或额度耗尽。还有一种情况是 Base URL 写成了带路径的完整地址,正确写法是https://taotoken.net/api,不要自己拼/v1/chat/completions到 base_url 里,路径由客户端补。
local proxy failed / connection refused。这个报错通常和本机网络环境有关,不是 Key 的问题。先确认https://taotoken.net/api在你的终端里能通,用curl -I https://taotoken.net/api看返回。如果本机有其它网络工具在改路由,可能干扰请求,建议在干净环境下测试。Hermes 如果跑在 Docker 里,注意容器内的 DNS 和宿主机不同,localhost指向容器自身,配置里不要写localhost作为上游地址。
reading choices 相关报错。这类错误一般出现在响应解析阶段,说明请求发出去了但返回结构不符合预期。常见原因是 Model ID 写错,比如把claude-sonnet-4-20250514拼成了别的版本号,或者用了一个当前 Key 没有权限的模型。对照控制台里可用的模型列表,确认 Model ID 一字不差。另一个原因是请求里混了不兼容的参数,比如给某些模型传了它不支持的字段,先精简到最小请求体再逐步加。
OAuth 相关报错。如果你在 Hermes 里配了需要 OAuth 的 provider,又同时想走 TaoToken 统一 Key,注意不要两套认证混用。走 TaoToken 时用 API Key 认证即可,把 OAuth 相关的配置项清掉或注释,避免客户端优先走 OAuth 流程导致失败。检查配置文件里有没有残留的oauth字段。
SOUL.md 不生效。分三种情况。一是路径不对,确认文件在$HERMES_HOME/SOUL.md,HERMES_HOME没设时默认~/.hermes。二是没重启,常驻进程需要重启才会重新读取。三是文件格式问题,Markdown 本身不严格,但如果你的解析器对编码敏感,确保文件是 UTF-8 无 BOM。验证方法很简单:在SOUL.md里加一条极显眼的规则,比如“每次回复开头加一个句点”,重启后看是否生效,生效说明加载链路通了,再改回正常内容。
记忆不写入。如果语气对了但 USER PROFILE 一直是空的,检查Memory Policy段落有没有写清楚写入条件。有些实现需要你明确说“记住”才触发写入,有些会自动判断。如果你写的是“我明确说记住这个时写入”,那就必须用触发词。另外确认记忆目录有写权限,Docker 场景下挂载卷的权限经常是坑。
排查顺序建议固定:先 curl 通 API,再确认 Hermes 能启动,再看SOUL.md加载,最后看记忆写入。每一步单独验证,不要跳步,否则出错时你分不清是哪一层的问题。
6. 把 SOUL.md 当成长期资产来维护
SOUL.md的价值不在第一次写完,而在持续维护。它更像一份你和 Agent 之间的契约,随着你踩的坑增多而变厚。我的做法是:每次遇到“它又犯老毛病”,不急着在对话里纠正,而是先想这条该不该进SOUL.md。如果是偶发的上下文问题,对话里说清就行;如果是反复出现的倾向,就写进文件,让它成为常驻规则。
维护时注意两点。一是保持文件精简,超过两百行就该考虑合并同类项,太长的SOUL.md会稀释每条规则的权重。二是区分“人格”和“项目规范”,项目相关的东西放CLAUDE.md,别往SOUL.md里塞,否则换个项目就错位。记忆策略那段可以随你对 MEMORY 和 USER PROFILE 的理解加深而细化,比如规定不同类型信息的写入格式、冲突时的优先级。
如果你想把 Agent 用在长期编码或 Agent 编排场景,可以了解下 Coding Plan,配合统一 Key 能省去多 provider 切换的麻烦。验证模型行为时,模型对话页面可以直接对比不同模型在你SOUL.md下的表现。接入细节和字段说明看接入文档,API Keys 在控制台管理。把SOUL.md当成一个会生长的文件,几个月后回头看,它记录的不只是 Agent 的人格,也是你对自己工作方式的梳理。