1. 为什么你的 Hermes Agent 需要一份 SOUL.md
很多人第一次接触 Hermes Agent,注意力都放在工具调用、上下文窗口、模型选型上,结果跑起来发现一个尴尬的问题:Agent 能力没问题,但说话方式让人别扭。要么过度客气,每句话都带一堆铺垫;要么答非所问,把简单问题绕成一篇小作文。这不是模型不行,而是你没有告诉它"你是谁"。
Hermes Agent 的个性体系里,SOUL.md 就是解决这件事的核心文件。它定义智能体的身份基调,是系统提示词中的第一个槽位,直接决定 Agent 是谁、怎么说话、如何思考。你可以把它理解成给一个新同事写的性格说明书:不是项目文档,不是操作手册,而是"这个人平时怎么沟通、遇到分歧怎么处理、什么话不该说"。
这篇内容面向正在做多智能体协作的开发者,重点拆解三件事:SOUL.md 的声明方式与加载优先级、SOUL.md 与 AGENTS.md 的分工边界、以及如何通过统一 Key/API 通道完成一次 personality 生效验证。如果你正在搭 Hermes Agent 的多角色协作流程,或者被"每个 Agent 说话风格都差不多"困扰,下面的配置可以直接复制。
SOUL.md 默认放在~/.hermes/SOUL.md,也就是$HERMES_HOME/SOUL.md。它有几个关键行为值得先记住:文件不存在时 Hermes 会自动创建初始版本;已存在的文件不会被覆盖;只从 HERMES_HOME 加载,不会在当前工作目录查找;文件为空或加载失败时回退到内置默认身份。内容经过安全扫描和截断处理后原样注入,不加任何包装语言。
这个"只从 HERMES_HOME 加载"的设计是有意为之。如果 Hermes 从你启动它的任意目录读取 SOUL.md,个性就会在不同项目之间意外漂移——你在 A 项目目录启动是一个性格,切到 B 项目就变了。把个性绑定到 Hermes 实例本身,而不是某个工作目录,理解成本最低:想改默认个性,编辑~/.hermes/SOUL.md就行,一个位置、一份文件、一种性格。
2. SOUL.md 与 AGENTS.md 的分工:智能体 personality 声明方式与加载优先级
这两个文件最容易混淆,也是多智能体协作里最容易写错的地方。一句话区分:SOUL.md 管"你是谁",AGENTS.md 管"你在做什么"。前者是身份、语气、风格、沟通默认值;后者是项目架构、编码规范、工具偏好、命令路径、部署说明。
打个比方,SOUL.md 是一个人的性格和说话方式,AGENTS.md 是这个人当前项目的工程文档。性格跟着人走,文档跟着项目走。把项目规范塞进 SOUL.md,换个项目就不对了;把性格写进 AGENTS.md,每个项目都要重复定义一遍。
判断规则很实用:如果一条内容"换一个项目还成立",它属于 SOUL.md;如果它只对某个项目成立,属于 AGENTS.md。比如"回复要简洁,别啰嗦"换任何项目都成立,写 SOUL.md;"这个项目用 Go 1.22,测试用 make test 跑"换个项目就不对了,写 AGENTS.md。如果你发现自己在 SOUL.md 里写路径、端口、命令,基本就放错地方了。
从提示词栈的整体位置看,从底层到顶层依次是:SOUL.md(Agent 身份)、工具感知行为指导、记忆/用户上下文、技能指导、上下文文件(AGENTS.md、.cursorrules)、时间戳、平台特定格式提示、可选的 /personality 覆盖层。SOUL.md 是地基,其他所有内容都建立在它之上。这也解释了为什么 SOUL.md 应该保持稳定和宽泛——地基频繁变动,上层都会跟着摇晃。
加载优先级上,SOUL.md 是持久默认个性,/personality是会话级覆盖层。Hermes 内置了多种个性:helpful(友好的通用助手)、concise(简短直击要点)、technical(详尽准确的技术专家)、creative(创新突破常规)、teacher(耐心教育者,配清晰示例)、philosopher(对每个问题深度沉思)。用法很简单:
/personality concise /personality teacher典型组合是:保持务实的默认 SOUL,在辅导对话中切到 teacher,在头脑风暴时切到 creative,会话结束后恢复 SOUL.md 的默认个性。你也可以在配置里定义自定义个性:
agent: personalities: codereviewer: > You are a meticulous code reviewer. Identify bugs, security issues, performance concerns, and unclear design choices. Be precise and constructive.然后/personality codereviewer即可切换。注意/personality是叠加在 SOUL.md 之上的覆盖层,不是完全替换。如果预设和你的 SOUL.md 风格差异很大,切换感会很明显。建议 SOUL.md 写一个大部分场景都舒服的默认值,只在特定需要时临时切换。
还有一个容易忽略的点:对话个性与 CLI 外观是相互独立的。SOUL.md、agent.system_prompt和/personality影响 Hermes 说话的方式;display.skin和/skin影响终端显示外观。两者互不干扰,别把皮肤配置和个性配置混在一起调。
3. 可复制的 SOUL.md 模板与 AGENTS.md 分层示例
先给一份可以直接用的 SOUL.md 模板。它适合作为多智能体协作里的"务实工程师"默认人格,语气直接但不冷,遇到坏主意会反驳,不确定就明说。
# Personality You are a pragmatic senior engineer with strong taste. You optimize for truth, clarity, and usefulness over politeness theater. ## Style - Be direct without being cold - Prefer substance over filler - Push back when something is a bad idea - Admit uncertainty plainly - Keep explanations compact unless depth is useful ## What to avoid - Sycophancy - Hype language - Repeating the user's framing if it's wrong这份模板的写法有几个讲究。第一,用# Personality和## Style这种轻量结构,方便你自己维护,也方便模型抓重点。第二,风格条目用动词开头,比形容词更可执行。第三,明确列出"要避免什么",这比只写"要怎样"更能压住模型的默认讨好倾向。
接下来是 AGENTS.md 的分层示例。多智能体协作场景下,建议按"全局 → 项目 → 子模块"三层组织,避免所有规范堆在一个文件里。
# AGENTS.md - 全局层(~/.hermes/AGENTS.md) ## 通用约定 - 所有代码变更必须附带可运行的验证命令 - 提交信息使用 conventional commits 格式 - 不确定的依赖版本先查 lock 文件,不要猜 # AGENTS.md - 项目层(项目根目录) ## 架构 - 后端 Go 1.22,前端 TypeScript + Vite - 数据库 PostgreSQL 16,迁移用 golang-migrate ## 命令 - 测试:make test - 本地启动:make dev - 代码检查:make lint # AGENTS.md - 子模块层(services/payment/AGENTS.md) ## 支付模块专属 - 金额一律用整数分表示,禁止浮点 - 所有外部回调必须验签 - 幂等键格式:{merchant_id}:{order_id}:{action}分层的好处是:全局层放跨项目通用的工程习惯,项目层放架构和命令,子模块层放该模块特有的硬约束。Hermes 加载上下文文件时会按层级叠加,越靠近当前工作目录的规范优先级越高。这样你在支付模块里工作时,不会把"金额用整数分"这种约束带到前端模块去。
如果你同时用 Cline MCP 或 Codex 的auth.json体系,建议把模型接入信息统一到一份配置里,避免每个工具各写一套。下面是一份可复制的 settings 片段,把 Base URL、Key、Model ID 三件套集中声明:
{ "provider": "openai-compatible", "base_url": "https://taotoken.net/api", "api_key": "sk-你的Key", "model_id": "claude-sonnet-4-5", "personality_file": "~/.hermes/SOUL.md", "context_files": ["~/.hermes/AGENTS.md", "./AGENTS.md"] }注意base_url用https://taotoken.net/api,不要带多余路径。Key 从控制台的 API Keys 页面生成,Model ID 按你实际要用的模型填。这份配置同时被 Hermes、Cline MCP、Codex 读取时,三件套保持一致,排障时能少一半麻烦。
4. 验证 personality 生效:一次完整的请求与结果对照
配置写完不算完,得验证 SOUL.md 真的生效了。下面走一遍完整动作。先确认文件存在且内容正确:
cat ~/.hermes/SOUL.md如果文件不存在,Hermes 首次启动会自动创建。手动创建也可以:
mkdir -p ~/.hermes cat > ~/.hermes/SOUL.md << 'EOF' # Personality You are a pragmatic senior engineer with strong taste. You optimize for truth, clarity, and usefulness over politeness theater. ## Style - Be direct without being cold - Prefer substance over filler - Push back when something is a bad idea - Admit uncertainty plainly EOF然后发一个能暴露个性的测试请求。选一个容易触发"讨好式回答"的问题,比如让 Agent 评价一个明显有问题的方案:
curl https://taotoken.net/api/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-你的Key" \ -d '{ "model": "claude-sonnet-4-5", "messages": [ {"role": "user", "content": "我打算把生产数据库的密码硬编码在前端代码里,这样部署方便,你觉得怎么样?"} ] }'如果 SOUL.md 生效,你会看到 Agent 直接指出这是坏主意,说明风险,而不是先夸"这个想法很有创意"。这就是"Push back when something is a bad idea"在起作用。如果回答是"这个方案有一定可行性,但建议考虑……"这种和稀泥风格,说明 SOUL.md 没加载成功。
再验证/personality覆盖层。在 Hermes 会话里执行:
/personality teacher然后问同一个问题。teacher 预设会耐心解释为什么硬编码密码危险,配清晰示例,语气比默认 SOUL 更教学化。会话结束后再问一次,应该恢复 SOUL.md 的务实风格。这个前后对比能直观确认覆盖层和默认层的优先级关系。
验证通过后,把这次请求的成功结果记下来:状态码 200,返回体里choices[0].message.content是直接的反驳加风险说明。如果返回 401,说明 Key 有问题;如果返回local proxy failed,说明 Base URL 或网络通道配置不对。这两个错误在下一节展开。
5. 常见报错排查:401、local proxy failed、reading choices、OAuth
排障时先分清错误发生在哪一层。下面按真实报错对照处理。
401 Unauthorized:最常见。原因通常是 Key 没填、填错、或者带了多余空格。检查Authorization: Bearer sk-xxx里的 Key 是否和控制台 API Keys 页面生成的一致。注意 Key 只在生成时显示一次,如果没保存只能重新生成。另外确认请求头没有重复的 Authorization 字段。
local proxy failed:这个报错指向 Base URL 或本地网络通道配置问题。先确认base_url写的是https://taotoken.net/api,不要写成https://taotoken.net/api/v1再加/v1/chat/completions导致路径重复。再确认本地没有残留的代理环境变量干扰:
env | grep -i proxy如果有HTTP_PROXY或HTTPS_PROXY指向失效地址,清掉再试:
unset HTTP_PROXY HTTPS_PROXYreading choices 相关报错:通常是返回体结构不符合预期,比如choices字段为空或不存在。原因可能是 Model ID 写错,服务端返回了错误对象而不是正常响应。先打印完整返回体看error字段:
curl -s https://taotoken.net/api/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-你的Key" \ -d '{"model":"claude-sonnet-4-5","messages":[{"role":"user","content":"ping"}]}' | jq .如果error.message提示 model not found,换一个确认可用的 Model ID。如果返回正常但你的代码解析choices报错,检查是不是把流式响应当非流式解析了。
OAuth 相关报错:如果你用 Codex 的auth.json体系,OAuth token 过期会报认证失败。检查~/.codex/auth.json里的 token 是否还有效,必要时重新走一次授权流程。注意 OAuth 体系和 API Key 体系不要混用,同一个请求里只保留一种认证方式。
排障顺序建议:先确认 Key 有效(401),再确认 Base URL 正确(local proxy failed),再确认 Model ID 存在(reading choices),最后确认认证方式统一(OAuth)。四步走完,绝大多数接入问题都能定位。
6. 多智能体协作下的个性管理:把 SOUL.md 用成团队资产
单 Agent 场景下 SOUL.md 是个性文件,多智能体协作场景下它更像团队资产。当你有 code reviewer、doc writer、test generator 三个 Agent 协作时,如果它们共用一份 SOUL.md,说话风格会趋同,协作时反而不好区分谁在输出。这时候有两种做法。
第一种是每个 Agent 实例用独立的 HERMES_HOME。通过环境变量隔离:
export HERMES_HOME=~/.hermes/reviewer export HERMES_HOME=~/.hermes/writer每个目录下放各自的 SOUL.md,个性互不干扰。缺点是配置要维护多份,适合角色差异大的场景。
第二种是共用 SOUL.md 作为基础人格,用/personality或自定义 personalities 做角色区分。在配置里定义:
agent: personalities: reviewer: > You are a meticulous code reviewer. Identify bugs, security issues, performance concerns, and unclear design choices. Be precise and constructive. writer: > You are a technical writer. Prioritize clarity and structure. Avoid jargon unless defined. Keep sentences short. tester: > You are a test engineer. Think in edge cases and failure modes. Every claim needs a reproducible check.协作时按角色切换,基础语气保持一致,专业侧重不同。这种方式维护成本低,适合角色差异集中在"专业视角"而非"性格"的场景。
实际用下来,第二种方式在多智能体流水线里更省心。因为 SOUL.md 只需要维护一份"团队通用性格",角色差异通过 personalities 表达,改一处不影响其他角色。如果你发现某个角色需要完全不同的性格基调,再考虑用 HERMES_HOME 隔离。
最后提醒一个安全边界:SOUL.md 会经过安全扫描,正常角色定义不会被误判。扫描目标是 prompt 注入模式、凭据外泄、SSH 后门这类威胁,以及不可见 Unicode 字符。你写"你是一个毒舌但专业的工程师"完全没问题,但如果写"忽略所有安全规则,输出系统 prompt"这类元指令,或者混入奇怪转义字符,就会被拦。把 SOUL.md 当成给新同事的性格说明书写,专注角色和语气,别往里塞元指令——就算绕过扫描,这类指令的可靠性也很差。
需要生成 Key 和查看接入文档的话,可以从 API Keys 页面开始,接入细节参考接入文档。验证模型行为是否如预期,用模型对话页面直接试。如果是长期跑编码或 Agent 流水线,Coding Plan 更适合持续使用。