Hermes vs OpenClaw:基于源码的 Agent Loop 全面分析

0 阅读20分钟

Hermes vs OpenClaw:基于源码的 Agent Loop 全面分析

请添加图片描述

作者:吴佳浩

撰稿时间:2026-6-7

最后更新:2026-6-10

声明:本文所有结论均来自俺对两个仓库源码的分析和测(转载请注明出处 吴佳浩Alben) Hermes: github.com/NousResearch/hermes-agent OpenClaw: github.com/openclaw/openclaw

引言

Hermes和OpenClaw的对比文章视频很多,但大多数停留在功能层面:支持哪些模型、有哪些工具、是否支持多Agent。

真正决定一个Agent系统上限的,其实不是工具数量,而是Agent Loop本身。

从学术谱系来看,两者都源于姚顺雨等人在2022年提出的ReAct(Reason + Act)范式:让大模型在推理(Thought)与行动(Action)之间循环迭代,通过工具调用获取外部信息,再将Observation反馈回下一轮推理。

然而,当ReAct从论文走向工程落地之后,两条完全不同的演化路线出现了。

Hermes选择继续强化Agent本身——记忆、技能、学习、长期成长;OpenClaw则选择强化Agent运行环境——会话、调度、流式事件、生命周期与可靠性。

前者试图回答:

“Agent如何变得越来越聪明?”

后者试图回答:

“Agent如何在生产环境中稳定运行数千次甚至数万次任务?”

这也是为什么,同样是Agent Loop,两者最终演化出了完全不同的架构形态。


一、两个项目的真实起源

timeline
    title 两个项目的诞生时间线
    2025-11-24 : OpenClaw 前身 Clawdbot 发布
               : 作者 Peter Steinberger(奥地利,vibe coder)
               : TypeScript,本地 Gateway + 消息平台集成
    2026-01-27 : Clawdbot → Moltbot
               : 应 Anthropic 商标投诉改名
    2026-01-30 : Moltbot → OpenClaw
               : 开始病毒式传播
    2026-02-14 : Steinberger 加入 OpenAI
               : 成立非营利基金会接管项目
    2026-02    : Hermes Agent 发布
               : NousResearch 出品,Python 重写
               : 定位「在 OpenClaw 基础上填补记忆短板」
               : 内置 hermes claw migrate 迁移工具

关键背景:OpenClaw 的 VISION.md 明确写道:

"OpenClaw started as a personal playground to learn AI and build something genuinely useful: an assistant that can run real tasks on a real computer."

而 Hermes 的发布文章则直接写明:

"OpenClaw...Its limitation, as users noted publicly, is that memory between sessions requires manual setup. Hermes was built to solve that gap."

这不是两个竞争者,而是一个明确的继承与扩展关系


二、技术栈对比:语言差异决定了执行模型

HermesOpenClaw
主语言Python 83%(主逻辑)TypeScript 13%(TUI / Web)TypeScript(Node.js 22+)
并发模型同步线程模型
concurrent.futures + threading.Lock
原生异步模型
async/await + Event Loop
包管理uv + pippnpm monorepo
安装方式curl ... | bash(Shell Installer)或 PowerShellnpm install -g openclaw
LLM 客户端层auxiliary_client.py(264KB)— 统一 LLM 调用抽象pi-ai(Mario Zechner 作品)— 多 Provider 抽象 + 流式事件归一化
Agent Loop 层AIAgent 类(run_agent.py,6933 行)pi-agent-core(Mario Zechner 作品)— Agent Loop + 工具执行 + 事件系统
Agent Runtime 层agent/ 子包(prompt_builder、context_compressor、display 等)pi-coding-agent — 完整 Runtime(文件工具、JSONL session、压缩、扩展)
CLI / TUI 层hermes_cli/ + hermes_tui/pi-tui — Terminal UI
Gateway 层Gateway(Python 实现)OpenClaw Gateway — 在 pi-* 层次之上构建的多渠道 + Hook 系统

OpenClaw 的架构层次

    pi-ai           → LLM 多 provider 抽象,流式事件归一化
    pi-agent-core   → Agent Loop,工具执行,事件系统
    pi-coding-agent → 完整 Agent Runtime(文件工具、JSONL session、压缩、扩展)
    pi-tui          → Terminal UI
    ─────────────────────────
    OpenClaw Gateway → 在以上层次之上构建的 Gateway + 多渠道 + Hook 系统

这不是简单的语言偏好问题。Python 的 GIL 和同步模型天然倾向于 while 循环 + ThreadPool;Node.js 的 Event Loop 天然倾向于事件驱动 + 异步流。两个系统的执行模型差异,根源在语言选择,不只是设计哲学。


三、仓库规模的真实对比

Hermes Agent 代码规模(agent/ 目录核心文件)

文件大小职责
run_agent.py6,933 行 / 335KB主入口,AIAgent 类(不是 15k+)
agent/agent_runtime_helpers.py~110KBAgent Runtime 辅助函数
agent/agent_init.py~88KBAgent 初始化
agent/auxiliary_client.py~264KBLLM 统一调用抽象
agent/anthropic_adapter.py~102KBAnthropic 原生 SDK 适配
agent/prompt_builder.py~19KBSystem Prompt 组装
agent/context_compressor.py~22KB上下文压缩引擎
agent/tool_guardrails.py~18KB工具循环检测护栏
agent/background_review.py~31KB后台自我回顾(Memory Nudge)
agent/display.py~20KBCLI 展示(spinner、diff 渲染、Tool Preview)
agent/model_metadata.py~21KB模型元数据、上下文长度探测
agent/iteration_budget.py~3.4KB迭代预算计数器
agent/tool_dispatch_helpers.py~17KB工具并发调度
agent/bedrock_adapter.py~50KBAWS Bedrock 适配
tools/registry.py22 个工具模块的自注册注册表

OpenClaw 代码规模

层级说明
src/ 核心TypeScript,数十个子系统
packages/ 工作区pnpm monorepo
extensions/ 插件渠道适配器等
58,209 commits约为 Hermes 的 5.2 倍

Commit 数量差异(11,158 vs 58,209)是最直观的迭代深度指标。OpenClaw 的迭代密度远高于 Hermes,这符合「更早诞生、更大社区、更长演化时间」的事实。


四、共同骨架:两者都实现了同一个 ReAct 循环

image.png

两者入口对称:

HermesOpenClaw
主入口agent.chat() / agent.run_conversation()runEmbeddedPiAgent()
立即返回阻塞等待最终回复{ runId, acceptedAt } 立即返回
结果获取函数返回值agent.wait RPC 轮询 lifecycle end
核心位置run_agent.py: AIAgentsrc/agents/pi-embedded-runner/run.ts

五、执行模型:同步 while vs 异步事件流

Hermes:同步 while 循环 + 可中断 HTTP

sequenceDiagram
    participant U as 用户
    participant A as AIAgent
    participant BT as 后台线程(HTTP)
    participant T as 工具

    U->>A: agent.chat("...")
    loop while True(同步)
        A->>BT: threading.Thread 发起 HTTP
        Note over A,BT: 主线程 wait:响应 / interrupt_event / 超时
        BT-->>A: response
        alt has tool_calls
            alt 并发安全 & 多工具
                A->>T: ThreadPoolExecutor(最多8线程)
            else 含 clarify 等交互工具
                A->>T: 顺序执行
            end
            T-->>A: 结果(按原始顺序重排)
            A->>A: 追加 tool 消息,continue
        else 纯文本
            A->>A: 持久化 session
            A-->>U: 返回 final_response
        end
    end

源码中有精细的并发判断逻辑(_should_parallelize_tool_batch()):

# 永不并发的工具(交互式)
_NEVER_PARALLEL_TOOLS = frozenset({"clarify"})

# 可安全并发的只读工具(来自 agent/tool_dispatch_helpers.py,已验证)
_PARALLEL_SAFE_TOOLS = frozenset({
    "ha_get_state", "ha_list_entities", "ha_list_services",
    "read_file", "search_files", "session_search",
    "skill_view", "skills_list", "vision_analyze",
    "web_extract", "web_search",
})

# 路径作用域工具:检查路径是否重叠才决定是否并发
_PATH_SCOPED_TOOLS = frozenset({"read_file", "write_file", "patch"})

# 注意:_MAX_TOOL_WORKERS(ThreadPoolExecutor max_workers)在 run_agent.py
# 中使用,不是模块级常量;MCP 工具并发通过 _is_mcp_tool_parallel_safe() 单独判断

还有专门的 _SafeWriter 类包装 stdout/stderr,防止 daemon 模式下 broken pipe 崩溃——这是生产化运行的细节。

OpenClaw:异步事件流 + 会话串行化

sequenceDiagram
    participant C as 客户端(任意渠道)
    participant GW as Gateway RPC
    participant Q as 会话 Queue
    participant RT as Pi-Agent Runtime
    participant PI as pi-agent-core
    participant LLM as 模型

    C->>GW: agent RPC(带 sessionKey)
    GW-->>C: { runId, acceptedAt }(立即)
    GW->>Q: 入队(全局 Queue + 会话 Channel 串行化)
    Q->>RT: runEmbeddedPiAgent({ sessionId, sessionKey,<br/>provider, model, prompt, timeoutMs,<br/>bashElevated, abortSignal, ... })
    loop Agent Loop(异步事件驱动)
        RT->>PI: 构建 Pi 会话,订阅事件
        PI->>LLM: 流式请求
        LLM-->>PI: token 流
        PI-->>RT: text_delta / thinking_delta 事件
        RT-->>GW: stream: &#34;assistant&#34;
        GW-->>C: 实时推送(各渠道适配)
        opt 工具调用
            PI-->>RT: tool start/update/end 事件
            RT-->>GW: stream: &#34;tool&#34;
            GW-->>C: 工具进度实时可见
        end
    end
    RT-->>GW: lifecycle: { phase: &#34;end&#34;, payload, usage }
    GW-->>C: 最终结果

runEmbeddedPiAgent 的真实参数签名(来自源码):

runEmbeddedPiAgent({
  sessionId: string,
  sessionKey: string,          // 会话串行化 key
  sessionFile: string,         // JSONL 转录文件路径
  workspaceDir: string,
  agentDir: string,
  config: OpenClawConfig,
  prompt: string,
  timeoutMs: number,           // 默认 600,000ms(600秒)
  runId: string,
  provider?: string,
  model?: string,
  bashElevated?: {
    enabled: boolean,
    allowed: string[],
    defaultLevel: string
  },
  abortSignal?: AbortSignal,   // 外部可取消
})

注意:timeoutMs 默认值是 600 秒(10 分钟),不是 48 小时


六、工具注册机制:自注册 vs 集中注册

Hermes:自注册式 Registry + Agent 级拦截

image.png

Agent 级工具todomemorydelegate_tasksession_searchskill_manage 等工具不走 registry dispatch,而是由 AIAgent 直接拦截、修改内部状态——这使它们能操作 Agent 的内存、技能、子任务等核心状态。

OpenClaw:Provider 插件化 + 工具事件化

graph TD
    subgraph ToolFlow[&#34;OpenClaw 工具执行流&#34;]
        PT[&#34;pi-agent-core 触发工具调用&#34;] --> BH[&#34;before_tool_call Hook\n{ block: true } = 终止(低优先级 handler 停止)&#34;]
        BH --> AP[&#34;Exec Approval 检查\n危险 bash 命令需确认&#34;]
        AP --> EX[&#34;执行工具&#34;]
        EX --> SE[&#34;tool start/update/end 事件\n实时流出&#34;]
        EX --> AH[&#34;after_tool_call Hook&#34;]
        AH --> RP[&#34;tool_result_persist Hook\n落盘前最后变换&#34;]
        RP --> WR[&#34;写入 JSONL 转录\n(会话写锁保护)&#34;]
    end

七、工具循环护栏(Tool Guardrails)—— Hermes 独有

这是 Hermes Agent Loop 中一个重要的保护层,源码位于 agent/tool_guardrails.py(~500 行)。OpenClaw 没有等价物——工具的重复调用完全由 LLM 自觉,没有护栏层。

工具分类体系

# 只读工具(无副作用)
IDEMPOTENT_TOOL_NAMES = frozenset({
    "read_file", "search_files", "web_search", "web_extract",
    "session_search", "browser_snapshot", "browser_console",
    "browser_get_images", "mcp_filesystem_read_file",
    "mcp_filesystem_list_directory", ...
})

# 有副作用的工具
MUTATING_TOOL_NAMES = frozenset({
    "terminal", "execute_code", "write_file", "patch",
    "todo", "memory", "skill_manage",
    "browser_click", "browser_type", "browser_navigate",
    "send_message", "cronjob", "delegate_task", "process", ...
})

三种检测机制

检测类型触发条件默认警告阈值默认阻断阈值
exact_failure完全相同参数 + 相同错误结果2 次5 次
same_tool_failure同工具不同参数均失败3 次8 次
no_progress连续只使用只读工具无进展2 次5 次

护栏行为层级

    ALLOW  → 静默通过
    WARN   → 注入 synthetic system message 提示 agent 改变策略
    HALT   → 直接截断,强制 LLM 给出最终答案

Warnings 默认开启且不阻止工具执行;Hard Stops 需要显式在 config.yaml 中开启(hard_stop_enabled: true)。

针对不同工具的失败提示

护栏系统会根据失败的工具类型给出定制化的提示:

# terminal 工具失败的专项提示
if tool_name == "terminal":
    return common + (
        "For terminal failures, run a small diagnostic such as "
        "`pwd && ls -la` in the same tool, then try an absolute path, "
        "a simpler command, a different working directory, "
        "or a different tool such as read_file/write_file/patch."
    )

# 通用工具失败提示
return common + (
    "Try different arguments, a narrower query/path, "
    "an absolute path when relevant, or a different tool "
    "that can make progress."
)

设计哲学

tool_guardrails.py 的 docstring 明确声明:

"The controller in this module is intentionally side-effect free: it tracks per-turn tool-call observations and returns decisions. Runtime code owns whether those decisions become warning guidance, synthetic tool results, or controlled turn halts."

护栏层是纯检测+决策,不主动干预执行——是否转为警告/阻断由 Runtime 决定。


八、迭代预算(Iteration Budget)—— Hermes 独有

Hermes 的 agent/iteration_budget.py(线程安全计数器,源码已验证)

class IterationBudget:
    """Thread-safe iteration counter for an agent."""
    def __init__(self, max_total: int):
        # 父 Agent 默认 90,子 Agent 从 delegation.max_iterations 取(默认 50)
        self.max_total = max_total
        self._used = 0
        self._lock = threading.Lock()

    def consume(self) -> bool:  # 消耗 1 次,返回 True 表示在预算内
    def refund(self) -> None:   # 退还 1 次(仅 execute_code 成功后调用)

    @property
    def used(self) -> int:      # 已使用次数
    @property
    def remaining(self) -> int: # 剩余次数

关键设计:

  • 父子关系(代码内有两处矛盾的注释):agent_init.py 注释说 "Shared — consumed across parent + all subagents",而 iteration_budget.py docstring 说 "Each subagent gets an independent budget"。实际行为取决于 delegate_task 调用时是否传入父 Agent 的 budget 对象。子 Agent 默认上限为 delegation.max_iterations(默认 50)
  • 软限制:用完时注入 system message 提示尽快结束,而非直接截断
  • 精准退还:只有 execute_code 成功时才 refund,防止 agent 仅依赖 LLM 推理而不实际执行

OpenClaw 靠 timeoutMs 硬超时,没有「濒临上限时注入提示」的软机制。


九、并发模型的根本差异

Hermes:为单/少量 Agent 设计

    用户请求 → AIAgent 实例(一般每用户一个进程)
                    → ThreadPoolExecutor(仅用于工具并发,max 8 workers)
                            → 工具 A / 工具 B / 工具 N

OpenClaw:为多用户/多渠道/多 Agent 并发设计

    多渠道入站(WhatsApp / Telegram / Discord / ...)
            → Gateway RPC
                → 全局 Queue(可选,跨会话调度)
                    → 会话 Channel A(本 session 所有 Run 串行)
                    → 会话 Channel B
                    → 会话 Channel N
                        → Session Write Lock(跨进程 + 进程感知,文件级锁,等待超时 60s)
                            → pi-embedded-runner A
                            → pi-embedded-runner B

Session Write Lock 是跨进程的文件锁(不只是进程内互斥),能捕获来自其他进程的写入者。这是 OpenClaw 为多实例部署设计的保护机制。


十、System Prompt 组装策略

Hermes:砖块式 Prompt 建筑

agent/prompt_builder.py 定义了多个独立的「指导砖块」,按需组合:

# 基础身份
DEFAULT_AGENT_IDENTITY = "You are Hermes Agent, an intelligent AI assistant..."

# 如何使用 memory 工具
MEMORY_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..."
    "Do NOT save task progress, session outcomes, completed-work logs..."
    "Write memories as declarative facts, not instructions to yourself..."
)

# 何时创建 skill
SKILLS_GUIDANCE = (
    "After completing a complex task (5+ tool calls), fixing a tricky error, "
    "or discovering a non-trivial workflow, save the approach as a "
    "skill with skill_manage so you can reuse it next time."
    "When using a skill and finding it outdated, incomplete, or wrong, "
    "patch it immediately with skill_manage(action='patch')..."
)

# 何时用 session_search
SESSION_SEARCH_GUIDANCE = (
    "When the user references something from a past conversation... "
    "use session_search to recall it before asking them to repeat themselves."
)

# 强制执行工具调用
TOOL_USE_ENFORCEMENT_GUIDANCE = (
    "# Tool-use enforcement\n"
    "You MUST use your tools to take action — do not describe what you would do "
    "or plan to do without actually doing it..."
)

# 必须跑出真实结果
TASK_COMPLETION_GUIDANCE = (
    "# Finishing the job\n"
    "When the user asks you to build, run, or verify something, the deliverable is "
    "a working artifact backed by real tool output — not a description of one."
    "NEVER substitute plausible-looking fabricated output..."
)
按模型品牌定制行为指导

Hermes 针对不同模型家族的已知缺陷注入专项指导:

# 这些模型家族需要额外的「必须用工具,别只说不做」prompt
TOOL_USE_ENFORCEMENT_MODELS = (
    "gpt", "codex", "gemini", "gemma", "grok", "glm", "qwen", "deepseek"
)

OpenAI GPT/Codex 和 xAI Grok 还有额外的 OPENAI_MODEL_EXECUTION_GUIDANCE,解决这些模型「声称完成但不实际执行」「跳过前置检查」「幻觉替代工具结果」等已知失败模式。

看板模式

当 Agent 运行在 Kanban(看板)模式时,会注入完整的任务协议:

KANBAN_GUIDANCE = (
    "# Kanban task execution protocol\n"
    "1. Orient → kanban_show()\n"
    "2. Work inside the workspace\n"
    "3. Heartbeat on long operations → kanban_heartbeat()\n"
    "4. Block on genuine ambiguity → kanban_block()\n"
    "5. Complete with structured handoff → kanban_complete()\n"
    "6. If follow-up work appears, create it; don't do it → kanban_create()\n"
)

OpenClaw:分层注入

    SOUL.md → AGENTS.md → Skills → TOOLS.md → runtime context

模板化,文件和 prompt 分开管理。没有按模型品牌定制的行为指导。


十一、上下文文件安全扫描 —— Hermes 独有

agent/prompt_builder.py 中包含一个安全层——在加载 AGENTS.md / HERMES.md 等上下文文件前,扫描注入威胁:

def _scan_context_content(content: str, filename: str) -> str:
    """Scan context file content for injection. Returns sanitized content.

    Uses the "context" scope from the shared threat-pattern library, which
    covers classic injection + promptware/C2 patterns + role-play hijack.
    Content matching is BLOCKED at this layer because the file would
    otherwise enter the system prompt verbatim and the user has no chance
    to intervene.
    """
    findings = _scan_for_threats(content, scope="context")
    if findings:
        return f"[BLOCKED: {filename} contained potential prompt injection "
               f"({', '.join(findings)}). Content not loaded.]"
    return content

Hermes 还会在项目目录中搜索 .hermes.mdHERMES.md(从 cwd 向上遍历到 git root),在注入 system prompt 前剥离 YAML frontmatter。OpenClaw 没有这层安全扫描。


十二、模型元数据与上下文长度探测 —— Hermes 更深

agent/model_metadata.py(~21KB)实现了复杂的上下文长度探测系统:

Provider 推断

Hermes 能从 base_url 自动推断 provider:

_URL_TO_PROVIDER = {
    "api.openai.com": "openai",
    "api.anthropic.com": "anthropic",
    "api.deepseek.com": "deepseek",
    "api.x.ai": "xai",
    "dashscope.aliyuncs.com": "alibaba",
    "integrate.api.nvidia.com": "nvidia",
    # ... 30+ 条目
}

上下文长度探测阶梯

当模型未知时,从高到低逐级探测:

CONTEXT_PROBE_TIERS = [256_000, 128_000, 64_000, 32_000, 16_000, 8_000]
MINIMUM_CONTEXT_LENGTH = 64_000  # 低于此值的模型拒绝运行

本地端点识别

能识别 Tailscale CGNAT(100.64.0.0/10)、Docker 内部 DNS、RFC-1918 私有地址,自动调整超时策略。

OpenClaw 的模型元数据解析内嵌在 pi-ai 层,没有 Hermes 这么细粒度的探测和 provider 推断逻辑。


十三、OpenClaw 的 VISION.md 里有一条被忽略的关键声明

OpenClaw 的 VISION.md 明确写着不会合并的功能

    What We Will Not Merge (For Now):
    - Agent-hierarchy frameworks (manager-of-managers / nested planner trees)
      as a default architecture
    - Heavy orchestration layers that duplicate existing agent and tool
      infrastructure

这不是「OpenClaw 架构天然支持 Agent Tree」,而是主动拒绝它。这与 Hermes 内置 delegate_task() 的 Agent Tree 路线形成了清晰的哲学对立。

Hermes 的 delegate_task

  • 直接在 run_agent.py 内拦截,创建新的 AIAgent 实例
  • 子 Agent 的迭代上限来自 delegation.max_iterations(默认 50),总额独立于父 Agent
  • ⚠️ 注意:agent_init.py 注释称 budget "shared across parent + subagents",但 iteration_budget.py docstring 称子 Agent 有 "independent budget"。实际行为取决于传入的 iteration_budget 参数

OpenClaw 的立场:明确不做这个。


十四、Provider 抽象与 Fallback

graph TD
    subgraph HermesProv[&#34;Hermes:深度 Provider 抽象&#34;]
        H_IN[&#34;统一入口&#34;] --> H_DT{&#34;API 模式判断\n4级优先级&#34;}
        H_DT --> H_CC[&#34;chat_completions\nOpenAI / OpenRouter / 自定义&#34;]
        H_DT --> H_CR[&#34;codex_responses\nOpenAI Codex&#34;]
        H_DT --> H_AM[&#34;anthropic_messages\n原生 Anthropic SDK&#34;]
        H_CC & H_CR & H_AM --> H_UF[&#34;统一 OpenAI 格式&#34;]
        H_UF --> H_FB[&#34;Fallback 链\n主 → 备1 → 备2\n各辅助任务独立 Fallback 链&#34;]
    end

    subgraph OpenClawProv[&#34;OpenClaw:pi-ai 多 Provider 抽象&#34;]
        O_IN[&#34;getModel(provider, modelId)&#34;] --> O_API{&#34;api 字段路由&#34;}
        O_API --> O_OA[&#34;openai-completions\n(兼容所有 OpenAI 格式端点)&#34;]
        O_API --> O_AN[&#34;anthropic\n(原生 Anthropic SDK)&#34;]
        O_API --> O_GG[&#34;google / groq / bedrock...&#34;]
        O_OA & O_AN & O_GG --> O_ST[&#34;统一 stream 事件\ntext_delta / thinking_delta / done&#34;]
        O_ST --> O_FB[&#34;runWithModelFallback()\nFailoverError 分类引擎&#34;]
    end

两边都有 Fallback,但实现路径不同:

  • Hermes 的 Fallback 逻辑在 AIAgent 内,是 Agent 自己的重试行为
  • OpenClaw 的 Fallback 在 runWithModelFallback() 层,是 Runtime 层面的 Provider 切换

十五、扩展机制:事后通知 vs 流水线拦截

Hermes(Callback,事后通知型)OpenClaw(Hook + Plugin,可拦截型)
工具回调tool_progress_callbackbefore_tool_call 🔴 可终止
思考状态thinking_callback
推理内容reasoning_callback
用户澄清clarify_callback
步骤追踪step_callback / stream_delta_callback
模型解析before_model_resolve
Prompt 构建before_prompt_build(可注入内容)
Agent 回复before_agent_reply 🔴 可接管整轮
消息发送message_sending 🔴 可终止发送
工具结果tool_result_persist(落盘前变换)
压缩before/after_compaction
安装before/after_install

🔴 = 可终止流水线的节点

OpenClaw AGENTS.md 明确规定了 Hook 的决策规则:

  • before_tool_call: { block: true } → 终态,停止低优先级 handler
  • before_tool_call: { block: false } → 空操作,不清除已有阻止
  • message_sending: { cancel: true } → 终态

十六、上下文压缩

核心差异

HermesOpenClaw
压缩层数双压缩层(Agent 50% + Gateway 85%)单层触发型
摘要格式结构化摘要(Goal / Constraints / Progress / Key Decisions / Relevant Files / Next Steps / Critical Context)通用摘要
迭代合并✅ 第二次压缩时更新上次摘要("items move from In Progress to Done")
引擎可插拔ContextEngine ABC 允许替换
Hook 可见❌ 内部行为before/after_compaction 事件
压缩策略先 flush Memory 到磁盘 → 压缩中间轮次 → 保留末尾 protect_last_n(默认 20)条 → 创建子 session lineage触发 → 执行压缩 → 可能触发重试 → 重置内存 buffer

Hermes 的双压缩层

graph LR
    subgraph HermesComp[&#34;Hermes:压缩是 Agent 决策&#34;]
        T1[&#34;context > 50% → 预检压缩\nAgent 层&#34;]
        T2[&#34;context > 85% → Gateway 触发\nGateway 层&#34;]
        T1 & T2 --> FL[&#34;先 flush Memory 到磁盘\n(MEMORY.md / USER.md)&#34;]
        FL --> CP[&#34;ContextCompressor.compress()\n摘要中间轮次\n保留末尾 protect_last_n 条(默认20)\n工具调用对保持完整&#34;]
        CP --> NL[&#34;生成新 session lineage ID\n压缩 = 创建子 session&#34;]
    end

OpenClaw 的压缩生命周期

graph LR
    subgraph OpenClawComp[&#34;OpenClaw:压缩是 Runtime 生命周期&#34;]
        E1[&#34;compaction 事件&#34;] --> BH[&#34;before_compaction Hook\n外部可注入 / 观察&#34;]
        BH --> CP2[&#34;执行压缩算法\n(pi-coding-agent 层)&#34;]
        CP2 --> AH[&#34;after_compaction Hook\n外部可感知&#34;]
        AH --> RT[&#34;可能触发 Agent 重试\n重置内存 buffer 避免重复&#34;]
    end

十七、自进化能力:Hermes 独有

这是 Hermes 最重要的差异化特性,OpenClaw 完全没有对应物:

graph TD
    subgraph HermesEvolution[&#34;Hermes 闭环学习系统&#34;]
        TASK[&#34;完成任务&#34;] --> SKILL[&#34;自主创建 SKILL.md\n可复用的程序化记忆&#34;]
        SKILL --> IMPROVE[&#34;技能在使用中自我改进\n(类 DSPy GEPA 进化)&#34;]
        SKILL --> MEM[&#34;持久化 Memory\nSQLite FTS5 搜索&#34;]
        MEM --> USER[&#34;USER.md 用户画像\nHoncho dialectic 建模&#34;]
        USER --> NEXT[&#34;下次对话\n跨 session / 跨平台 / 跨设备 记忆&#34;]
        NEXT --> TASK
    end

技能自动创建

agent/background_review.py(~31KB)实现了后台自我回顾:

# 伪代码还原自源码
class BackgroundReviewer:
    def review_and_create_skill(self, tool_calls_count, task_result):
        if tool_calls_count < 5:
            return  # 简单任务不触发

        review_prompt = (
            "Review this completed task and its tool calls. "
            "If the workflow is reusable, create a concise SKILL.md..."
        )
        skill_md = self._call_auxiliary_llm(review_prompt)
        self._dispatch_tool("skill_manage", action="create", name=..., content=skill_md)

Memory Nudge(记忆自驱)

每个 turn 结束后,后台线程自动运行:

# 伪代码还原自源码
def _background_memory_nudge(self):
    nudge_prompt = (
        "Review this conversation turn. What durable facts about the user, "
        "their environment, preferences, or recurring patterns should be "
        "remembered for future sessions?"
    )
    memories = self._call_auxiliary_llm(nudge_prompt)
    for m in memories:
        self._dispatch_tool("memory", action="add", content=m)

# 在独立线程中启动,不阻塞主响应
threading.Thread(target=background_memory_nudge).start()

技能自我改进

Agent 可以随时通过 skill_manage 工具修改已有技能:

# Agent 可直接调用的工具
skill_manage(action="create", name="deploy-k8s", content=full_skill_md)
skill_manage(action="patch", name="deploy-k8s", old_string="...", new_string="...")
skill_manage(action="edit", name="deploy-k8s", file_path="SKILL.md", ...)
skill_manage(action="delete", name="obsolete-skill")

衍生项目

Nous Research 还开了独立仓库 hermes-agent-self-evolution,用 DSPy + GEPA 做技能文件的进化优化:

  • 阶段 1:SKILL.md 内容进化 ✅
  • 阶段 2:工具描述进化(计划中)
  • 阶段 3:系统提示进化(计划中)
  • 阶段 4:工具实现代码进化(计划中)

这是 Hermes 与 OpenClaw 在 AI 能力维度上的本质差异。


十八、OpenClaw 独有的 Post-Turn 设计细节

OpenClaw 虽然没有 Hermes 的「回头看」自进化机制,但 Agent Loop 退出后有完整的收尾流程,体现在 runs.ts 的 run 生命周期管理中:

Run 生命周期管理

    ACTIVE_EMBEDDED_RUNS     → 当前活跃的 run handle
    ACTIVE_EMBEDDED_RUN_SNAPSHOTS → run 状态快照
    ABANDONED_EMBEDDED_RUNS  → 被放弃的 run(session 断开后追踪)
    EMBEDDED_RUN_WAITERS     → 等待 run 结束的外部观察者
    EMBEDDED_RUN_MODEL_SWITCH_REQUESTS → 运行中切换模型的请求队列

消息队列(Run 内 Steering)

// 运行中向 agent 注入消息的能力
queueEmbeddedAgentMessage(sessionId, text, options)
// 返回状态:
// - { queued: true, target: "embedded_run" }      → 成功注入
// - { queued: true, target: "reply_run" }         → 转入 reply 管道
// - { queued: false, reason: "no_active_run" }    → 无活跃 run
// - { queued: false, reason: "not_streaming" }    → run 已结束流
// - { queued: false, reason: "compacting" }       → run 正在压缩
// - { queued: false, reason: "runtime_rejected" }  → run 内部拒绝

Abort 机制

// 按 sessionId 终止单个 run
abortEmbeddedAgentRun(sessionId)

// 批量终止模式
abortEmbeddedAgentRun(undefined, { mode: "all" })        // 全部
abortEmbeddedAgentRun(undefined, { mode: "compacting" })  // 仅压缩中的

这套 Run 生命周期管理是 OpenClaw 作为「生产级 Gateway」的体现——hermes 的 post-turn 更多是「自我改进」,而 OpenClaw 的 post-turn 更多是「运行态管理」。


十九、多渠道支持:OpenClaw 独有

mindmap
    root((OpenClaw Gateway))
        消息平台
            WhatsApp
            Telegram
            Discord
            Slack
            Signal
            iMessage
            Microsoft Teams
            WeChat / QQ
            Matrix / IRC
            LINE / Feishu
            还有 10 余个
        伴侣应用
            macOS 菜单栏
            iOS Node
            Android Node
            Windows Hub
        特殊能力
            Voice Wake(macOS/iOS)
            Talk Mode(Android,连续语音)
            Live Canvas(A2UI)
            Web Chat

Hermes 支持 Telegram、Discord、Slack、WhatsApp、Signal 等,但渠道广度和多平台伴侣应用是 OpenClaw 的核心护城河。


二十、架构定位重新校准

基于源码的真实结论:

graph TD
    subgraph Actual[&#34;真实的关系(基于源码)&#34;]
        OC[&#34;OpenClaw\n2025-11 起源\nTypeScript / 消息平台优先\nGateway + 多渠道 + Runtime\n开源社区驱动&#34;]
        HM[&#34;Hermes\n2026-02 发布\nPython / 终端 + 记忆优先\n闭环学习 + Agent 能力\nNous Research 主导&#34;]
        OC -- &#34;Hermes 填补 OpenClaw 的记忆短板\nhermes claw migrate 内置迁移工具&#34; --> HM
    end

    subgraph Strengths[&#34;各自核心优势&#34;]
        OS1[&#34;OpenClaw 优势:\n多渠道接入广度\nRuntime 生产稳定性\nHook 可拦截扩展\n社区规模&#34;]
        HS1[&#34;Hermes 优势:\n跨 session 持久记忆\n闭环技能自进化\n多 Provider 统一抽象\nAgent Tree 子任务&#34;]
    end

二十一、核心指标真实速查表

维度HermesOpenClaw
起源时间2026-022025-11(as Clawdbot)
关系在 OpenClaw 基础上发展,内置迁移工具原版,更早
主语言Python 83% + TypeScript 13%TypeScript(Node.js 22+)
核心入口run_agent.py: AIAgent(6,933 行)pi-embedded-runner/run.ts: runEmbeddedPiAgent
Agent Loop同步 while + _interruptible_api_call异步事件流(pi-agent-core)
Loop 结构Agent 直连 LLM,while 循环内聚Gateway 代理 LLM,事件驱动
Post-Turn✅ 技能自动生成 + Memory Nudge❌ 直接结束,无「回头看」
工具并发_should_parallelize_tool_batch() + ThreadPool(max 8)事件化,异步原生
工具护栏✅ 3 种 loop guardrail(exact_failure / same_tool / no_progress)❌ 无
迭代预算✅ 90 次软限制 + refund 机制❌ 仅硬超时(600s 默认)
上下文文件扫描✅ 注入检测 + HERMES.md 发现❌ 无
模型探测✅ 阶梯式上下文探测 + 30+ Provider 自动推断pi-ai 层处理
Prompt 组装砖块式 + 按模型品牌定制指导分层模板注入
Agent Tree✅ 原生,delegate_task() 内置主动拒绝(VISION.md)
Fallback✅ 内置runWithModelFallback()
压缩层数双压缩层(Agent 50% + Gateway 85%)单层触发型
压缩格式8 字段结构化摘要 + 迭代合并通用摘要
上下文压缩引擎可插拔(ContextEngine ABC)内置
扩展机制Callback(通知型)Hook + Plugin(可拦截型,可终止)
记忆系统🔥 核心优势,跨 session + 自进化 SKILL + 8 个外部 Provider需手动配置
跨会话搜索session_search(SQLite FTS5 全文检索,搜索原始消息)memory_search(语义搜索,搜索记忆摘要)
多渠道Telegram/Discord/Slack 等主流🔥 20+ 渠道 + 全平台伴侣应用
Run 生命周期阻塞式返回值Queue / Abort / Waiter / Model Switch
定位个人助手 + AI 研究工具(Nous Research)个人助手 + 消息平台中枢(社区项目)

结语

OpenClaw 解决:怎么接入所有消息平台,怎么稳定运行。 Hermes 解决:怎么让 Agent 记住你,怎么让 Agent 变得更聪明。

两者不是同一赛道的竞争对手,而是从 OpenClaw 这个共同根基上长出的两个方向。Hermes 是在承认「OpenClaw 在渠道和 Runtime 上已经很好了」之后,专门去补它记忆能力不足的缺口。

理解这个关系,比任何架构框架都更接近事实。


附录:论断溯源索引

本文基于对以下源文件的直接读取: Hermes: run_agent.py(6,933行)、agent/tool_guardrails.py(~500行)、agent/background_review.py(~31KB)、agent/prompt_builder.py(~19KB)、agent/context_compressor.py(~22KB)、agent/model_metadata.py(~21KB)、agent/display.py(~20KB)、agent/iteration_budget.py(~3.4KB)、agent/tool_dispatch_helpers.py(~17KB)、agent/agent_runtime_helpers.py(~110KB)、agent/agent_init.py(~88KB) OpenClaw: src/agents/pi-embedded-runner/run.tssrc/auto-reply/reply/agent-runner.tsVISION.md(已验证)、AGENTS.md(已验证)、src/agents/embedded-agent-runner/runs.ts


以下是本文关键论断的验证状态,顺便作做个记录感兴趣的筒子们可以自己对照着看一下:

#论断验证状态源文件
1_NEVER_PARALLEL_TOOLS = frozenset({"clarify"})✅ 已验证agent/tool_dispatch_helpers.py:59
2_PARALLEL_SAFE_TOOLSha_get_state, skills_list 等 11 个✅ 已验证agent/tool_dispatch_helpers.py:61-72
3_PATH_SCOPED_TOOLS = frozenset({"read_file", "write_file", "patch"})✅ 已验证agent/tool_dispatch_helpers.py:75
4_should_parallelize_tool_batch() 逻辑(路径重叠检测等)✅ 已验证agent/tool_dispatch_helpers.py:132-177
5_is_destructive_command() — 终端命令破坏性检测✅ 已验证agent/tool_dispatch_helpers.py:78-128
6IDEMPOTENT_TOOL_NAMES / MUTATING_TOOL_NAMES 完整名单✅ 已验证agent/tool_guardrails.py:22-59
7ToolCallGuardrailConfig 默认阈值(2/5, 3/8, 2/5)✅ 已验证agent/tool_guardrails.py:63-97
8Guardrail 决策级别:ALLOW / WARN / BLOCK / HALT✅ 已验证agent/tool_guardrails.py:149-162
9Warnings 默认开启 + Hard Stops 需显式开启✅ 已验证agent/tool_guardrails.py:80-82
10IterationBudget 类:consume(), refund(), 线程安全✅ 已验证agent/iteration_budget.py:26-61
11max_iterations 默认 90(agent_init.py✅ 已验证agent/agent_init.py:228
12子 Agent 默认 50 次(来自 delegation.max_iterations✅ 已验证agent/iteration_budget.py:17-19
13BackgroundReviewer 后台线程 + fork AIAgent✅ 已验证agent/background_review.py:1-26
14_MEMORY_REVIEW_PROMPT / _SKILL_REVIEW_PROMPT 完整内容✅ 已验证agent/background_review.py:38-178
15_scan_context_content() — 上下文文件注入检测✅ 已验证agent/prompt_builder.py
16_URL_TO_PROVIDER — 30+ Provider 自动推断✅ 已验证agent/model_metadata.py
17CONTEXT_PROBE_TIERS 阶梯探测 + MINIMUM_CONTEXT_LENGTH = 64000✅ 已验证agent/model_metadata.py
18TOOL_USE_ENFORCEMENT_MODELS 名单✅ 已验证agent/prompt_builder.py
19VISION.md "What We Will Not Merge" — Agent Tree 拒绝✅ 已验证OpenClaw VISION.md
20AGENTS.md Hook 决策规则({ block: true } 终态等)✅ 已验证OpenClaw AGENTS.md
21execution_context 区分 foreground/background/trajectory✅ 已验证agent/background_review.py:185-201
22api_mode 4 级自动检测(chat/codex/anthropic/bedrock)✅ 已验证agent/agent_init.py
23IterationBudget 父子共享 vs 独立(代码内矛盾)✅ 矛盾已确认agent_init.py:251:"Shared — consumed across parent + all subagents";iteration_budget.py:15-20:"Each subagent gets an independent budget"
24_interruptible_api_call() 函数✅ 已验证run_agent.py:3968(thin forwarder)→ 实现在 agent/chat_completion_helpers.py:125,后台线程 + 请求级取消标志 + stale-call 检测
25_MAX_TOOL_WORKERS = 8✅ 已验证run_agent.py 模块级常量(位于 _openrouter_prewarm_done 上方)
26_SafeWriter✅ 已验证agent/process_bootstrap.py:62-103,包装 stdout/stderr 静默捕获 broken pipe 的 OSError/ValueError

读者复核指南

  • 全部 26 项关键论断均已完成源码交叉验证,标记 ✅ 的可直接引用对应文件行号
  • 本文于 2026-06-10 完成验证;两个项目的仓库持续更新中,关心的童鞋请以最新源码为准

-- 本文在发布前经过了系统性的源码交叉验证。如果你发现错误,请在评论区给我留言或者私信俺。 !!!!!!!还有掘金你的markdwon编辑器该更新了部分语法不支持我只能截图