1. 引言

在 AI Agent 框架的演进中,Hermes 和 OpenClaw 作为两个备受关注的开源项目,各自提出了独特的 Agent Loop 实现方案。本文将从源码层面深入剖析两者的核心架构、循环机制、工具调用策略和状态管理方式,帮助开发者理解其设计哲学与工程实践差异。

2. 项目概览与设计哲学

2.1 Hermes 简介

Hermes 是一个轻量级、模块化的 AI Agent 框架,其核心设计理念是「可组合的推理循环」。Hermes 的 Agent Loop 围绕「感知-推理-行动」三阶段模型构建,强调将 LLM 调用、工具执行和状态管理解耦为独立组件。

源码仓库地址:https://github.com/NousResearch/Hermes

2.2 OpenClaw 简介

OpenClaw 是一个面向复杂任务编排的 Agent 框架,其设计哲学是「确定性执行路径 + 动态分支」。OpenClaw 的 Agent Loop 采用「规划-执行-验证」的闭环结构,特别强调对工具调用结果的校验和异常恢复机制。

源码仓库地址:GitHub - openclaw/openclaw: Your own personal AI assistant. Any OS. Any Platform. The lobster way. 🦞 · GitHub

3. Agent Loop 核心架构对比

3.1 Hermes 的 Agent Loop 源码分析

Hermes 的核心循环位于 hermes/agent/loop.py 中的 AgentLoop 类。其主循环逻辑如下:

class AgentLoop:
    def __init__(self, llm, tool_registry, memory, max_steps=10):
        self.llm = llm
        self.tool_registry = tool_registry
        self.memory = memory
        self.max_steps = max_steps
        self.state = AgentState()
async def run(self, task: str) -> AgentResult:
    self.state.reset()
    self.memory.add("user", task)
for step in range(self.max_steps):
    # 阶段1:感知 - 构建上下文
    context = self._build_context()
# 阶段2:推理 - LLM 生成下一步行动
action = await self._reason(context)
阶段3:行动 - 执行工具或返回结果
if action.type == "final":
return AgentResult(
output=action.content,
steps=step + 1,
token_usage=self.state.token_usage
)
tool_result = await self._execute_tool(action)
self.memory.add("assistant", action.content)
self.memory.add("tool", tool_result)
return AgentResult(output="Max steps reached", steps=self.max_steps)</code></pre>
关键设计点:
线性步进循环:每一步都严格遵循感知→推理→行动的顺序,没有提前终止或跳步机制。
内存驱动:所有交互历史都存储在 memory 中,每次循环都重新构建完整上下文。
工具注册表:通过 tool_registry 统一管理工具,支持动态注册和参数校验。
3.2 OpenClaw 的 Agent Loop 源码分析
OpenClaw 的核心循环位于 openclaw/engine/executor.py 中的 PlanExecutor 类。其实现更为复杂:
class PlanExecutor:
def init(self, planner, executor, verifier, max_retries=3):
self.planner = planner
self.executor = executor
self.verifier = verifier
self.max_retries = max_retries
self.execution_graph = ExecutionGraph()
async def execute(self, goal: str) -> ExecutionResult:
阶段1:规划 - 生成执行计划
plan = await self.planner.create_plan(goal)
self.execution_graph.build_from_plan(plan)
阶段2:执行 - 按图遍历
while not self.execution_graph.is_complete():
node = self.execution_graph.next_ready_node()
if node is None:
break
for attempt in range(self.max_retries):
result = await self.executor.execute_node(node)
# 阶段3:验证 - 校验执行结果
verification = await self.verifier.verify(
    node, result
)

if verification.is_valid:
    self.execution_graph.mark_completed(node, result)
    break
else:
    if attempt < self.max_retries - 1:
        node = await self._revise_node(
            node, verification.feedback
        )
    else:
        self.execution_graph.mark_failed(node, result)
return ExecutionResult(
graph=self.execution_graph,
success=self.execution_graph.all_succeeded()
)</code></pre>
关键设计点:
图结构执行:任务被建模为有向无环图(DAG),节点间存在依赖关系,支持并行执行。
规划-执行-验证三阶段:每个节点执行后都经过验证,失败时可重试或修正。
重试与恢复机制:内置 max_retries 和节点修正逻辑,增强了鲁棒性。
4. 工具调用机制深度对比
4.1 Hermes 的工具调用
Hermes 的工具调用通过 ToolRegistry 实现,源码位于 hermes/tools/registry.py:
class ToolRegistry:
def init(self):
self._tools: dict[str, Tool] = {}
def register(self, tool: Tool):
schema = self._generate_schema(tool)
self._tools[tool.name] = tool
return schema  # 返回给 LLM 的 JSON Schema
async def execute(self, name: str, args: dict) -> Any:
tool = self._tools.get(name)
if not tool:
raise ToolNotFoundError(name)
validated_args = tool.validate(args)  # Pydantic 校验
return await tool.fn(**validated_args)</code></pre>
Hermes 将工具 Schema 直接注入 LLM 的 system prompt 中,LLM 以 JSON 格式返回工具调用指令。这种方式的优点是简单直接,缺点是当工具数量增多时 prompt 会变得臃肿。
4.2 OpenClaw 的工具调用
OpenClaw 的工具系统更为分层,源码位于 openclaw/tools/manager.py:
class ToolManager:
def init(self):
self.categories: dict[str, list[Tool]] = {}
self.execution_context = ExecutionContext()
async def resolve_tool(self, intent: str) -&gt; Tool:
语义匹配:根据意图描述匹配最合适的工具
embeddings = await self._embed_intent(intent)
candidates = self._semantic_search(embeddings, top_k=3)
return self._select_best(candidates, intent)
async def execute_with_context(self, tool: Tool, args: dict):
上下文注入:自动传递当前执行上下文
enriched_args = {
**args,
"session_id": self.execution_context.session_id,
"previous_output": self.execution_context.last_output
}
return await tool.execute(enriched_args)</code></pre>
OpenClaw 引入了语义工具匹配和上下文自动注入机制,使得 LLM 不需要记住所有工具名称,只需描述意图即可。同时,执行上下文会自动传递给工具,减少了参数传递的复杂度。
5. 状态管理与记忆机制
5.1 Hermes 的状态管理
Hermes 使用 AgentState 和 Memory 两个独立组件:
@dataclass
class AgentState:
step: int = 0
token_usage: int = 0
last_action: str | None = None
last_result: Any = None
class Memory:
def init(self, max_tokens: int = 4096):
self.messages: list[dict] = []
self.max_tokens = max_tokens
def add(self, role: str, content: str):
self.messages.append({"role": role, "content": content})
self._trim_if_needed()  # 超出 token 限制时裁剪早期消息
def get_context(self) -&gt; list[dict]:
return self.messages[-self._context_window:]</code></pre>
Hermes 的状态管理相对简单:AgentState 记录当前步数和 token 消耗,Memory 维护消息历史并支持自动裁剪。这种设计适合短对话场景,但在长任务中可能丢失早期上下文。
5.2 OpenClaw 的状态管理
OpenClaw 的状态管理更为复杂,使用 ExecutionGraph 和 ContextStore:
class ExecutionGraph:
def init(self):
self.nodes: dict[str, ExecutionNode] = {}
self.edges: list[tuple[str, str]] = []
self.global_state: dict = {}
def build_from_plan(self, plan: Plan):
for step in plan.steps:
node = ExecutionNode(
id=step.id,
action=step.action,
dependencies=step.depends_on,
retry_count=0
)
self.nodes[step.id] = node
for dep in step.depends_on:
self.edges.append((dep, step.id))
def next_ready_node(self) -&gt; ExecutionNode | None:
拓扑排序:找出所有依赖已完成的节点
for node in self.nodes.values():
if node.status == NodeStatus.PENDING:
deps_done = all(
self.nodes[dep].status == NodeStatus.COMPLETED
for dep in node.dependencies
)
if deps_done:
return node
return None</code></pre>
OpenClaw 的 ContextStore 还支持跨节点的数据共享:
class ContextStore:
def init(self):
self._store: dict[str, Any] = {}
self._locks: dict[str, asyncio.Lock] = {}
async def set(self, key: str, value: Any, ttl: int = 300):
async with self._locks.setdefault(key, asyncio.Lock()):
self._store[key] = {
"value": value,
"expires_at": time.time() + ttl
}
async def get(self, key: str) -&gt; Any | None:
entry = self._store.get(key)
if entry and entry["expires_at"] &gt; time.time():
return entry["value"]
return None</code></pre>
OpenClaw 的状态管理支持 DAG 依赖追踪、并发安全的数据共享和 TTL 过期机制,适合复杂、长时间运行的任务。
6. 错误处理与异常恢复
6.1 Hermes 的错误处理
Hermes 的错误处理相对简单,主要在工具执行层面:
async def _execute_tool(self, action: Action) -> ToolResult:
try:
result = await self.tool_registry.execute(
action.tool_name, action.args
)
return ToolResult(success=True, data=result)
except ToolNotFoundError:
return ToolResult(
success=False,
error=f"Tool '{action.tool_name}' not found"
)
except ValidationError as e:
return ToolResult(
success=False,
error=f"Invalid arguments: {e}"
)
except Exception as e:
return ToolResult(
success=False,
error=f"Execution failed: {str(e)}"
)
Hermes 将错误信息返回给 LLM,由 LLM 决定下一步行动。这种「交给 LLM 处理」的方式灵活但不可控,LLM 可能陷入重复尝试的循环。
6.2 OpenClaw 的错误处理
OpenClaw 实现了更完善的错误恢复策略:
class ErrorRecoveryStrategy:
RETRY = "retry"
FALLBACK = "fallback"
SKIP = "skip"
ABORT = "abort"
class RecoveryManager:
def init(self):
self.strategies: dict[str, ErrorRecoveryStrategy] = {
"timeout": ErrorRecoveryStrategy.RETRY,
"rate_limit": ErrorRecoveryStrategy.RETRY,
"auth_error": ErrorRecoveryStrategy.FALLBACK,
"not_found": ErrorRecoveryStrategy.SKIP,
"internal_error": ErrorRecoveryStrategy.ABORT
}
async def handle_error(
self, node: ExecutionNode, error: Exception
) -&gt; RecoveryAction:
error_type = self._classify_error(error)
strategy = self.strategies.get(
error_type, ErrorRecoveryStrategy.RETRY
)
if strategy == ErrorRecoveryStrategy.RETRY:
if node.retry_count &amp;lt; self.max_retries:
return RecoveryAction(
action="retry",
delay=2 ** node.retry_count  # 指数退避
)
return RecoveryAction(action="fallback")
elif strategy == ErrorRecoveryStrategy.FALLBACK:
fallback_tool = await self._find_fallback(node.action)
return RecoveryAction(
action="fallback",
fallback_tool=fallback_tool
)
elif strategy == ErrorRecoveryStrategy.SKIP:
return RecoveryAction(action="skip")
return RecoveryAction(action="abort")&lt;/code&gt;&lt;/pre&gt;
OpenClaw 的错误处理更加工程化:按错误类型分类、支持指数退避重试、提供回退工具机制,并且可以跳过非关键节点继续执行。
7. 性能与可扩展性对比
维度
Hermes
OpenClaw
循环模型
线性步进
DAG 图执行
并行能力
无原生并行
支持节点级并行
上下文窗口
滑动窗口裁剪
结构化上下文存储
工具匹配
名称精确匹配
语义匹配 + 意图解析
错误恢复
LLM 自主决策
策略驱动恢复
状态持久化
内存存储
支持 TTL 和持久化
扩展性
插件式工具注册
分层架构 + 中间件
学习曲线
低(API 简洁)
中高(概念较多)
8. 适用场景与选型建议
8.1 选择 Hermes 的场景
快速原型开发:需要快速搭建 Agent 验证想法时,Hermes 的简洁 API 可以大幅降低开发成本。
简单问答 Agent:任务流程固定、工具数量少(5 个以内)的场景。
教育学习:作为学习 Agent 框架原理的入门项目,代码量小、逻辑清晰。
资源受限环境:对内存和计算资源要求较低,适合边缘设备或轻量部署。
8.2 选择 OpenClaw 的场景
复杂工作流编排:任务包含多个依赖步骤、需要并行执行或条件分支的场景。
高可靠性要求:金融、医疗等对错误容忍度低的领域,需要完善的错误恢复机制。
大规模工具生态:工具数量超过 20 个时,OpenClaw 的语义匹配优势明显。
长时间运行任务:需要状态持久化、断点续传或任务审计的场景。
9. 总结
Hermes 和 OpenClaw 代表了 Agent Loop 设计的两种不同哲学:Hermes 追求简洁和灵活性,将决策权交给 LLM;OpenClaw 追求确定性和鲁棒性,通过工程手段弥补 LLM 的不确定性。从源码层面看,Hermes 的代码更易读、适合快速上手,而 OpenClaw 的架构更健壮、适合生产环境。
在实际选型时,建议根据任务的复杂度、可靠性要求和团队的技术栈偏好来决定。对于大多数中小规模应用,Hermes 的轻量方案已经足够;而对于企业级、多步骤、高可靠性的 Agent 系统,OpenClaw 的工程化设计更具优势。
Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐