提示词组装
Hermes 刻意将以下两部分分开处理:
- 已缓存的系统提示词状态
- API 调用时的临时追加内容
这是项目中最重要的设计决策之一,因为它影响着:
- Token 用量
- 提示词缓存的有效性
- 会话连续性
- 记忆准确性
主要相关文件:
run_agent.pyagent/prompt_builder.pytools/memory_tool.py
已缓存的系统提示词层级
已缓存的系统提示词按大致如下顺序组装:
- Agent 身份 — 优先使用
HERMES_HOME中的SOUL.md,否则回退到prompt_builder.py中的DEFAULT_AGENT_IDENTITY - 工具感知行为指导
- Honcho 静态块(启用时)
- 可选系统消息
- 冻结的 MEMORY 快照
- 冻结的 USER 个人资料快照
- 技能索引
- 上下文文件(
AGENTS.md、.cursorrules、.cursor/rules/*.mdc)——当 SOUL.md 已在第 1 步作为身份加载时,此处不再包含它 - 时间戳 / 可选会话 ID
- 平台提示
当设置了 skip_context_files(例如子 Agent 委托场景)时,SOUL.md 不会被加载,而是使用硬编码的 DEFAULT_AGENT_IDENTITY。
具体示例:组装后的系统提示词
以下是所有层级都存在时,最终系统提示词的简化示意(注释说明每个部分的来源):
# Layer 1: Agent Identity (from ~/.hermes/SOUL.md)
You are Hermes, an AI assistant created by Nous Research.
You are an expert software engineer and researcher.
You value correctness, clarity, and efficiency.
...
# Layer 2: Tool-aware behavior guidance
You have persistent memory across sessions. Save durable facts using
the memory tool: user preferences, environment details, tool quirks,
and stable conventions. Memory is injected into every turn, so keep
it compact and focused on facts that will still matter later.
...
When the user references something from a past conversation or you
suspect relevant cross-session context exists, use session_search
to recall it before asking them to repeat themselves.
# Tool-use enforcement (for GPT/Codex models only)
You MUST use your tools to take action — do not describe what you
would do or plan to do without actually doing it.
...
# Layer 3: Honcho static block (when active)
[Honcho personality/context data]
# Layer 4: Optional system message (from config or API)
[User-configured system message override]
# Layer 5: Frozen MEMORY snapshot
## Persistent Memory
- User prefers Python 3.12, uses pyproject.toml
- Default editor is nvim
- Working on project "atlas" in ~/code/atlas
- Timezone: US/Pacific
# Layer 6: Frozen USER profile snapshot
## User Profile
- Name: Alice
- GitHub: alice-dev
# Layer 7: Skills index
## Skills (mandatory)
Before replying, scan the skills below. If one clearly matches
your task, load it with skill_view(name) and follow its instructions.
...
<available_skills>
software-development:
- code-review: Structured code review workflow
- test-driven-development: TDD methodology
research:
- arxiv: Search and summarize arXiv papers
</available_skills>
# Layer 8: Context files (from project directory)
# Project Context
The following project context files have been loaded and should be followed:
## AGENTS.md
This is the atlas project. Use pytest for testing. The main
entry point is src/atlas/main.py. Always run `make lint` before
committing.
# Layer 9: Timestamp + session
Current time: 2026-03-30T14:30:00-07:00
Session: abc123
# Layer 10: Platform hint
You are a CLI AI Agent. Try not to use markdown but simple text
renderable inside a terminal.
SOUL.md 在提示词中的位置
SOUL.md 存放于 ~/.hermes/SOUL.md,作为 Agent 的身份标识——也是系统提示词的最开头部分。prompt_builder.py 中的加载逻辑如下:
# From agent/prompt_builder.py (simplified)
def load_soul_md() -> Optional[str]:
soul_path = get_hermes_home() / "SOUL.md"
if not soul_path.exists():
return None
content = soul_path.read_text(encoding="utf-8").strip()
content = _scan_context_content(content, "SOUL.md") # Security scan
content = _truncate_content(content, "SOUL.md") # Cap at 20k chars
return content
当 load_soul_md() 返回内容时,它会替换硬编码的 DEFAULT_AGENT_IDENTITY。随后调用 build_context_files_prompt() 时传入 skip_soul=True,以防止 SOUL.md 出现两次(一次作为身份,一次作为上下文文件)。
若 SOUL.md 不存在,系统将回退到以下内容:
You are Hermes Agent, an intelligent AI assistant created by Nous Research.
You are helpful, knowledgeable, and direct. You assist users with a wide
range of tasks including answering questions, writing and editing code,
analyzing information, creative work, and executing actions via your tools.
You communicate clearly, admit uncertainty when appropriate, and prioritize
being genuinely useful over being verbose unless otherwise directed below.
Be targeted and efficient in your exploration and investigations.
上下文文件的注入方式
build_context_files_prompt() 使用优先级系统——只加载一种项目上下文类型(先匹配先用):
# From agent/prompt_builder.py (simplified)
def build_context_files_prompt(cwd=None, skip_soul=False):
cwd_path = Path(cwd).resolve()
# Priority: first match wins — only ONE project context loaded
project_context = (
_load_hermes_md(cwd_path) # 1. .hermes.md / HERMES.md (walks to git root)
or _load_agents_md(cwd_path) # 2. AGENTS.md (cwd only)
or _load_claude_md(cwd_path) # 3. CLAUDE.md (cwd only)
or _load_cursorrules(cwd_path) # 4. .cursorrules / .cursor/rules/*.mdc
)
sections = []
if project_context:
sections.append(project_context)
# SOUL.md from HERMES_HOME (independent of project context)
if not skip_soul:
soul_content = load_soul_md()
if soul_content:
sections.append(soul_content)
if not sections:
return ""
return (
"# Project Context\n\n"
"The following project context files have been loaded "
"and should be followed:\n\n"
+ "\n".join(sections)
)
上下文文件发现详情
| 优先级 | 文件 | 搜索范围 | 说明 |
|---|---|---|---|
| 1 | .hermes.md、HERMES.md | 从 CWD 向上到 git 根目录 | Hermes 原生项目配置 |
| 2 | AGENTS.md | 仅 CWD | 通用 Agent 指令文件 |
| 3 | CLAUDE.md | 仅 CWD | Claude Code 兼容性 |
| 4 | .cursorrules、.cursor/rules/*.mdc | 仅 CWD | Cursor 兼容性 |
所有上下文文件均会经过:
- 安全扫描 — 检测提示词注入模式(不可见 Unicode、"ignore previous instructions"、凭证窃取尝试)
- 截断处理 — 以 70/20 的头尾比例截取,上限 20,000 字符,并添加截断标记
- 去除 YAML frontmatter —
.hermes.md的 frontmatter 会被移除(保留给未来的配置覆盖功能)
仅在 API 调用时注入的层
以下内容有意不作为已缓存系统提示词的一部分持久化:
ephemeral_system_prompt(临时系统提示词)- 预填充消息(prefill messages)
- 网关派生的会话上下文覆盖层
- 在当前轮次用户消息中注入的 Honcho 后续召回内容
这种分离确保稳定前缀保持稳定,从而有利于缓存命中。
记忆快照
本地记忆和用户个人资料数据在会话开始时以冻结快照的形式注入。会话中途的写入操作会更新磁盘状态,但不会改变已构建的系统提示词,直到新会话开始或强制重建时才会生效。
上下文文件
agent/prompt_builder.py 使用优先级系统扫描并净化项目上下文文件——只加载一种类型(先匹配先用):
.hermes.md/HERMES.md(从 CWD 向上遍历到 git 根目录)AGENTS.md(启动时的 CWD;子目录在会话过程中通过agent/subdirectory_hints.py逐步发现)CLAUDE.md(仅 CWD).cursorrules/.cursor/rules/*.mdc(仅 CWD)
SOUL.md 通过 load_soul_md() 单独加载,用于身份插槽。加载成功后,build_context_files_prompt(skip_soul=True) 会防止其出现两次。
长文件在注入前会被截断。
技能索引
当技能工具可用时,技能系统会向提示词贡献一份紧凑的技能索引。
支持的提示词自定义接入点
大多数用户应将 agent/prompt_builder.py 视为实现代码,而非配置接入点。推荐的自定义路径是修改 Hermes 已加载的提示词输入,而不是直接编辑 Python 模板。
优先使用这些接入点
~/.hermes/SOUL.md— 用您自己的 Agent 角色设定和固定行为替换内置的默认身份块。~/.hermes/MEMORY.md和~/.hermes/USER.md— 提供持久化的跨会话事实和用户个人资料数据,在新会话开始时以快照形式注入。- 项目上下文文件,如
.hermes.md、HERMES.md、AGENTS.md、CLAUDE.md或.cursorrules— 注入仓库特定的工作规范。 - 技能(Skills)— 打包可复用的工作流和参考资料,无需编辑核心提示词代码。
- 可选的系统提示词配置 / API 覆盖 — 添加部署特定的指令文本,无需 fork Hermes。
- 临时覆盖层,如
HERMES_EPHEMERAL_SYSTEM_PROMPT或预填充消息 — 添加仅限当前轮次的指导,该内容不应成为已缓存提示词前缀的一部分。
何时需要直接修改代码
仅当您正在维护 fork 或向上游贡献行为变更时,才编辑 agent/prompt_builder.py。该文件为每次会话组装提示词的管道结构、缓存边界和注入顺序。直接修改该文件属于全局产品变更,而非每用户的提示词自定义。
换言之:
- 如果您想要不同的助手身份,编辑
SOUL.md - 如果您想要不同的仓库规则,编辑项目上下文文件
- 如果您想要可复用的操作流程,添加或修改技能
- 如果您想改变 Hermes 对所有人组装提示词的方式,修改 Python 代码并将其视为代码贡献
为何采用这种提示词组装方式
这种架构经过刻意优化,以实现:
- 保留提供商侧的提示词缓存
- 避免不必要地改变历史记录
- 保持记忆语义的可理解性
- 允许网关/ACP/CLI 追加上下文,而不污染持久化的提示词状态