Hermes Agent 架构设计文档
优质文章,第一时间送达!
版本: 基于 2026-05-30 源码分析项目: NousResearch/hermes-agent规模: ~435K 行生产代码 (不含测试), ~900 测试文件, ~17K 测试用例
目录
-
概述与设计目标 -
分层架构总览 -
核心执行引擎 -
工具系统 -
多入口系统 (CLI / Gateway / TUI / ACP) -
会话与持久化 -
记忆系统 (Memory) -
Provider 适配层 -
认证与凭证池 -
上下文压缩 -
安全与护栏 -
插件系统 -
定时任务 (Cron) -
Skill 系统与 Curator -
Kanban 多 Agent 协作 -
关键设计决策与权衡
1. 概述与设计目标
Hermes Agent 是 Nous Research 开发的开源 AI Agent 框架。与 Anthropic Claude Code、OpenAI Codex CLI 属于同一品类,但具有以下差异化设计目标:
|
|
|
|---|---|
| Provider 无关 |
|
| 自改进 |
|
| 跨 session 持久记忆 |
|
| 多平台消息 |
|
| 可扩展 |
|
| 容错 |
|
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):
-
扫描 tools/目录下所有.py文件 -
用 AST 静态分析 ( _module_registers_tools) 判断文件是否调用registry.register() -
仅 import 包含注册调用的模块 — 避免 import 无关模块 -
import 触发模块级 registry.register()调
-
用 → 工具注册完成
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_file,search_files,web_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 │└─────────────────────────────────────────────────┘
设计要点:
-
WAL 模式: 支持并发读取 + 单写入者 -
NFS 兼容: 在 NFS/SMB 等不支持 WAL 的文件系统上自动降级到 DELETE journal 模式 -
System Prompt 缓存: 将 system prompt 持久化到 DB,跨 turn 复用(减少 token、加速 prefix cache 命中) -
压缩分裂链: 压缩触发新 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 适配器职责
-
API 格式转换: 不同 provider 的 message role、tool call 格式、reasoning 内容位置各不相同 -
Schema 翻译: e.g. Gemini 不支持 strict参数,gemini_schema.py做降级处理 -
Reasoning 提取: Anthropic 的 thinking、DeepSeek 的 reasoning_content 统一提取到assistant_msg[“reasoning”] -
Prompt Caching: Anthropic 的 cache_control breakpoints 由 agent/prompt_caching.py自动注入 -
Streaming 统一: 不同 provider 的 streaming delta 格式统一为 OpenAI 兼容格式
8.3 关键适配器
|
|
|
|
|---|---|---|
|
|
anthropic_adapter.py |
|
|
|
bedrock_adapter.py |
|
|
|
gemini_native_adapter.py |
|
|
|
codex_responses_adapter.py |
|
|
|
copilot_acp_client.py |
|
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() 扫描:
-
内置插件: hermes-agent/plugins/ -
用户插件: ~/.hermes/plugins/ -
项目插件: <project>/.hermes/plugins/ -
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
|
|
Script-only
no_agent=True) |
|
Chained
context_from) |
|
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_BOARDenv 限定) -
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 |
|
|
agent/conversation_loop.py |
|
|
run_agent.py |
|
|
hermes_state.py |
|
|
trajectory_compressor.py |
|
|
batch_runner.py |
|
|
model_tools.py |
|
|
toolsets.py |
|
|
mcp_serve.py |
|
|
附录 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 测试
往期推荐
▼
《从 0 到 1 搞懂大模型训练:核心流程拆解 + 必懂概念,技术人收藏级干货》
实战分享:零代码玩转本地自动化-用自然语言让电脑自动整理文件 + 盯紧心仪岗位
实战分享:用 Multi-Agent 自动化搞定公众号日更,从选题到发布全流程!
AI学习交流群(含资料领取)

优质文章,第一时间送达!
夜雨聆风