38 万 Star 的 OpenClaw 凭什么碾压 Hermes Agent?源码级架构对决:从 Gateway 到 Agent Loop 的五维拆解
英文标题:380K Star 的 OpenClaw 凭什么碾压 Hermes Agent?源码级架构对决——从 Gateway 到 Agent Loop 的五维拆解
原文对比了 OpenClaw 与 Nous Research 的 Hermes Agent:前者以 TypeScript Gateway 管理 25 多个消息通道和多 Agent 编排,后者以 Python 单循环为核心。两者在会话并发、工具注册与安全、记忆检索、多 Agent 协作等方面采用不同方案。原文称,Hermes 的 Hindsight 可在 472 毫秒内从 9216 条事实中语义召回相关记忆,而 OpenClaw 更依赖文件和 Agent 自主管理。对开发者而言,选型取决于多通道与原生编排需求,以及对语义记忆、工具扩展和分层安全的侧重。
4.4 KB
中文
OpenClaw(GitHub 上有 38 万 Star)和 Hermes Agent(由 Nous Research 开发)是 2026 年最受关注的两个开源 Agent 框架。它们解决同一个问题——让 AI 自主执行任务——但架构哲学截然相反:OpenClaw 用 TypeScript Gateway 作为中央控制平面管理 25 多个消息通道和 14 多个子 Agent;Hermes Agent 用 Python 单循环 run_conversation() 在进程内完成一切。本文从源码层面拆解两者的 Agent 生命周期、工具系统、记忆架构、多 Agent 协作和安全模型,给出五维对照表和生产环境选型参考。
一、先看全貌:两个框架的架构哲学
OpenClaw:Gateway 控制平面
OpenClaw 启动后,会在本机绑定一个 Gateway 进程(Node.js,src/gateway/),它承担三个角色:
- 消息路由——从 Telegram、WhatsApp、Discord、Slack、iMessage 等 25 多个通道接收消息,按
session_key路由到正确的会话。 - 会话管理——维护所有活跃会话的生命周期,按 Lane Queue 串行调度同一会话内的消息。
- Agent 编排——通过
sessions_spawn启动子 Agent,通过sessions_send实现 Agent 间通信。
vbscript 用户消息(Telegram) → Channel Plugin 解析 → Gateway 路由(session_key) → Lane Queue 排队 → Agent Runtime 执行(Pi-Embedded / CLI Runner) → Model Call → Tool Dispatch → Response
Gateway 之下,Agent Runtime 有两种模式:
- Pi-Embedded Runner:进程内执行,共享 Gateway 的工具和配置,适合轻量任务。
- CLI Runner:独立子进程(如
claudeCLI),通过 ACP(Agent Communication Protocol)与 Gateway 通信。
Hermes Agent:Python 单循环
Hermes Agent 没有 Gateway。它是一个 Python 进程,入口在 hermes/agent.py 的 run_conversation():
yaml 用户消息 → System Prompt 组装 → Agent Loop 开始 ├── Phase 1: Memory Recall(Hindsight 语义召回) ├── Phase 2: Skill Load(匹配 skill → 注入提示词) ├── Phase 3: Model Call(API 请求) ├── Phase 4: Tool Dispatch(解析 tool_calls → 执行 → 结果注入) ├── Phase 5: Hindsight Retain(自动记忆写入) └── Phase 6: 循环或终止
关键区别:Hermes 的「单循环」意味着同一时间只处理一个会话、一条消息。没有 Lane Queue,没有 Gateway 路由,也没有多 Agent 原生支持,直到 v0.16 才引入 delegate_task。
一张表看懂差异
| 维度 | OpenClaw | Hermes Agent |
|---|---|---|
| 语言 | TypeScript(Node.js) | Python |
| 架构模型 | Gateway 中心辐射式架构 | 单进程直接循环 |
| 多会话 | 原生并发,Lane Queue 串行 | 单会话,靠多次调用 |
| 消息通道 | 内置 25 多个(Telegram、Discord、Slack、WhatsApp 等) | Telegram + WebUI(靠 frp/cc-switch 扩展) |
| 子进程安全 | CLI Runner + Sandbox(Docker) | execute_code + 6 种终端后端 |
| 记忆系统 | JSONL Session Log + Daily Markdown | Hindsight PG + Memory.md + Session DB |
| 工具注册 | 静态 tools/ 目录 + 插件 |
动态 ToolRegistry + @register_tool 装饰器 |
| 配置文件 | openclaw.json + SOUL.md + TOOLS.md |
config.yaml + SOUL.md + skills/ |
二、Agent 生命周期:从消息到响应
OpenClaw:session_spawn → lane_queue → run
当一条 Telegram 消息到达:
步骤 1——Channel Plugin 接入
typescript interface ChannelPlugin { id: string; start: (gateway: Gateway) => Promise; stop: () => Promise; onMessage: (msg: ChannelMessage) => Promise; }
所有通道插件实现同一个接口。Gateway 启动时遍历注册表,为每个通道调用 start()。
步骤 2——Gateway 路由
消息从通道插件进入 Gateway 后,首先要确定 session_key:
typescript
这个 key 决定了消息分配到哪个 Agent 实例的哪个会话。同一 session_key 的消息被串行化到同一条 Lane Queue。
步骤 3——Lane Queue 串行调度
java Lane Queue (先进先出) ┌─────────┐ │ msg_001 │ → Agent Runtime 处理中 ├─────────┤ │ msg_002 │ → 等待 ├─────────┤ │ msg_003 │ → 等待 └─────────┘
这是 OpenClaw 最关键的设计决策之一:同一会话的消息严格串行,避免 Agent 在处理上一条消息时收到新消息导致上下文竞争。但不同 session_key 的会话可以并行。
步骤 4——Agent Runtime 执行
Pi-Embedded Runner 在进程内完成整个 Agent Loop:
typescript async function runAgentLoop(session) {
const context = await loadContext(session);
const systemPrompt = await buildSystemPrompt(session);
const response = await modelCall(systemPrompt, context);
if (response.tool_calls) { for (const toolCall of response.tool_calls) { const result = await executeTool(toolCall); context.push({ role: "tool", content: result }); }
return runAgentLoop(session);
}
await saveSession(session); return response; }
Hermes Agent:run_conversation() 的 7 个阶段
Hermes 的核心循环在 hermes/agent/loop.py(约 800 行),分为 7 个明确阶段:
python async def run_conversation(user_message, session_id):
memories = await hindsight_recall(user_message)
skills = match_skills(user_message)
system_prompt = assemble_prompt(memories, skills)
for turn in range(MAX_TURNS):
response = await model_call(system_prompt, messages)
if response.tool_calls:
results = await execute_tools(response.tool_calls)
messages.extend(results)
if response.finish_reason == "stop":
break
await hindsight_retain(session_context)
return messages
关键差异
| OpenClaw | Hermes Agent | |
|---|---|---|
| 并发模型 | Lane Queue 串行 + 多会话并行 | 单线程,每次一条消息 |
| 上下文管理 | JSONL Session Log,按行追加 | 内存消息列表,超过 budget 触发 compaction |
| 会话持久化 | 文件系统(~/.openclaw/sessions/) |
Session DB(SQLite)+ Hindsight PG |
| 终止条件 | 模型返回 stop_reason |
finish_reason="stop"、MAX_TURNS 或 budget 用尽 |
三、工具系统:注册、分发与安全边界
OpenClaw 工具系统
工具定义在 src/agents/tools/ 下,按功能分目录。每个目录内是一个完整的工具模块,包含定义文件和测试文件:
css src/agents/tools/ ├── browser-tool.ts ← Playwright 浏览器自动化 + CDP 控制 ├── file-tools.ts ← 文件读写(read/write/search) ├── terminal-tools.ts ← Shell 命令执行(foreground/background/pty) ├── canvas-tools.ts ← Canvas 渲染(HTML → 图片) ├── cron-tools.ts ← 定时任务调度 ├── session-tools.ts ← sessions_spawn / sessions_send(多 Agent 核心) ├── mcp-tools.ts ← MCP 协议客户端工具 ├── memory-tools.ts ← 记忆写入/读取 └── ...
每个工具实现一个统一的接口:
typescript interface ToolDefinition { name: string; description: string; parameters: JSONSchema; execute: (params: any, context: ToolContext) => Promise; policy?: ToolPolicy; }
**工具策略(Tool Policy)**是 OpenClaw 安全模型的核心——不是简单地「禁用危险操作」,而是给每个工具定义精细的权限边界:
typescript interface ToolPolicy { requireApproval?: boolean; sandboxOnly?: boolean; allowArgs?: string[]; denyArgs?: string[]; maxTimeout?: number; }
工具分发流程:当 LLM 返回 tool_calls 后,Gateway 进入分发循环——逐个工具执行,结果注入上下文,再决定是否继续调用模型:
sql Model returns tool_calls → for each tool_call: → policy check(是否需确认?是否限沙箱?) → execute(params) → result → push to context → back to model(带工具结果)
Hermes Agent 工具系统
Hermes 用 Python 装饰器注册工具,一个装饰器搞定全部元数据:
python @register_tool( name="terminal", description="Execute shell commands on Linux. " "Foreground for short commands, " "background=true for long-running tasks.", parameters={ "command": {"type": "string", "description": "The command to execute"}, "background": {"type": "boolean", "default": False}, "timeout": {"type": "integer", "default": 180} } ) async def terminal(command: str, background: bool = False, timeout: int = 180):
if background:
return await run_background(command, timeout)
return await run_foreground(command, timeout)
工具注册表是动态加载的:启动时扫描所有 ToolProvider 子类,按需实例化。每个工具还可以携带 skill 元数据,说明它归属于哪个 skill,便于按 skill 分组管理和权限控制。
Hermes 的工具安全分层更细:
| 安全层 | 机制 |
|---|---|
| Prompt 层 | 在 System Prompt 中注入工具使用规则 |
| 策略层 | execute_code 沙箱:禁用 os.system()、subprocess(除 hermes_tools.terminal) |
| 终端层 | 可选 6 种终端后端:local / ssh / docker / pty / background + sandbox |
| 凭据层 | AES-256-CBC Vault,敏感参数(API Key、密码)不经过 LLM |
对比
| OpenClaw | Hermes Agent | |
|---|---|---|
| 注册方式 | 静态 TypeScript 文件 | 装饰器 @register_tool 动态注册 |
| 安全策略 | ToolPolicy(确认 + 沙箱) | 四层防御(Prompt → Policy → Terminal → Vault) |
| 工具数量 | 60 多个(含浏览器、Canvas、定时任务、MCP) | 50 多个(含 Playwright、终端、SSH 远程、视觉) |
| 扩展方式 | 写 .ts 文件 → 放入 tools/ 目录 → 重启 |
写 Python + @register_tool → 放入 skills/ → 热加载 |
| MCP 支持 | 原生 mcp-tools.ts |
通过 native-mcp skill 接入 |
四、记忆系统:文件 vs 数据库
这是两个框架差异最大的模块。
OpenClaw:JSONL + Daily Markdown
javascript ~/.openclaw/ ├── sessions/ │ └── agent_main_telegram_12345.jsonl ← 每行一个 JSON 事件 ├── memory/ │ ├── 2026-06-24.md ← 今日记忆(Markdown 格式) │ └── 2026-06-23.md ← 昨日记忆 └── SOUL.md ← Agent 人格定义
- Session Log(JSONL):记录每一条消息的完整上下文,按行追加,无限增长。
- Daily Memory(Markdown):Agent 从 Session Log 中自行提炼的长期记忆,由 Agent 自己决定写什么、写到哪天。
- 没有语义搜索:记忆查找靠
grep加上 Agent 自行阅读 Markdown 文件。
{"timestamp":"2026-06-24T10:30:00Z","role":"user","content":"帮我查天气"} {"timestamp":"2026-06-24T10:30:02Z","role":"assistant","content":"正在查询..."} {"timestamp":"2026-06-24T10:30:05Z","role":"tool","name":"web_search","result":"..."}
Hermes Agent:三层记忆矩阵
| 层 | 存储 | 用途 | 查找方式 |
|---|---|---|---|
| Memory.md | 文件系统 | 紧急兜底(环境事实、偏好) | 全文注入 System Prompt |
| Hindsight | PostgreSQL + pgvector | 语义记忆(9216 条以上事实) | hindsight_recall() 语义搜索 + 关键词 + 实体图 |
| Session DB | SQLite | 会话历史(FTS5 全文索引) | session_search() 跨会话检索 |
Hermes 的记忆查找是三段式管道:
- Hindsight
recall:bge-m3嵌入 → pgvector ANN → 重排序 → top-K。 - Session DB FTS5:通过 SQLite 全文搜索历史会话。
- Memory.md 全文注入:兜底。
关键差异
OpenClaw 的记忆模型本质是文件系统 + Agent 自管理——简单、透明,但缺乏语义检索能力。当你问「上次用户说的那个配置是什么」时,Agent 需要自己用 grep 搜索文件。Hermes 的 Hindsight 可以在 472 毫秒内从 9216 条事实中语义召回相关记忆。
五、多 Agent 协作:平台原生 vs 工具模拟
OpenClaw:sessions_spawn + sessions_send(第一公民)
OpenClaw 的多 Agent 模型不是后来的补丁——从架构设计的第一天起,Gateway 就承担了 Agent 编排的职责。
核心 API 只有两个:
typescript sessions_spawn({ agent: "code-reviewer", // 子 Agent 的配置名(openclaw.json 中定义) prompt: "Review PR #42 的安全问题", model: "claude-sonnet-4", // 可以指定不同模型(不同 Agent 用不同模型) context: "项目使用 Django + PostgreSQL", });
sessions_send({ target: "agent:code-reviewer:session_abc123", message: "重点检查 SQL 注入和 XSS", });
sessions_send 的内部实现:Gateway 找到目标 session_key,将消息作为一条新的用户输入注入该会话的 Lane Queue,触发一次新的 Agent Loop 执行。对子 Agent 来说,这条消息和用户发的消息没有区别——它不知道消息来自人类还是另一个 Agent。
社区在实践中形成了 5 种架构模式(来自 OpenClaw 社区研究文档):
| 模式 | 机制 | 典型场景 | 并发度 |
|---|---|---|---|
| Routing | 按消息内容匹配路由规则 → 不同 Agent | 客服分流:「退款」→退款 Agent,「技术」→技术 Agent | 高(按消息并行) |
| Sub-Agent | sessions_spawn 启动,完成后结果回传主 Agent |
代码审查 Agent 审查 PR → 结果发给主 Agent | 低(同步等待) |
| Messaging | sessions_send Agent 间异步消息 |
流水线:爬虫 Agent → 分析 Agent → 报告 Agent | 中(异步流水线) |
| Orchestrator | 三层嵌套(depth ≤ 2) | Kev's Dream Team:14 多个 Agent,Orchestrator 分配任务 | 中(嵌套控制) |
| CLI Agent | openclaw agent 命令行启动独立进程 |
一次性任务:生成 100 篇 SEO 文章 | 高(进程级隔离) |
Kev's Dream Team(14 多个 Agent)的实际架构:
scss Kev (Orchestrator, Opus 4.5) ├── Code Reviewer (Claude Sonnet 4) ├── Security Scanner (Claude Opus 4.5) ├── SEO Optimizer (GPT-4o) ├── Content Writer (Claude Sonnet 4) │ ├── Research Sub-Agent (深度=2) │ └── Fact Checker (深度=2) ├── Data Analyst (Claude Opus) └── Publisher (Claude Sonnet)
每个 Agent 有独立的 SOUL.md、独立的内存空间、独立的工具权限。Orchestrator 通过 sessions_send 分发任务,通过 sessions_spawn 创建子 Agent。关键限制:嵌套深度最大为 2(maxSpawnDepth: 2),防止无限递归。
Hermes Agent:delegate_task + Kanban(工具层模拟)
Hermes 的多 Agent 是通过 delegate_task 工具实现的——它不是 Gateway 层的原生能力,而是一个在 Agent Loop 内部被调用的工具:
python delegate_task( goal="分析这个错误日志,找出根因", context=""" 日志文件: /var/log/hermes/error.log 环境: Ubuntu 22.04, Python 3.11 最近变更: 升级了 Hindsight 0.8.0 """, toolsets=["terminal", "file", "web"], role="leaf" )
子 Agent 在全新的独立会话上下文中运行——不知道主 Agent 之前做了什么,也不知道其他子 Agent 的结果。它只能通过 context 参数接收信息,通过返回值回传摘要。
Kanban 模式(kanban-codex-lane skill):
Kanban Board ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ Lane 1 │ │ Lane 2 │ │ Lane 3 │ │ Lane 4 │ │ Lane 5 │ │ 爬取数据 │ │ 清洗数据 │ │ 分析数据 │ │ 写报告 │ │ 发布 │ │ Codex │ │ Codex │ │ Codex │ │ Codex │ │ Codex │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘
5 个 Codex CLI 子进程并行执行,通过文件系统传递中间产物。状态由看板管理,主 Agent 只负责调度和汇总。
对比
| OpenClaw | Hermes Agent | |
|---|---|---|
| 子 Agent 启动 | sessions_spawn(Gateway 原生 API) |
delegate_task(Agent Loop 内的工具) |
| Agent 间通信 | sessions_send(消息注入 Lane Queue) |
无直接 API,靠文件系统 / 共享内存 |
| 嵌套深度 | maxSpawnDepth: 2 |
max_spawn_depth: 3 |
| 模型独立 | 每个 Agent 独立配置模型 | 默认继承父 Agent,可覆盖 |
| 会话隔离 | 独立 session_key + 独立上下文 | 独立 session ID + 独立上下文 |
| 工具权限 | 每个 Agent 独立配置 tools/ 目录 | toolsets 参数限制工具集 |
| 生产案例 | Kev's Dream Team(14 多个 Agent) | 含光 Kanban(5 个 Codex Lane) |
六、安全模型:信任用户 vs 分级防御
OpenClaw:用户是第一道防线
OpenClaw 的安全哲学很直白——「信任用户的判断,把决策权交给用户」:
- 危险操作(如
rm -rf /)触发requireApproval→ 弹出确认对话框。 sandboxOnly策略将高风险工具限制在 Docker 沙箱内。- 没有内置的 Prompt Injection 防御。
typescript openclaw security audit --check openclaw security fix
Hermes Agent:分层防御
Hermes 从 System Prompt 层就开始防御:
- Prompt Injection 检测:
threat_patterns.py匹配已知攻击模式。 - 工具沙箱:
execute_code在受限 Python 环境中运行,终端命令通过策略过滤。 - 凭据保险库:AES-256-CBC 加密,master key 不由 Agent 掌握。
- 爆炸半径评估:SOUL v4.5 要求在每次行动前
(原文至此截断。)
English / 原文
OpenClaw(380K GitHub Stars)和 Hermes Agent(Nous Research)是 2026 年最受关注的两个开源 Agent 框架。它们解决同一个问题——让 AI 自主执行任务——但架构哲学截然相反:OpenClaw 用 TypeScript Gateway 作为中央控制平面管理 25+ 消息通道和 14+ 子 Agent;Hermes Agent 用 Python 单循环 run_conversation() 在进程内完成一切。本文从源码级拆解两者的 Agent 生命周期、工具系统、记忆架构、多 Agent 协作和安全模型,给出五维对照表和生产环境选型指南。
一、先看全貌:两个框架的架构哲学
OpenClaw:Gateway 控制平面
OpenClaw 启动后,会在本机绑定一个 Gateway 进程 (Node.js,src/gateway/),它承担三个角色:
- 消息路由 ——从 Telegram/WhatsApp/Discord/Slack/iMessage 等 25+ 通道接收消息,按
session_key路由到正确的会话 - 会话管理 ——维护所有活跃会话的生命周期,按 Lane Queue 串行调度同一会话内的消息
- Agent 编排 ——通过
sessions_spawn启动子 Agent,通过sessions_send实现 Agent 间通信
vbscript
代码解读
复制代码
用户消息(Telegram)
→ Channel Plugin 解析
→ Gateway 路由(session_key)
→ Lane Queue 排队
→ Agent Runtime 执行(Pi-Embedded / CLI Runner)
→ Model Call → Tool Dispatch → Response
Gateway 之下,Agent Runtime 有两种模式:
- Pi-Embedded Runner :进程内执行,共享 Gateway 的工具和配置,适合轻量任务
- CLI Runner :独立子进程(如
claudeCLI),通过 ACP(Agent Communication Protocol)与 Gateway 通信
Hermes Agent:Python 单循环
Hermes Agent 没有 Gateway。它是一个 Python 进程,入口在 hermes/agent.py 的 run_conversation():
yaml
代码解读
复制代码
用户消息 → System Prompt 组装 → Agent Loop 开始
├── Phase 1: Memory Recall(Hindsight 语义召回)
├── Phase 2: Skill Load(匹配 skill → 注入提示词)
├── Phase 3: Model Call(API 请求)
├── Phase 4: Tool Dispatch(解析 tool_calls → 执行 → 结果注入)
├── Phase 5: Hindsight Retain(自动记忆写入)
└── Phase 6: 循环或终止
关键区别:Hermes 的「单循环」意味着同一时间只处理一个会话、一个消息 。没有 Lane Queue,没有 Gateway 路由,没有多 Agent 原生支持(直到 v0.16 才引入 delegate_task)。
一张表看懂差异
| 维度 | OpenClaw | Hermes Agent |
|---|---|---|
| 语言 | TypeScript (Node.js) | Python |
| 架构模型 | Gateway hub-and-spoke | 单进程直接循环 |
| 多会话 | 原生并发,Lane Queue 串行 | 单会话,靠多次调用 |
| 消息通道 | 25+ 内置(Telegram/Discord/Slack/WhatsApp…) | Telegram + WebUI(靠 frp/cc-switch 扩展) |
| 子进程安全 | CLI Runner + Sandbox(Docker) | execute_code + 6 种终端后端 |
| 记忆系统 | JSONL Session Log + Daily Markdown | Hindsight PG + Memory.md + Session DB |
| 工具注册 | 静态 tools/ 目录 + 插件 |
动态 ToolRegistry + @register_tool 装饰器 |
| 配置文件 | openclaw.json + SOUL.md + TOOLS.md |
config.yaml + SOUL.md + skills/ |
二、Agent 生命周期:从消息到响应
OpenClaw:session_spawn → lane_queue → run
当一条 Telegram 消息到达:
Step 1 — Channel Plugin 接入
typescript
代码解读
复制代码
interface ChannelPlugin {
id: string;
start: (gateway: Gateway) => Promise<void>;
stop: () => Promise<void>;
onMessage: (msg: ChannelMessage) => Promise<void>;
}
所有通道插件实现同一个接口。Gateway 启动时遍历注册表,为每个通道调用 start()。
Step 2 — Gateway 路由
消息从通道插件进入 Gateway 后,首先要确定 session_key:
typescript
代码解读
复制代码
这个 key 决定了消息分配到哪个 Agent 实例的哪个会话。同一 session_key 的消息被串行化到同一条 Lane Queue。
Step 3 — Lane Queue 串行调度
java
代码解读
复制代码
Lane Queue (先进先出)
┌─────────┐
│ msg_001 │ → Agent Runtime 处理中
├─────────┤
│ msg_002 │ → 等待
├─────────┤
│ msg_003 │ → 等待
└─────────┘
这是 OpenClaw 最关键的设计决策之一:同一会话的消息严格串行 ,避免 Agent 在处理上一条消息时收到新消息导致上下文竞争。但不同 session_key 的会话可以并行。
Step 4 — Agent Runtime 执行
Pi-Embedded Runner 在进程内完成整个 Agent Loop:
typescript
代码解读
复制代码
async function runAgentLoop(session) {
const context = await loadContext(session);
const systemPrompt = await buildSystemPrompt(session);
const response = await modelCall(systemPrompt, context);
if (response.tool_calls) {
for (const toolCall of response.tool_calls) {
const result = await executeTool(toolCall);
context.push({ role: "tool", content: result });
}
return runAgentLoop(session);
}
await saveSession(session);
return response;
}
Hermes Agent:run_conversation() 7 阶段
Hermes 的核心循环在 hermes/agent/loop.py(约 800 行),分为 7 个明确阶段:
python
代码解读
复制代码
async def run_conversation(user_message, session_id):
memories = await hindsight_recall(user_message)
skills = match_skills(user_message)
system_prompt = assemble_prompt(memories, skills)
for turn in range(MAX_TURNS):
response = await model_call(system_prompt, messages)
if response.tool_calls:
results = await execute_tools(response.tool_calls)
messages.extend(results)
if response.finish_reason == "stop":
break
await hindsight_retain(session_context)
return messages
关键差异
| OpenClaw| Hermes Agent
---|---|---
并发模型| Lane Queue 串行 + 多会话并行| 单线程,每次一个消息
上下文管理| JSONL Session Log,按行追加| 内存消息列表,超过 budget 触发 compaction
会话持久化| 文件系统(~/.openclaw/sessions/)| Session DB(SQLite)+ Hindsight PG
终止条件| 模型返回 stop_reason| finish_reason="stop" 或 MAX_TURNS 或 budget 用尽
三、工具系统:注册、分发与安全边界
OpenClaw 工具系统
工具定义在 src/agents/tools/ 下,按功能分目录。每个目录内是一个完整的工具模块,包含定义文件和测试文件:
css
代码解读
复制代码
src/agents/tools/
├── browser-tool.ts ← Playwright 浏览器自动化 + CDP 控制
├── file-tools.ts ← 文件读写(read/write/search)
├── terminal-tools.ts ← Shell 命令执行(foreground/background/pty)
├── canvas-tools.ts ← Canvas 渲染(HTML → 图片)
├── cron-tools.ts ← 定时任务调度
├── session-tools.ts ← sessions_spawn / sessions_send(多 Agent 核心)
├── mcp-tools.ts ← MCP 协议客户端工具
├── memory-tools.ts ← 记忆写入/读取
└── ...
每个工具实现一个统一的接口:
typescript
代码解读
复制代码
interface ToolDefinition {
name: string;
description: string;
parameters: JSONSchema;
execute: (params: any, context: ToolContext) => Promise<ToolResult>;
policy?: ToolPolicy;
}
**工具策略(Tool Policy)**是 OpenClaw 安全模型的核心——不是简单地"禁用危险操作",而是给每个工具定义精细的权限边界:
typescript
代码解读
复制代码
interface ToolPolicy {
requireApproval?: boolean;
sandboxOnly?: boolean;
allowArgs?: string[];
denyArgs?: string[];
maxTimeout?: number;
}
工具分发流程 :当 LLM 返回 tool_calls 后,Gateway 进入分发循环——逐个工具执行,结果注入上下文,再决定是否继续调用模型:
sql
代码解读
复制代码
Model returns tool_calls
→ for each tool_call:
→ policy check(是否需确认?是否限沙箱?)
→ execute(params)
→ result → push to context
→ back to model(带工具结果)
Hermes Agent 工具系统
Hermes 用 Python 装饰器注册工具,一个装饰器搞定全部元数据 :
python
代码解读
复制代码
@register_tool(
name="terminal",
description="Execute shell commands on Linux. "
"Foreground for short commands, "
"background=true for long-running tasks.",
parameters={
"command": {"type": "string", "description": "The command to execute"},
"background": {"type": "boolean", "default": False},
"timeout": {"type": "integer", "default": 180}
}
)
async def terminal(command: str, background: bool = False, timeout: int = 180):
if background:
return await run_background(command, timeout)
return await run_foreground(command, timeout)
工具注册表是动态加载 的——启动时扫描所有 ToolProvider 子类,按需实例化。每个工具还可以携带 skill 元数据,说明它归属于哪个 skill,便于按 skill 分组管理和权限控制。
Hermes 的工具安全分层更细:
| 安全层 | 机制 |
|---|---|
| Prompt 层 | System Prompt 中注入工具使用规则 |
| 策略层 | execute_code 沙箱:禁用 os.system()、subprocess(除 hermes_tools.terminal) |
| 终端层 | 6 种终端后端可选:local / ssh / docker / pty / background + sandbox |
| 凭据层 | AES-256-CBC Vault,敏感参数(API Key/密码)不经过 LLM |
对比
| OpenClaw| Hermes Agent
---|---|---
注册方式| 静态 TypeScript 文件| 装饰器 @register_tool 动态注册
安全策略| ToolPolicy(confirm + sandbox)| 四层防御(Prompt → Policy → Terminal → Vault)
工具数量| 60+(含浏览器/Canvas/定时任务/MCP)| 50+(含 Playwright/终端/SSH 远程/vision)
扩展方式| 写 .ts 文件 → 放 tools/ 目录 → 重启| 写 Python + @register_tool → 放 skills/ → 热加载
MCP 支持| 原生 mcp-tools.ts| 通过 native-mcp skill 接入
四、记忆系统:文件 vs 数据库
这是两个框架差异最大的模块。
OpenClaw:JSONL + Daily Markdown
javascript
代码解读
复制代码
~/.openclaw/
├── sessions/
│ └── agent_main_telegram_12345.jsonl ← 每行一个 JSON 事件
├── memory/
│ ├── 2026-06-24.md ← 今日记忆(Markdown 格式)
│ └── 2026-06-23.md ← 昨日记忆
└── SOUL.md ← Agent 人格定义
-
Session Log(JSONL) :记录每一条消息的完整上下文,按行追加,无限增长
-
Daily Memory(Markdown) :Agent 从 Session Log 中自行提炼 的长期记忆,由 Agent 自己决定写什么、写到哪天
-
没有语义搜索 :记忆查找靠
grep+ Agent 自行阅读 Markdown 文件json 代码解读 复制代码
{"timestamp":"2026-06-24T10:30:00Z","role":"user","content":"帮我查天气"} {"timestamp":"2026-06-24T10:30:02Z","role":"assistant","content":"正在查询..."} {"timestamp":"2026-06-24T10:30:05Z","role":"tool","name":"web_search","result":"..."}
Hermes Agent:三层记忆矩阵
| 层 | 存储 | 用途 | 查找方式 |
|---|---|---|---|
| Memory.md | 文件系统 | 紧急兜底(环境事实、偏好) | 全文注入 System Prompt |
| Hindsight | PostgreSQL + pgvector | 语义记忆(9216+ facts) | hindsight_recall() 语义搜索 + 关键词 + 实体图 |
| Session DB | SQLite | 会话历史(FTS5 全文索引) | session_search() 跨会话检索 |
Hermes 的记忆查找是三段式管道 :
- Hindsight
recall:bge-m3嵌入 → pgvector ANN → 重排序 → top-K - Session DB FTS5:SQLite 全文搜索历史会话
- Memory.md 全文注入:兜底
关键差异
OpenClaw 的记忆模型本质是文件系统 + Agent 自管理 ——简单、透明,但缺乏语义检索能力。当你问「上次用户说的那个配置是什么」时,Agent 需要自己 grep 文件。Hermes 的 Hindsight 可以 472ms 内从 9216 条 fact 中语义召回相关记忆。
五、多 Agent 协作:平台原生 vs 工具模拟
OpenClaw:sessions_spawn + sessions_send(第一公民)
OpenClaw 的多 Agent 模型不是后来的补丁——从架构设计的第一天起,Gateway 就承担了 Agent 编排的职责。
核心 API 只有两个:
typescript
代码解读
复制代码
sessions_spawn({
agent: "code-reviewer", // 子 Agent 的配置名(openclaw.json 中定义)
prompt: "Review PR #42 的安全问题",
model: "claude-sonnet-4", // 可以指定不同模型(不同 Agent 用不同模型)
context: "项目使用 Django + PostgreSQL",
});
sessions_send({
target: "agent:code-reviewer:session_abc123",
message: "重点检查 SQL 注入和 XSS",
});
Sessions_send 的内部实现 :Gateway 找到目标 session_key,将消息作为一条新的用户输入注入该会话的 Lane Queue,触发一次新的 Agent Loop 执行。对子 Agent 来说,这条消息和用户发的消息没有区别 ——它不知道消息来自人类还是另一个 Agent。
社区在实践中形成了 5 种架构模式(来自 OpenClaw 社区研究文档):
| 模式 | 机制 | 典型场景 | 并发度 |
|---|---|---|---|
| Routing | 按消息内容匹配路由规则 → 不同 Agent | 客服分流:「退款」→退款 Agent,「技术」→技术 Agent | 高(按消息并行) |
| Sub-Agent | sessions_spawn 启动,完成后结果回传主 Agent |
代码审查 Agent 审查 PR → 结果发给主 Agent | 低(同步等待) |
| Messaging | sessions_send Agent 间异步消息 |
流水线:爬虫 Agent → 分析 Agent → 报告 Agent | 中(异步流水线) |
| Orchestrator | 三层嵌套(depth ≤ 2) | Kev's Dream Team:14+ Agent,Orchestrator 分配任务 | 中(嵌套控制) |
| CLI Agent | openclaw agent 命令行启动独立进程 |
一次性任务:生成 100 篇 SEO 文章 | 高(进程级隔离) |
Kev's Dream Team(14+ Agent)的实际架构:
scss
代码解读
复制代码
Kev (Orchestrator, Opus 4.5)
├── Code Reviewer (Claude Sonnet 4)
├── Security Scanner (Claude Opus 4.5)
├── SEO Optimizer (GPT-4o)
├── Content Writer (Claude Sonnet 4)
│ ├── Research Sub-Agent (深度=2)
│ └── Fact Checker (深度=2)
├── Data Analyst (Claude Opus)
└── Publisher (Claude Sonnet)
每个 Agent 有独立的 SOUL.md、独立的内存空间、独立的工具权限。Orchestrator 通过 sessions_send 分发任务,通过 sessions_spawn 创建子 Agent。关键限制 :嵌套深度最大为 2(maxSpawnDepth: 2),防止无限递归。
Hermes Agent:delegate_task + Kanban(工具层模拟)
Hermes 的多 Agent 是通过 delegate_task 工具实现的——它不是 Gateway 层的原生能力,而是一个在 Agent Loop 内部被调用的工具 :
python
代码解读
复制代码
delegate_task(
goal="分析这个错误日志,找出根因",
context="""
日志文件: /var/log/hermes/error.log
环境: Ubuntu 22.04, Python 3.11
最近变更: 升级了 Hindsight 0.8.0
""",
toolsets=["terminal", "file", "web"],
role="leaf"
)
子 Agent 在全新的独立会话上下文 中运行——不知道主 Agent 之前做了什么、不知道其他子 Agent 的结果。它只能通过 context 参数接收信息,通过返回值回传摘要。
Kanban 模式 (kanban-codex-lane skill):
代码解读
复制代码
Kanban Board
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ Lane 1 │ │ Lane 2 │ │ Lane 3 │ │ Lane 4 │ │ Lane 5 │
│ 爬取数据 │ │ 清洗数据 │ │ 分析数据 │ │ 写报告 │ │ 发布 │
│ Codex │ │ Codex │ │ Codex │ │ Codex │ │ Codex │
└──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘
5 个 Codex CLI 子进程并行执行,通过文件系统传递中间产物。状态由看板管理,主 Agent 只负责调度和汇总。
对比
| OpenClaw| Hermes Agent
---|---|---
子 Agent 启动| sessions_spawn(Gateway 原生 API)| delegate_task(Agent Loop 内的工具)
Agent 间通信| sessions_send(消息注入 Lane Queue)| 无直接 API,靠文件系统 / 共享内存
嵌套深度| maxSpawnDepth: 2| max_spawn_depth: 3
模型独立| 每个 Agent 独立配置模型| 默认继承父 Agent,可 override
会话隔离| 独立 session_key + 独立上下文| 独立 session ID + 独立上下文
工具权限| 每个 Agent 独立配置 tools/ 目录| toolsets 参数限制工具集
生产案例| Kev's Dream Team(14+ Agent)| 含光 Kanban(5 Codex Lane)
六、安全模型:信任用户 vs 分级防御
OpenClaw:用户是第一道防线
OpenClaw 的安全哲学很直白——「信任用户的判断,把决策权交给用户」:
-
危险操作(如
rm -rf /)触发requireApproval→ 弹出确认对话框 -
sandboxOnly策略将高风险工具限制在 Docker 沙箱内 -
没有内置的 Prompt Injection 防御
typescript 代码解读 复制代码
openclaw security audit --check
openclaw security fix
Hermes Agent:分层防御
Hermes 从 System Prompt 层就开始防御:
- Prompt Injection 检测 :
threat_patterns.py匹配已知攻击模式 - 工具沙箱 :
execute_code在受限 Python 环境中运行,终端命令通过策略过滤 - 凭据保险库 :AES-256-CBC 加密,master key 不由 Agent 掌握
- 爆炸半径评估 :SOUL v4.5 要求在每次行动前评估影响范围
七、选型指南:什么时候该用哪个
| 你的场景 | 推荐 | 原因 |
|---|---|---|
| 需要接入多个聊天平台(Telegram+Discord+Slack+微信) | OpenClaw | 25+ 通道原生支持,Gateway 统一路由 |
| 需要复杂的多 Agent 编排 | OpenClaw | sessions_spawn + sessions_send 是第一公民 |
| 需要深度语义记忆搜索 | Hermes Agent | Hindsight PG + pgvector,472ms 召回 |
| 在资源受限的设备上运行(树莓派/Jetson) | Hermes Agent | Python 进程,内存占用更低 |
| 需要严格的安全审计 | Hermes Agent | Prompt Injection 防御 + Vault 加密 + 爆炸半径评估 |
| 你是 Python 技术栈 | Hermes Agent | 纯 Python,零 JS 依赖 |
| 你是 TypeScript/Node.js 技术栈 | OpenClaw | TypeScript 91.4%,npm 生态 |
| 需要快速上手、开箱即用 | OpenClaw | npm install + openclaw init 三步启动 |
| 需要深度定制 Agent 内部逻辑 | Hermes Agent | Python 代码更直观,无 Gateway 抽象层 |
八、总结:两条路线,一个终局
OpenClaw 和 Hermes Agent 代表了 Agent 框架的两种路线:
- OpenClaw :平台路线 ——做一个 Agent 的操作系统。Gateway 是内核,Channel Plugins 是驱动,Agent Runtime 是应用。多 Agent 是设计的第一天就内置的能力,25+ 消息通道让它"无处不在"。代价是 TypeScript 技术栈的复杂度、调试门槛高,以及安全模型把防线设在"用户确认"而非"系统拦截"上。
- Hermes Agent :工具路线 ——做一个可编程的 Agent 运行时。
run_conversation()是核心 API,装饰器是扩展接口,Python 生态是所有自定义的起点。深层语义记忆(Hindsight PG + pgvector)是它的护城河——当你需要 Agent 从 9216 条历史事实中 472ms 召回相关知识时,OpenClaw 的 grep + Markdown 做不到。代价是通道覆盖少、多 Agent 是后来者。
从商业视角看 :
- OpenClaw = 380K Star 的社区飞轮 → 生态繁荣 → 更多插件和 Skill → 正向循环
- Hermes Agent = Nous Research 的架构实验场 → Hindsight / Profile 隔离 / Cron 自动驾驶等独有能力 → 技术深度溢价
选哪个,取决于你的核心诉求:
- 「让 Agent 无处不在」→ OpenClaw
- 「让 Agent 记得更牢、做得更安全」→ Hermes Agent
或者,像本文的作者一样——两个都跑,各取其长。