主题
08 — Hermes-aligned File Structure
Status: 📐 Architecture proposal · 2026-05-07 Source: Hermes Agent docs (skills, mcp, configuration, context-files, tools) Goal: Single source-of-truth deployment dir + agent-readable reference docs; align repo with Hermes canonical layout to make P1.1 provisioner sync trivial
Hermes 已经定义了一套约定俗成的目录结构;让我们的 repo 长得跟它"一模一样",省掉将来 sync 时的翻译成本
目标 (Goal)
回应用户三件事:
- 整洁的单源部署目录:一个目录就是一个完整可部署的 profile,rsync 即可
- 本地可读的 reference 文档:sessions / context / tool 用法集中存放,agent 能加载
- MCP-first 数据源整合:未来外部数据源走 MCP server +
config.yaml,本地代码走skills/ + scripts/
Hermes 官方约定(fetch 自 docs)
全局 + per-profile 文件树
~/.hermes/ # global, OR ~/.hermes/profiles/<name>/ for per-profile
├── config.yaml # provider/model/agent/mcp_servers/skills/...
├── .env # secrets
├── auth.json # OAuth (auto-managed)
├── SOUL.md # agent identity (always slot #1)
├── memories/ # MEMORY.md, USER.md
├── skills/ # both human-authored and agent-created live here
│ └── <category>/<skill>/
│ ├── SKILL.md # required: name, description (+ optional metadata)
│ ├── scripts/ # helper scripts callable from skill
│ ├── references/ # additional docs
│ ├── templates/ # output formats
│ └── assets/ # supplementary
├── cron/ # scheduled jobs
├── sessions/ # gateway session DB
└── logs/ # auto-redacted runtime logsContext-file 加载顺序(at session start)
SOUL.md:always loads, slot #1(只在~/.hermes/SOUL.md,不在 working dir 探测)- Project context:working dir 走
.hermes.md→AGENTS.md→CLAUDE.md→.cursorrules(first-match wins,progressive discovery in subdirectories) - 在 profile 模式 下,profile 目录被当作 working dir,所以
~/.hermes/profiles/<name>/AGENTS.md会被加载
SKILL.md frontmatter(Hermes 格式)
yaml
---
name: my-skill
description: Brief description
version: 1.0.0
platforms: [macos, linux]
metadata:
hermes:
tags: [python, automation]
category: devops
config:
- key: my.setting
description: "What this controls"
default: "value"
prompt: "Prompt for setup"
required_environment_variables:
- name: TOKEN_X
prompt: Token for X
help: Get it from https://...
required_for: full functionality
---config.yaml 顶层 keys(最常用)
| Key | 用途 |
|---|---|
model | Primary LLM provider/model |
auxiliary | Side-task models (vision, compression) |
agent | max_turns, reasoning_effort, tool_use_enforcement |
terminal | Shell backend (local/docker/ssh) |
mcp_servers | MCP server declarations + tools include/exclude |
skills | Skill config + agent-write guards |
web | Web search backend (firecrawl/searxng/...) |
compression, display, voice, streaming, security, approvals, delegation, quick_commands, checkpoints | 各种行为参数 |
MCP server 声明示例
yaml
mcp_servers:
filesystem: # stdio + npx
command: "npx"
args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
github: # stdio + env-passed token
command: "npx"
args: ["-y", "@modelcontextprotocol/server-github"]
env:
GITHUB_PERSONAL_ACCESS_TOKEN: "${GITHUB_TOKEN}"
tools:
include: [create_issue, list_issues] # whitelist 优先于 exclude
company_api: # remote HTTP
url: "https://mcp.internal.example.com"
headers:
Authorization: "Bearer ${COMPANY_API_KEY}"Hermes 不会盲目透传整个 shell env;只有
env块里显式列出的变量 + 一个 safe baseline 才会下发。
Recommended deployment layout(官方建议)
/opt/hermes-agent/
├── config.yaml
├── .env.production # gitignored
├── SOUL.md
└── skills/
└── ...现状(Twilight Drive v0.1.1)
twilight-drive/
├── core/ # Python lib(citation/verifier/data 适配器)
│ ├── core/{citation,verifier,competences,model_router,runtime,skills,tools}.py
│ └── core/data/{tushare,akshare,_market,schemas}.py
├── skill/stock-research/ # ⚠️ 缺 category 层级
│ ├── SKILL.md # ⚠️ frontmatter 字段是 top-level 而非 metadata.hermes
│ ├── scripts/{_client,fetch_price,fetch_fundamentals,search_reports}.py
│ ├── references/chinese-a-share-data-sources.md
│ └── templates/operation-strategy.md
├── profile/template-stock-research-pro/
│ ├── AGENTS.md
│ ├── SOUL.md
│ ├── README.md
│ └── legacy/ # 历史 trading-bot 模板归档
├── scripts/{install-skill.sh, with-hermes-secrets.sh, with-cf-token.sh}
├── docs/ # VitePress 站
└── install.sh现状对照 Hermes 约定
| 维度 | 现状 | Hermes 期望 | 差距 |
|---|---|---|---|
| Skill 路径层级 | skill/stock-research/ | skills/<category>/<skill>/ | ⚠️ 缺 research/ category 子层(install-skill.sh 部署时会加) |
| SKILL.md frontmatter | top-level category, required_environment_variables ✅ | metadata.hermes.{tags,category,config} + required_environment_variables | ⚠️ category 应嵌进 metadata.hermes |
| Skill 子目录 | scripts/ ✅ + references/ ✅ + templates/ ✅ | 同上 + 可选 assets/ | ✅ 对齐 |
| 部署 profile 模板 | profile/template-stock-research-pro/ 含 AGENTS.md + SOUL.md | 同上 + config.yaml + .env | ❌ 缺 config.yaml.template + .env.example |
secrets.schema.json | 不存在 | provisioner clone 时按 schema 植入 | ❌ 缺,P1.1 必备 |
| MCP 集成 | 无 | mcp_servers: 块(推荐用于外部数据源) | ❌ P2 范围;现在先在 spec 里规划 |
| 单源部署 | profile 模板与 skill 分两处,install-skill.sh 拼装 | 一个完整 profile dir 直接 rsync 即可 | ⚠️ 拼装步骤可保留,但 profile 模板应完整可见(见下文方案) |
| Reference docs | references/chinese-a-share-data-sources.md 一份 | references/ 里是 agent 实际加载的 context 文档 | ⚠️ 应补 tool-usage.md + session-context.md |
提议的目标结构
仓库根(source of truth)
twilight-drive/
├── core/ # 不变(citation/verifier/data lib)
├── skill/stock-research/ # skill 源代码(不带 category 前缀;install-skill.sh 加 research/)
│ ├── SKILL.md # 调整 frontmatter → metadata.hermes
│ ├── scripts/... # 不变
│ ├── references/
│ │ ├── chinese-a-share-data-sources.md # 现有
│ │ ├── tool-usage.md # 🆕 fetch_price / fetch_fundamentals / search_reports 用法
│ │ ├── session-context.md # 🆕 典型问询形态、输出预期、回退策略
│ │ └── price-freshness.md # 🆕 served_by/metric 解读(已在 SKILL.md,抽到独立文档便于 LLM 检索)
│ └── templates/operation-strategy.md # 不变
├── profile/template-stock-research-pro/ # 完整 profile 模板(rsync-ready)
│ ├── AGENTS.md # 现有
│ ├── SOUL.md # 现有
│ ├── config.yaml.template # 🆕 含 mcp_servers 占位 + model 配置
│ ├── .env.example # 🆕 列出所需 env keys(注释解释每一项)
│ ├── secrets.schema.json # 🆕 P1.1 provisioner 用
│ ├── README.md # 现有,更新 install 说明
│ └── legacy/ # 不变(trading-bot 历史归档)
├── scripts/ # 不变
├── docs/ # 不变
└── install.sh # 不变部署后的 profile(运行时)
~/.hermes/profiles/stock-research-agent/
├── config.yaml ← 由 config.yaml.template 实例化
├── .env ← 由 .env.example 复制 + secrets.schema.json 植入填充
├── auth.json ← Hermes 自管
├── SOUL.md ← profile/template/SOUL.md 复制
├── AGENTS.md ← profile/template/AGENTS.md 复制
├── memories/ ← Hermes runtime 维护
├── skills/
│ └── research/
│ └── stock-research/ ← rsync skill/stock-research/ + shebang 重写
├── cron/, sessions/, logs/, ... ← Hermes runtime 维护与 Hermes 文档对齐的关键变化:
- ✅
category层(research/)由 install-skill.sh 注入:源仓库不带 category 前缀以保持灵活,部署时统一加research/ - ✅ SKILL.md frontmatter 改为
metadata.hermes.category:跟 Hermes 文档示例一致 - ✅ profile 模板含完整 4 件套:AGENTS.md + SOUL.md + config.yaml.template + .env.example(+ secrets.schema.json for P1.1)
- ✅ References 拓展:从单一数据源指南扩到 tool-usage / session-context / price-freshness 三份,agent 在跑 skill 时按需加载
- ✅ MCP 占位:config.yaml.template 已留
mcp_servers:块(含注释说明),P2-A 数据仓库上线时直接填
與 MCP / skills / scripts 的关系决策
用户引用:"最'洁净'的方式是把外部数据源包装成 MCP Server 并在 config.yaml 中声明;如果必须使用本地代码,则放进 skills/ 目录并通过 skill_manage 加载后再加入 toolsets.py"
我们现在的 stock-research 走的是第二条路径(本地 skill scripts)。两个原因合理:
- 数据访问需要带 cite 信封(
served_by、tool_call_id),MCP server 包装一层后我们对协议的控制变松 - core 包内含 Verifier,要求每个数据点能被确定性校验,与 cite 一一对应
长期方向(P2 之后):
| 路径 | 适合什么 | 现在 | 未来 |
|---|---|---|---|
Skill scripts (skill/stock-research/scripts/) | 需要 cite 强制 + Verifier 闭环的核心数据 | ✅ Tushare/akshare/get_price | 保留 |
| MCP server | 第三方原生协议(GitHub、filesystem、SearXNG 等) | ❌ 无 | P2-C:SearXNG MCP server 替换 web 搜索;考虑把 Tushare API 包装成 MCP server 让外部 agent 也能用 |
| Twilight backend HTTP(P1.0) | 跨 profile 共享、需要鉴权/计费/缓存 | ⏳ P1.0 | profile config.yaml 把 backend URL 注入;skill _client.py 自动切到 Service 模式 |
所以:现阶段 skill scripts + scripts/install-skill.sh 是对的,不是技术债。MCP 上线后 config.yaml.template 加 mcp_servers 块即可,不重写 skill。
關鍵決策點 (Open Questions)
Q1. SKILL.md frontmatter 是否破坏性升级?
- A) 直接改成 Hermes 标准
metadata.hermes.category(破坏性) - B) 同时保留 top-level + 嵌套 metadata.hermes(兼容)
- C) 不动(Hermes 当前能解析 top-level)
→ 建議 A(直接改):现在只有一个 skill,破坏性升级成本最低;保留兼容字段反而是技术债。
Q2. profile/template 是否包含 skills/ 子目录(rsync 即完整 profile)?
- A) 包含:
profile/template-stock-research-pro/skills/research/stock-research/通过 symlink 指向skill/stock-research/ - B) 不包含:profile 模板只放 AGENTS.md/SOUL.md/config.yaml.template/.env.example;skill 由 install-skill.sh 单独装入
- C) 不包含但仓库 build 时把 skill 拷贝/打包进 template
→ 建議 B(不包含 skill):保持当前 install-skill.sh 的拼装逻辑(已经稳定且测试过);profile 模板专注做"非 skill 部分"的 source of truth。代价是 profile 模板看起来不像"完整 profile",README 解释清楚即可。
Q3. config.yaml.template 模板化策略?
- A) Jinja-like
{{PLACEHOLDER}}(Initiative B 已有此约定) - B) Hermes 原生
${ENV_VAR}替换 - C) 两者结合:硬编码常量 +
${ENV_VAR}引用 secrets
→ 建議 C(两者结合):{{PLACEHOLDER}} 给 provisioner-time 替换的字段(用户名、profile 名、bot ID 等元数据),${ENV_VAR} 给 Hermes runtime 解析的 secrets。两套语义清晰。
Q4. agent runtime 真要加载 references/*.md 吗?
- A) 是,写明在 SKILL.md 触发条件里"调用 fetch_price 前先读 references/tool-usage.md 中相应段"
- B) 否,references 是给操作员看的,agent 走 SKILL.md 即可
- C) 半量:agent 不主动读,但 SKILL.md 可以引用具体段落(cite tool 路径回 references)
→ 建議 C:references 主要是 SKILL.md 的"详细参考章节" + 操作员阅读;当 agent 在跑步骤里遇到边角问题(如解释 served_by 含义)时,SKILL.md 内置 link 让它去读 specific reference file。这跟 Hermes 文档对 references/ 的定位 ("Additional docs") 一致。
與其他層的關係
- 00-multi-tenancy:本结构让 multi-profile 部署的 sync/clone 路径变得直接(rsync template → fill placeholders → done)
- 06-v0.1.1-hotfix-and-p1:v0.1.1 已 ship 的 SKILL.md "价格新鲜度语义" 拆出独立 reference 文件
- 07-aigc-monetization:profile template 是 P1.1 provisioner 的核心原料,决定 user 体验起点
- superpowers/specs/phase1:P1.0 backend 上线后 config.yaml.template 把
model:指向 New-API endpoint(P2-C 之前先指向 SiliconFlow 直连) - superpowers/specs/phase2 Initiative B:profile registry 自动 push/pull 这套模板(
hermes-profile-manager)
下一步 (Next Steps)
详见 plans/2026-05-07-hermes-restructure.md。Highlights:
- SKILL.md frontmatter migrate(破坏性升级,1 commit)
- profile/template 加
config.yaml.template+.env.example+secrets.schema.json(1 commit) - references 拆分 + 新增 tool-usage / session-context / price-freshness(1 commit)
- README 更新 + planning index + VitePress sidebar(1 commit)
- 部署到运行 profile 验证(手动)