乐于分享
好东西不私藏

Hermes Agent 架构设计文档

Hermes Agent 架构设计文档

点击下方”坍缩与扩张”,选择“加为星标

优质文章,第一时间送达!

版本: 基于 2026-05-30 源码分析目: NousResearch/hermes-agent规模: ~435K 行生产代码 (不含测试), ~900 测试文件, ~17K 测试用例


目录

  1. 概述与设计目标
  2. 分层架构总览
  3. 核心执行引擎
  4. 工具系统
  5. 多入口系统 (CLI / Gateway / TUI / ACP)
  6. 会话与持久化
  7. 记忆系统 (Memory)
  8. Provider 适配层
  9. 认证与凭证池
  10. 上下文压缩
  11. 安全与护栏
  12. 插件系统
  13. 定时任务 (Cron)
  14. Skill 系统与 Curator
  15. Kanban 多 Agent 协作
  16. 关键设计决策与权衡

1. 概述与设计目标

Hermes Agent 是 Nous Research 开发的开源 AI Agent 框架。与 Anthropic Claude Code、OpenAI Codex CLI 属于同一品类,但具有以下差异化设计目标:

设计目标
实现手段
Provider 无关
20+ LLM Provider 通过 adapter 模式统一接入
自改进
Skill 系统 + Curator 让 Agent 从经验中学习
跨 session 持久记忆
SQLite FTS5 存储 + 可插拔 Memory Backend
多平台消息
Gateway 支持 17+ 即时通讯平台
可扩展
插件系统 + MCP 协议 + 自定义 Toolset
容错
Fallback 链 + Credential Pool 轮换 + 重试退避

2. 分层架构总览

┌──────────────────────────────────────────────────────────────────┐│                         入口 / 表示层                              ││  ┌──────────┐  ┌──────────────┐  ┌──────────┐  ┌─────────────┐  ││  │  cli.py  │  │  gateway/run │  │ ui-tui/  │  │ acp_adapter │  ││  │(15K LOC) │  │   .py (网关) │  │(Ink TUI) │  │  (IDE集成)   │  ││  └────┬─────┘  └──────┬───────┘  └────┬─────┘  └──────┬──────┘  ││       │               │               │               │         │├───────┴───────────────┴───────────────┴───────────────┴─────────┤│                     Agent 核心执行层                               ││  ┌─────────────────────────────────────────────────────────────┐  ││  │            run_agent.py: AIAgent (~4.5K LOC)                 │  ││  │  ┌─────────────────────────────────────────────────────────┐│  ││  │  │ agent/conversation_loop.py: run_conversation() (~4.6K) ││  ││  │  │  ┌──────────────┐ ┌──────────────┐ ┌────────────────┐ ││  ││  │  │  │ LLM API Call │→│ Tool Dispatch│→│ Result → Loop  │ ││  ││  │  │  │  (streaming) │ │(parallel/seq)│ │  (max 90 iter) │ ││  ││  │  │  └──────────────┘ └──────────────┘ └────────────────┘ ││  ││  │  └─────────────────────────────────────────────────────────┘│  ││  └─────────────────────────────────────────────────────────────┘  ││                                                                   ││  ┌──────────────┐ ┌──────────────┐ ┌──────────────────────────┐  ││  │prompt_builder│ │   context    │ │   memory_manager         │  ││  │ (系统提示词) │ │ _compressor  │ │   (记忆编排)             │  ││  └──────────────┘ └──────────────┘ └──────────────────────────┘  │├───────────────────────────────────────────────────────────────────┤│                      工具编排层                                    ││  ┌─────────────────────────────────────────────────────────────┐  ││  │  model_tools.py (1K LOC): get_tool_definitions / dispatch   │  ││  │  tools/registry.py: Central Registry (自注册 + 自动发现)     │  ││  │  toolsets.py: Toolset 组合与继承                              │  ││  └─────────────────────────────────────────────────────────────┘  ││                                                                   ││  ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌───────────────┐  ││  │ terminal   │ │file_tools  │ │web_tools   │ │browser_tool   │  ││  │  (shell)   │ │(read/write │ │(web_search,│ │(CDP/Puppeteer)│  ││  │            │ │ /patch)    │ │ web_extract)│ │               │  ││  ├────────────┤ ├────────────┤ ├────────────┤ ├───────────────┤  ││  │delegate    │ │vision      │ │session     │ │skill_manage   │  ││  │_task       │ │_analyze    │ │_search     │ │               │  ││  └────────────┘ └────────────┘ └────────────┘ └───────────────┘  ││  ... 70+ tools in tools/ directory                                │├───────────────────────────────────────────────────────────────────┤│                      基础支撑层                                    ││  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────┐ ││  │ Provider │ │ 插件系统  │ │  Session │ │ 安全/    │ │  Log  │ ││  │ Adapters │ │ plugins/ │ │  Store   │ │ 护栏     │ │  ging │ ││  │ (20+)    │ │ (11模块) │ │ state.db │ │          │ │       │ ││  └──────────┘ └──────────┘ └──────────┘ └──────────┘ └────────┘ │├───────────────────────────────────────────────────────────────────┤│                      持久化存储                                    ││  ┌───────────────────┐  ┌──────────────────┐                     ││  │ ~/.hermes/state.db│  │ ~/.hermes/       │                     ││  │ (SQLite + FTS5)   │  │ config.yaml + .env│                    ││  │ Sessions/Messages │  │ (配置 + 密钥)     │                    ││  └───────────────────┘  └──────────────────┘                     │└───────────────────────────────────────────────────────────────────┘

模块依赖链

tools/registry.py  (零依赖 — 被所有工具文件导入)       ↑tools/*.py  (每个文件 import 时调用 registry.register())       ↑model_tools.py  (导入所有工具模块,触发自动注册)       ↑run_agent.py, cli.py, batch_runner.py, gateway/run.py

3. 核心执行引擎

3.1 AIAgent 类 (run_agent.py)

AIAgent 是系统的核心类,构造参数约 60+,覆盖 credentials、routing、callbacks、session context 等全维度。核心参数:

classAIAgent:def__init__(self,        base_url: str,           # LLM API endpoint        api_key: str,            # 认证密钥        provider: str,           # provider 标识 (openrouter, anthropic, ...)        api_mode: str,           # "chat_completions" | "codex_responses" | ...        model: str,              # 模型名        max_iterations: int=90,  # 最大工具调用迭代次数        enabled_toolsets: list,  # 启用的工具集        session_id: str,         # 会话 ID        credential_pool,         # 多凭证池        fallback_model: dict,    # 降级模型配置        iteration_budget,        # 迭代预算        ...    )

3.2 对话循环 (agent/conversation_loop.py)

这是整个系统的「心脏」,约 4600 行,函数 run_conversation() 驱动一个完整的用户 turn。核心流程:

run_conversation(agent, user_message)├─ 1. 前置准备│   ├─ _install_safe_stdio()        # 防止 broken pipe 崩溃│   ├─ agent._ensure_db_session()   # 确保 session 记录在 DB 中│   ├─ set_runtime_main(p, m)       # 通知 auxiliary_client 当前主模型│   ├─ set_session_context(sid)     # 设置日志 session 上下文│   ├─ _sanitize_surrogates()       # 清理 Unicode surrogate 字符│   └─ _restore_or_build_system_prompt()  # 恢复缓存/重新构建系统提示词├─ 2. 构建消息列表│   ├─ 系统提示词 (prompt_builder 组装)│   ├─ Memory 上下文 (prefetch_all)│   ├─ conversation_history (前序对话)│   └─ 用户消息 (新输入)├─ 3. 核心循环 (while api_call_count < max_iterations)│   ││   ├─ _interruptible_api_call(client, messages, tools)│   │   ├─ 构建 API 请求 (messages + tool schemas)│   │   ├─ 流式/非流式调用 LLM│   │   └─ 返回 response (tool_calls 列表 或 text)│   ││   ├─ 如果是 tool_calls:│   │   ├─ _should_parallelize_tool_batch()  # 并行度判断│   │   ├─ ThreadPoolExecutor (max 8 workers)│   │   │   └─ 每个 tool_call → handle_function_call()│   │   │       └─ registry.dispatch() → 具体 handler│   │   ├─ 结果追加到 messages[]│   │   └─ api_call_count++│   ││   ├─ 如果是 text: → 返回 final_response│   ││   ├─ 上下文压缩检查:│   │   ├─ estimate_messages_tokens_rough()│   │   └─ 超阈值 → context_compressor.compress()│   ││   └─ 中断检查:│       ├─ 用户 /stop, /new│       └─ IterationBudget.remaining <= 0├─ 4. 后处理│   ├─ 保存到 state.db (SessionDB)│   ├─ Usage/cost 统计│   ├─ Background memory sync│   ├─ Background skill review (Curator)│   └─ Gateway 投递 (如果是消息平台)└─ 返回 dict: {"final_response": str, "messages": [...], "usage": {...}}

3.3 中断机制

Agent loop 支持优雅中断:

  • _interrupt_requested 标志:由 /stop 命令或用户新消息触发
  • Budget 保护IterationBudget 追踪剩余迭代,用尽时停止
  • 一 turn 宽限期 (_budget_grace_call):budget 耗尽后仍允许一次 final API call 让模型输出文字而非截断在 tool call 中间

3.4 Fallback 链

当主 Provider/Model 调用失败时触发:

主模型失败  ↓classify_api_error() → FailoverReason  ↓┌─ Rate Limit (429) → 等待 retry-after / jittered backoff├─ Auth Error (401)  → Token 过期 → credential_pool.rotate()├─ Context Overflow  → 触发压缩,重试├─ Service Unavailable (503) → jittered backoff 重试└─ 所有重试耗尽 → 切换到 fallback_model

4. 工具系统

4.1 注册中心 (tools/registry.py)

核心数据结构 _tool_registry 存储所有已注册工具:

_registry: Dict[str, ToolEntry] = {"terminal": ToolEntry(        name="terminal",        toolset="terminal",        schema={...},           # OpenAI function-calling schema        handler=handler_fn,     # 实际执行函数        check_fn=check_fn,      # 可用性检查        requires_env=["SOME_KEY"],        ...    ),    ...}

自动发现机制 (discover_builtin_tools):

  1. 扫描 tools/ 目录下所有 .py 文件
  2. 用 AST 静态分析 (_module_registers_tools) 判断文件是否调用 registry.register()
  3. 仅 import 包含注册调用的模块 — 避免 import 无关模块
  4. import 触发模块级 registry.register() 调
  1. 用 → 工具注册完成
def_module_registers_tools(module_path: Path) -> bool:"""静态 AST 分析,不需要实际执行模块"""    source = module_path.read_text()    tree = ast.parse(source)# 检查顶层语句中是否有 registry.register() 调用return any(_is_registry_register_call(stmt) for stmt in tree.body)

4.2 工具分发 (model_tools.py)

handle_function_call() 是工具执行的统一入口:

defhandle_function_call(function_name, function_args, task_id, user_task):# 1. 查找注册的工具    tool = registry.get(function_name)# 2. 检查权限/护栏    guardrail_decision = toolguard_check(function_name, function_args)if guardrail_decision == ToolGuardrailDecision.BLOCK:return synthetic_error_result# 3. 异步桥接 (主线程用持久化 loop, worker 线程用 thread-local loop)if asyncio.iscoroutinefunction(tool.handler):        result = _run_async_safe(tool.handler(args))else:        result = tool.handler(args)# 4. 大结果截断 + 文件存储if len(result) > MAX_INLINE_RESULT:        result = store_to_temp_file(result)return result

4.3 并行工具执行

_should_parallelize_tool_batch() 判断是否可并行:

  • 检查文件路径冲突:两个 write_file 或 patch 不能同时操作同一文件
  • 检查 terminal 互斥:多个 terminal 不能同时执行(共享 shell 状态)
  • idempotent 操作read_filesearch_filesweb_search)始终可并行
  • 最大并发数:8 workers (ThreadPoolExecutor)

4.4 工具集 (toolsets.py)

_HERMES_CORE_TOOLS = ["web_search""web_extract",      # Web"terminal""process",             # Shell"read_file""write_file",         # 文件"patch""search_files","vision_analyze""image_generate"# 视觉"skills_list""skill_view",       # 技能"skill_manage","browser_navigate""browser_*",   # 浏览器 (CDP)"text_to_speech""todo""memory","session_search""clarify","execute_code""delegate_task","cronjob""send_message",]

工具集支持组合继承:例如 "full_stack" = _HERMES_CORE_TOOLS + ["spotify", "homeassistant"]


5. 多入口系统

5.1 CLI (cli.py + hermes_cli/)

技术栈: prompt_toolkit (输入) + Rich (渲染) + KawaiiSpinner (动画)

hermes chat → main.py → HermesCLI.__init__()                          ├─ prompt_toolkit Application                          ├─ autocomplete (SlashCommandCompleter)                          ├─ history (FileHistory)                          ├─ skin engine (hermes_cli/skin_engine.py)                          └─ process_command() → Slash 命令分发

Slash 命令中心注册表 (hermes_cli/commands.py):

@dataclass(frozen=True)classCommandDef:    name: str              # 规范名: "background"    description: str       # 描述    category: str          # "Session", "Configuration", ...    aliases: tuple = ()    # 别名: ("bg",)    args_hint: str = ""# 参数占位符    subcommands: tuple = ()    cli_only: bool = False    gateway_only: bool = FalseCOMMAND_REGISTRY: List[CommandDef] = [...]

设计原则: 所有消费者 (CLI help, Gateway dispatch, Telegram BotCommands, Slack 映射, autocomplete) 从这个唯一注册表派生数据。

5.2 Gateway (gateway/run.py)

多平台消息网关,约 17+ 平台适配器:

gateway/platforms/├── telegram.py, discord.py, slack.py        # 主流 IM├── whatsapp.py, signal.py, matrix.py         # 加密 IM├── feishu.py, dingtalk.py, wecom.py, weixin.py  # 中国平台├── email.py, sms.py                          # 传统消息├── bluebubbles.py (iMessage)                 # Apple├── homeassistant.py                          # 智能家居├── webhook.py, api_server.py                 # HTTP└── yuanbao.py                                # 元宝

Gateway Session 管理:

  • Agent 缓存: LRU cache + idle TTL (1小时) 避免重复创建 AIAgent
  • Session 路由: 基于 (platform, user_id, chat_id) 的 session key 映射
  • PII 脱敏: 可选的 privacy.redact_pii 配置,hash 用户 ID
  • Session Reset 策略: 可配置的自动重置逻辑(按时间/消息数)

5.3 TUI (ui-tui/ + tui_gateway/)

  • 前端: Ink (React for terminal) — ui-tui/src/entry.tsx
  • 后端: Python JSON-RPC server — tui_gateway/server.py
  • 通信: WebSocket transport

5.4 ACP Adapter (acp_adapter/)

IDE 集成(VS Code / Zed / JetBrains),实现 ACP (Agent Communication Protocol):

  • server.py — ACP 服务器
  • session.py — Session 管理
  • tools.py — 工具适配

6. 会话与持久化

6.1 SessionDB (hermes_state.py)

SQLite 数据库 (~/.hermes/state.db),Schema v14:

┌─────────────────────────────────────────────────┐│                     state.db                    │├─────────────────────────────────────────────────┤│  sessions                                       ││  ├─ session_id (TEXT PK)                        ││  ├─ title (TEXT)                                ││  ├─ source (TEXT)  # "cli", "telegram", ...     ││  ├─ platform (TEXT)                             ││  ├─ user_id (TEXT)                              ││  ├─ system_prompt (TEXT)  # 缓存,支持 prefix   ││  │   cache 复用                                  ││  ├─ parent_session_id (TEXT)  # 压缩分裂链       ││  └─ created_at, updated_at (TIMESTAMP)          ││                                                 ││  messages                                       ││  ├─ message_id (INTEGER PK)                     ││  ├─ session_id (FK → sessions)                  ││  ├─ role (TEXT)  # user/assistant/tool/system   ││  ├─ content (TEXT)                              ││  ├─ tool_calls (JSON)                           ││  └─ timestamp (TEXT)                            ││                                                 ││  fts_messages (FTS5 虚拟表)                     ││  └─ content (全文索引)                           ││                                                 ││  models (session 使用的 model 配置)              ││  ├─ session_id (FK)                             ││  ├─ provider, model, base_url                   ││  └─ context_length                              │└─────────────────────────────────────────────────┘

设计要点:

  1. WAL 模式: 支持并发读取 + 单写入者
  2. NFS 兼容: 在 NFS/SMB 等不支持 WAL 的文件系统上自动降级到 DELETE journal 模式
  3. System Prompt 缓存: 将 system prompt 持久化到 DB,跨 turn 复用(减少 token、加速 prefix cache 命中)
  4. 压缩分裂链: 压缩触发新 session 创建,通过 parent_session_id 链追溯

7. 记忆系统 (Memory)

7.1 MemoryManager (agent/memory_manager.py)

MemoryManager├─ builtin_memory_provider       # 内置 (默认)│   ├─ MEMORY.md (用户笔记)│   └─ USER.md (用户 profile)├─ 外部插件 (可选其一)│   ├─ honcho_provider│   ├─ mem0_provider│   └─ supermemory_provider└─ 上下文注入    ├─ build_system_prompt()  # 嵌入系统提示词    ├─ prefetch_all(msg)      # Turn 前检索相关记忆    └─ sync_all()             # Turn 后保存新记忆

设计约束:

  • 同一时间只允许一个外部 memory provider(防止 schema 膨胀和冲突)
  • Memory 内容用 <memory-context> 标签包裹,注入系统提示词
  • sanitize_context() 过滤标签
  • 和内部注释,防止记忆内容挟持 prompt

7.2 记忆生命周期

User Turn 开始  ├─ prefetch_all(user_message) → 检索相关记忆  ├─ build_system_prompt() → 注入到系统提示词  └─ [Agent 运行,可使用 memory tool]User Turn 结束  ├─ sync_all(user_msg, assistant_response) → 保存对话要点  └─ queue_prefetch_all() → 异步预取下一轮记忆

8. Provider 适配层

8.1 适配器架构

                        run_agent.py: AIAgent                               │                  ┌────────────┼────────────┐                  │            │            │            chat_completions  codex_      native               (OpenAI API)  responses   adapters                  │            │            │          ┌───────┴───────┐    │    ┌───────┴───────┐          │ OpenRouter    │    │    │ Anthropic      │          │ OpenAI        │    │    │ Bedrock        │          │ DeepSeek      │    │    │ Gemini Native  │          │ Grok/xAI      │    │    │ Moonshot       │          │ HuggingFace   │    │    │                │          │ GLM, MiniMax  │    │    │                │          │ Kimi, Qwen    │    │    │                │          │ 自定义 endpoint│    │    │                │          └───────────────┘    │    └───────────────┘                               │                        Codex Responses                        (OpenAI Codex CLI)

8.2 适配器职责

  1. API 格式转换: 不同 provider 的 message role、tool call 格式、reasoning 内容位置各不相同
  2. Schema 翻译: e.g. Gemini 不支持 strict 参数,gemini_schema.py 做降级处理
  3. Reasoning 提取: Anthropic 的 thinking、DeepSeek 的 reasoning_content 统一提取到assistant_msg[“reasoning”]
  4. Prompt Caching: Anthropic 的 cache_control breakpoints 由 agent/prompt_caching.py 自动注入
  5. Streaming 统一: 不同 provider 的 streaming delta 格式统一为 OpenAI 兼容格式

8.3 关键适配器

适配器
文件
要点
Anthropic
anthropic_adapter.py
cache_control, thinking blocks, 260K context
Bedrock
bedrock_adapter.py
AWS SigV4 签名, streaming
Gemini Native
gemini_native_adapter.py
Schema 降级, Google OAuth
Codex Responses
codex_responses_adapter.py
Codex CLI 协议, OAuth token
Copilot ACP
copilot_acp_client.py
GitHub Copilot ACP 协议

9. 认证与凭证池

9.1 CredentialPool (agent/credential_pool.py)

支持多个 API Key 池化 + 自动轮换:

CredentialPool(provider="openrouter")├─ entries: List[CredentialEntry]│   ├─ api_key: str│   ├─ status: "ok" | "exhausted" | "dead" | "expired"│   ├─ exhausted_at: datetime | None│   ├─ cooldown_until: datetime | None│   └─ rate_limit_info: dict├─ rotate() → CredentialEntry    # 切换到下一个可用凭证├─ mark_exhausted(entry)          # 标记凭证耗尽├─ mark_dead(entry)               # 标记永久失效└─ recover_exhausted_entries()    # cooldown 过期后恢复

9.2 凭证生命周期

OK ──(429/rate limit)──→ EXHAUSTED ──(cooldown expired)──→ OK  │                          │  └──(401/invalid token)──→ DEAD (永久移出池)

9.3 凭证来源

  • hermes_cli/auth.py: OAuth 流程 (Nous Portal, OpenAI Codex, Qwen)
  • agent/credential_sources.py: 环境变量、配置文件
  • agent/google_oauth.py: Google Cloud OAuth
  • auth.json: 持久化存储 OAuth tokens + 凭证池状态

10. 上下文压缩

10.1 ContextCompressor (agent/context_compressor.py)

当 token 估算超过阈值时自动触发上下文压缩:

compress(messages, agent):  1. 估算当前总 token  2. 如果 < threshold → 跳过  3. 如果 > threshold:     a. 保留 head (系统提示词 + 前几轮)     b. 保留 tail (最近 N token, 由 token budget 决定)     c. 压缩 middle:        ├─ 低成本预裁剪 (删除长 tool output)        ├─ 调用 auxiliary LLM 生成结构化摘要        │   ├─ ## Active Task        │   ├─ ## Completed Actions        │   ├─ ## Key Decisions        │   ├─ ## Pending User Asks        │   └─ ## Remaining Work        └─ 将摘要插入为 [CONTEXT COMPACTION...] 前缀消息  4. 迭代更新: 压缩多次时保留前次摘要,增量更新

关键设计:

  • 摘要预算 = 压缩内容的 20%,有绝对上限 (ceiling)
  • Filter-safe preamble: 告知模型摘要仅供参考,非活动指令
  • “Remaining Work” 代替 “Next Steps” (避免被误读为指令)

10.2 压缩配置

compression:enabled:truethreshold:0.50# 达到 context window 50% 时触发target_ratio:0.20# 压缩到 20%

11. 安全与护栏

11.1 Tool Guardrails (agent/tool_guardrails.py)

纯函数护栏,无副作用:

IDEMPOTENT_TOOLS = frozenset({"read_file""search_files""web_search", ...})MUTATING_TOOLS = frozenset({"terminal""write_file""patch""execute_code", ...})
  • 重复变异检测: 同一 turn 内同一操作重复执行时插入警告指导
  • 文件冲
  • 突检测_paths_overlap() 检查并行工具是否操作同一文件
  • 命令审批_is_destructive_command() 判断是否需用确认

11.2 安全配置

approvals:mode:manual# manual | smart | offsecurity:redact_secrets:true# 脱敏工具输出中的密钥tirith_enabled:true# 额外安全层privacy:redact_pii:true# Gateway 中 hash 用户 ID

11.3 注入防御

tools/threat_patterns.py 定义注入检测规则,应用于:

  • Context 文件扫描 (AGENTS.md.cursorrules)
  • Memory 内容扫描
  • Skill 内容扫描
  • Tool output delimiter 系统

12. 插件系统

12.1 插件类型

plugins/├── memory/           # 记忆后端 (honcho, mem0, supermemory)├── model-providers/  # 推理后端 (openrouter, anthropic, gmi, ...)├── image_gen/        # 图像生成 (DALL-E, Stable Diffusion, ...)├── video_gen/        # 视频生成├── browser/          # 浏览器自动化├── observability/    # 指标/追踪/日志├── spotify/          # Spotify 集成├── kanban/           # 多 Agent 看板├── context_engine/   # 上下文引擎├── teams_pipeline/   # Teams 集成├── hermes-achievements/  # 成就系统└── ...

12.2 插件发现

hermes_cli/plugins.py::discover_plugins() 扫描:

  1. 内置插件hermes-agent/plugins/
  2. 用户插件~/.hermes/plugins/
  3. 项目插件<project>/.hermes/plugins/
  4. pip 安装的插件: entry point hermes_plugins

12.3 插件接口

插件通过注册以下之一来扩展系统:

  • Tools: 调用 registry.register()
  • Memory Providers: 实现 MemoryProvider 接口
  • Model Providers: 注册到 provider 注册表
  • Hooks: 注册 Gateway hook

13. 定时任务 (Cron)

13.1 架构

cron/├── scheduler.py    # 调度引擎│   ├─ Tick 循环 (基于 schedule 解析)│   ├─ .tick.lock 文件防重 (多进程互斥)│   ├─ 3-min 硬中断 (防止 runaway job)│   └─ skip_memory=True (cron session 默认不加载记忆)└── jobs.py         # Job 定义    ├─ 调度表达式 ("30m""every 2h""0 9 * * *")    ├─ Prompt + Skills 绑定    ├─ 模型覆盖    ├─ Script 预处理 (no_agent=True 时 script 本身即 job)    ├─ context_from (job 输出链)    └─ 多平台投递

13.2 Job 类型

类型
说明
LLM-driven

 (默认)
Agent 执行 prompt,推理+工具调用
Script-only

 (no_agent=True)
纯脚本输出,零 token 消耗
Chained

 (context_from)
Job A 的输出注入 Job B 的上下文

14. Skill 系统与 Curator

14.1 Skill 文件结构

~/.hermes/skills/├── autonomous-ai-agents/│   └── hermes-agent/SKILL.md├── creative/│   └── ascii-art/SKILL.md└── ...SKILL.md:---name: hermes-agentdescription: "Configure, extend, or contribute to Hermes Agent."version: 2.1.0tags: [hermes, setup, configuration]---# Skill Content (Markdown)

14.2 Skill 分发机制

# agent/prompt_builder.pydefbuild_skills_index(skills_dirs, disabled_skills, platform):"""扫描所有 skill 目录,构建可用 skill 索引"""for skill_path in iter_skill_index_files(skills_dirs):        frontmatter = parse_frontmatter(skill_path)if skill_matches_platform(frontmatter, platform):# 提取 skill 名称、描述、触发条件# 注入系统提示词的 <available_skills> 块

Skills 通过 User Message 加载(非 system prompt),以保护 prompt caching。

14.3 Curator (agent/curator.py)

技能生命周期自动化管理:

Curator 周期 (可配置 interval)├─ 扫描 agent-created skills├─ 追踪使用 (sidecar ~/.hermes/skills/.usage.json)│   ├─ use_count, view_count, patch_count│   ├─ last_activity_at│   └─ state (active/stale/archived)├─ 自动归档: stale → archive (days 可配)├─ 自动备份: tar.gz pre-run backup└─ 保护:    ├─ Pinned skills 永不自动变更    ├─ Bundled + hub-installed skills 不可触    └─ 最大破坏性操作 = archive (永不删除)

15. Kanban 多 Agent 协作

15.1 架构

kanban/├─ kanban_db.py      # SQLite Board 存储├─ dispatcher        # Gateway 内运行│   ├─ 回收过期 claims│   ├─ 提升 ready 任务│   ├─ 原子 claim│   └─ spawn worker (指定 profile)└─ worker (独立进程)    └─ HERMES_KANBAN_TASK env → 限定 kanban_* toolset

15.2 隔离模型

  • Board: 硬边界 (workers 通过 HERMES_KANBAN_BOARD env 限定)
  • Tenant: 软命名空间 (workspace path + memory key 隔离)
  • 工具门控: Worker 只见 kanban_show/complete/block/heartbeat/comment/create/link

16. 关键设计决策与权衡

16.1 同步主循环 + 异步桥接

决策: 主 agent loop 保持同步,工具 handler 支持 async理由: 同步代码更易调试、追踪,async 工具通过持久化 event loop 桥接代价: 需要在 model_tools.py 维护 _get_tool_loop() / _get_worker_loop() 桥接代码

16.2 AST 静态发现 vs import 所有工具

决策: 用 AST 分析判断文件是否注册工具,只 import 需要的理由: 避免 import 无关模块、减少启动时间、防止副作用代价: 必须维护 AST 分析逻辑

16.3 User Message Skill 注入

决策: Skill 内容作为 user message 注入,而非 system prompt理由: 保护 Anthropic prompt cache (system prompt 不变 → cache 命中)代价: 多一轮 message role 管理复杂度

16.4 SQLite WAL + NFS 降级

决策: 优先 WAL 模式,失败时自动降级到 DELETE理由: WSL1/NFS/SMB 不支持 WAL 的文件锁,不能因此让 state.db 完全不可用代价: DELETE 模式下并发读取受限

16.5 Context Compression 结构化摘要

决策: 用辅助 LLM 生成结构化摘要(Active Task、Decisions、Pending Asks…)理由: 纯 token 截断丢失关键上下文;结构化的 summary 让模型知道 “what happened before”代价: 额外 LLM 调用成本;摘要准确性依赖 auxiliary model 质量

16.6 工具并行度判断

决策: 基于文件路径冲突分析决定并行/串行,非盲目并行理由: 两个同时写同一个文件的 tool call 会导致竞态代价: 需要维护 _paths_overlap() 和 _is_destructive_command() 判断逻辑


附录 A: 关键文件索引

文件
行数
职责
cli.py
15,338
交互式 CLI (prompt_toolkit + Rich)
agent/conversation_loop.py
4,611
核心对话循环
run_agent.py
4,589
AIAgent 类定义
hermes_state.py
3,449
SQLite Session 存储
trajectory_compressor.py
1,508
轨迹压缩
batch_runner.py
1,321
批量并行任务
model_tools.py
1,067
工具编排
toolsets.py
882
工具集定义
mcp_serve.py
897
MCP 服务器

附录 B: 目录结构

hermes-agent/├── run_agent.py             # AIAgent 核心类├── model_tools.py           # 工具编排├── toolsets.py              # 工具集定义├── cli.py                   # CLI 入口├── hermes_state.py          # SessionDB├── hermes_constants.py      # 全局常量├── hermes_bootstrap.py      # Windows UTF-8 引导├── batch_runner.py          # 批量运行├── agent/                   # Agent 内部模块 (40+)│   ├── conversation_loop.py    # 主循环│   ├── prompt_builder.py       # 系统提示词│   ├── context_compressor.py   # 上下文压缩│   ├── memory_manager.py       # 记忆管理│   ├── credential_pool.py      # 凭证池│   ├── <provider>_adapter.py   # Provider 适配│   └── ...├── hermes_cli/              # CLI 子命令 (50+)├── tools/                   # 工具实现 (70+)├── gateway/                 # 消息网关│   ├── run.py                  # 网关主进程│   ├── session.py              # Session 管理│   └── platforms/              # 平台适配器 (17+)├── plugins/                 # 插件系统 (11+)├── cron/                    # 定时任务├── acp_adapter/             # IDE 集成├── ui-tui/ + tui_gateway/  # Terminal UI└── tests/                   ~900 文件, ~17K 测试
💡 欢迎留言分享你的观点或提问,我们下期再见!

往期推荐

Claude 5.4 核心功能全解析手册

《从 0 到 1 搞懂大模型训练:核心流程拆解 + 必懂概念,技术人收藏级干货》

从入门到变现:2026年AI技能开发全指南

2026 年 AI 产品求职必备:8 个免费 Agent 平台,从开发到部署零成本

AI 产品经理必看:主流数据标注平台全景汇总(2026 最新版)

实战分享:零代码玩转本地自动化-用自然语言让电脑自动整理文件 + 盯紧心仪岗位

实战分享:用 Multi-Agent 自动化搞定公众号日更,从选题到发布全流程!

AI学习交流群(含资料领取)

「关注【坍缩与扩张】,这里不仅有 AI 行业干货,更有 AI 人的真实日常与情绪出口,回复「日常」加入 AI 人生活交流群」。
点击下方”坍缩与扩张”,选择“加为星标

优质文章,第一时间送达!