开源 AI Agent 架构设计对比:Python 单体 vs TypeScript 插件化

以 Hermes Agent 与 OpenClaw 为案例,深入分析两种主流 Agent 架构范式在工具注册、扩展机制、依赖管理等维度的工程取舍。

一、引言

2026 年,开源 AI Agent 框架进入快速分化期。在"个人 AI 助手"这一细分赛道上,两个代表性项目------Nous Research 的 Hermes Agent (Python)与社区驱动的 OpenClaw(TypeScript)------走出了截然不同的架构路线。前者选择了 Python 单体架构配合自注册工具模式,后者则构建了一套基于 WebSocket 控制面的 TypeScript monorepo 插件体系。

两者解决的核心问题高度一致:连接多个消息平台、调度 LLM 完成工具调用、管理会话与记忆。但在"如何组织代码"这一工程问题上,它们的选择几乎处于光谱的两端。本文将从工具注册机制、扩展模型、依赖管理、贡献门槛四个维度展开对比分析。

二、核心循环:同步单线程 vs 异步事件驱动

2.1 Hermes Agent 的 Agent Loop

Hermes Agent 的核心对话循环位于 run_agent.pyAIAgent 类中,采用同步迭代模式:

python 复制代码
while api_call_count < self.max_iterations and self.iteration_budget.remaining > 0:
    response = client.chat.completions.create(
        model=model, messages=messages, tools=tool_schemas
    )
    if response.tool_calls:
        for tool_call in response.tool_calls:
            result = handle_function_call(tool_call.name, tool_call.args, task_id)
            messages.append(tool_result_message(result))
        api_call_count += 1
    else:
        return response.content

这一设计的特点是线性可预测 :每一轮 LLM 调用 → 工具执行 → 结果回传 → 下一轮调用,整个流程在单线程内完成。消息格式遵循 OpenAI 标准(system/user/assistant/tool),reasoning 内容存储在 assistant_msg["reasoning"] 中。

2.2 OpenClaw 的 Gateway 控制面

OpenClaw 采用了不同的架构思路。其核心是一个 WebSocket 控制面(Gateway),所有客户端(CLI、消息平台适配器、macOS/iOS/Android 应用)通过 WebSocket 连接到 Gateway,由 Gateway 统一调度 Agent 运行时(称为 "Pi agent"):

复制代码
WhatsApp / Telegram / Slack / Discord / ...
               │
               ▼
┌───────────────────────────────┐
│            Gateway            │
│       (control plane)         │
│     ws://127.0.0.1:18789      │
└──────────────┬────────────────┘
               │
               ├─ Pi agent (RPC)
               ├─ CLI
               ├─ WebChat UI
               └─ macOS / iOS / Android nodes

Gateway 不仅是消息路由器,还承担了会话管理、工具注册、事件分发、Cron 调度等职责。这种设计天然支持多客户端并发接入,但也引入了更高的架构复杂度。

三、工具注册机制:自注册 vs 插件 SDK

3.1 Hermes Agent 的自注册模式

Hermes Agent 的工具系统围绕一个中央 ToolRegistry 单例构建(tools/registry.py)。每个工具文件在被 import 时自动调用 registry.register() 完成注册:

python 复制代码
# tools/registry.py 核心注册逻辑
def register(self, name, toolset, schema, handler, check_fn=None,
             requires_env=None, is_async=False, emoji="", 
             max_result_size_chars=None):
    """Register a tool. Called at module-import time by each tool file."""
    with self._lock:
        self._tools[name] = ToolEntry(
            name=name, toolset=toolset, schema=schema,
            handler=handler, check_fn=check_fn, ...
        )
        if check_fn and toolset not in self._toolset_checks:
            self._toolset_checks[toolset] = check_fn

一个典型的工具文件结构如下:

python 复制代码
# tools/my_tool.py
from tools.registry import registry

def my_tool(param1: str, param2: int = 10, **kwargs) -> str:
    result = do_work(param1, param2)
    return json.dumps(result)

MY_TOOL_SCHEMA = {
    "type": "function",
    "function": {
        "name": "my_tool",
        "description": "...",
        "parameters": { ... },
    },
}

registry.register(
    name="my_tool",
    toolset="my_toolset",
    schema=MY_TOOL_SCHEMA,
    handler=lambda args, **kw: my_tool(**args, **kw),
    check_fn=_check_requirements,
)

整个依赖链清晰且单向:

复制代码
tools/registry.py  (无依赖 --- 被所有工具文件导入)
       ↑
tools/*.py  (每个文件在 import 时调用 registry.register())
       ↑
model_tools.py  (导入 tools/registry + 触发工具发现)
       ↑
run_agent.py, cli.py, batch_runner.py

调度同样简洁------dispatch() 方法根据工具名查找 handler 并执行,异步 handler 通过 _run_async() 桥接:

python 复制代码
def dispatch(self, name, args, **kwargs):
    entry = self.get_entry(name)
    if not entry:
        return json.dumps({"error": f"Unknown tool: {name}"})
    try:
        if entry.is_async:
            from model_tools import _run_async
            return _run_async(entry.handler(args, **kwargs))
        return entry.handler(args, **kwargs)
    except Exception as e:
        return json.dumps({"error": f"Tool execution failed: {type(e).__name__}: {e}"})

这种模式的优势在于零配置、零仪式 :新增一个工具只需创建一个 Python 文件,在文件末尾调用 register(),然后在 model_tools.py_modules 列表中添加一行 import。不需要配置文件、不需要注册表、不需要构建步骤。

3.2 OpenClaw 的插件 SDK 体系

OpenClaw 走了一条完全不同的路。其扩展机制基于一套正式的 Plugin SDK,通过 openclaw/plugin-sdk/* 提供超过 150 个子路径导出(从 package.jsonexports 字段可以看到完整列表)。

一个典型的 Channel 插件注册流程如下:

typescript 复制代码
// extensions/telegram/index.ts
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";

export default defineChannelPluginEntry({
  id: "telegram",
  name: "Telegram",
  description: "Telegram bot integration",
  plugin: telegramPlugin,
  configSchema: telegramConfigSchema,
  setRuntime: (runtime) => { ... },
  registerFull: (api) => {
    api.registerTool((ctx) => createTelegramTool(ctx), { names: ["telegram_send"] });
  },
});

插件通过 api.registerChannel()api.registerTool()api.registerMemoryCapability() 等方法向 Gateway 注册能力。每个插件有独立的 openclaw.plugin.json 清单文件,声明元数据、依赖和配置 schema。

OpenClaw 的 extensions/ 目录下有超过 100 个插件目录,涵盖了 LLM 提供商(OpenAI、Anthropic、Google、Mistral 等)、消息平台、记忆后端、媒体生成等各个维度。这种架构的优势在于强隔离和可组合性:每个插件是独立的包,有明确的公共 API 边界,第三方开发者可以通过 npm 分发自己的插件。

3.3 对比小结

维度 Hermes Agent(自注册) OpenClaw(Plugin SDK)
注册方式 import 时自动注册 通过 SDK API 显式注册
工具定义 单文件自包含(schema + handler + register) 插件包(manifest + entry + runtime)
新增工具成本 1 个文件 + 1 行 import 1 个目录 + manifest + entry + 可能的构建配置
隔离性 弱(共享进程空间) 强(独立包边界,SDK 契约)
第三方分发 通过 Skills Hub(Markdown 指令) 通过 npm / ClawHub(代码包)
类型安全 运行时检查 编译时类型检查(TypeScript)

四、扩展模型:Skills vs Plugins

两个项目对"扩展"的理解存在根本差异。

4.1 Hermes Agent 的 Skills 优先策略

Hermes Agent 的 CONTRIBUTING.md 明确指出:"Should it be a Skill or a Tool? The answer is almost always skill."

Skills 是 Markdown 文件(SKILL.md),包含 YAML 前置元数据和自然语言指令。Agent 在运行时将 Skill 内容注入系统提示词,由 LLM 解释执行:

markdown 复制代码
---
name: arxiv-search
description: Search and analyze arXiv papers
version: 1.0.0
platforms: [macos, linux]
metadata:
  hermes:
    requires_toolsets: [terminal, web]
---

# arXiv Search

## When to Use
When the user asks about academic papers or research...

## Procedure
1. Use web_search to query arXiv API...
2. Parse the XML response...

这种设计的哲学是:大多数能力可以通过"指令 + 现有工具"组合实现,不需要写代码。只有当能力需要精确的二进制处理、流式事件或复杂的认证流程时,才应该写成 Tool。

Skills 还支持条件激活(fallback_for_toolsetsrequires_toolsets)、平台限制(platforms: [macos])、安全设置(required_environment_variables),以及 Agent 自主创建------这是 Hermes 闭环学习系统的一部分。

4.2 OpenClaw 的代码级插件

OpenClaw 的扩展是真正的代码包。以记忆插件为例,memory-core 插件包含:

复制代码
extensions/memory-core/
├── src/
│   ├── cli.ts
│   ├── dreaming.ts          # 短期记忆提升为长期记忆
│   ├── dreaming-command.ts
│   ├── flush-plan.ts        # 记忆刷新策略
│   ├── prompt-section.ts    # 系统提示词构建
│   ├── tools.ts             # memory_search, memory_get 工具
│   └── memory/
│       └── provider-adapters.ts
├── api.ts
├── index.ts                 # 插件入口
├── openclaw.plugin.json     # 清单文件
├── package.json
└── tsconfig.json

插件通过 definePluginEntry() 注册,可以注册工具、CLI 命令、记忆能力、Gateway 方法等多种能力类型。这种模式的优势在于精确控制:每个插件的行为是确定性的代码逻辑,而非 LLM 对自然语言指令的概率性解释。

4.3 取舍分析

Hermes 的 Skills 模式降低了扩展创建的门槛(不需要写代码),但引入了 LLM 解释的不确定性。OpenClaw 的 Plugin 模式保证了行为的确定性,但提高了开发成本和维护负担。

从实际效果看,Hermes 的 skills/ 目录包含约 30 个 Skill,覆盖研究、生产力、开发等场景;OpenClaw 的 extensions/ 目录包含超过 100 个插件,但其中大部分是 LLM 提供商适配器和消息平台适配器,而非用户可见的"能力扩展"。

五、依赖管理与构建复杂度

5.1 Hermes Agent:pip install 即用

Hermes Agent 使用标准的 pyproject.toml 管理依赖,通过 optional extras 实现按需安装:

toml 复制代码
[project]
dependencies = [
  "openai>=2.21.0,<3",
  "anthropic>=0.39.0,<1",
  "rich>=14.3.3,<15",
  "prompt_toolkit>=3.0.52,<4",
  # ...
]

[project.optional-dependencies]
messaging = ["python-telegram-bot[webhooks]>=22.6,<23", "discord.py[voice]>=2.7.1,<3", ...]
voice = ["faster-whisper>=1.0.0,<2", "sounddevice>=0.4.6,<1", ...]
dev = ["pytest>=9.0.2,<10", ...]

安装命令简洁明了:uv pip install -e ".[all]"pip install -e ".[messaging,cron]"。没有构建步骤,没有编译过程,clone 后即可运行。

5.2 OpenClaw:monorepo 构建链

OpenClaw 是一个 pnpm workspace monorepo,包含主包、UI 包、Plugin SDK 包、100+ 个 extension 包。构建流程涉及:

bash 复制代码
pnpm install
pnpm ui:build        # 构建 Web UI
pnpm build           # TypeScript 编译,生成 dist/

package.json 中的 exports 字段列出了超过 150 个子路径导出,每个对应一个 Plugin SDK 入口点。这种精细的模块划分为类型安全和树摇优化提供了基础,但也意味着更长的构建时间和更复杂的依赖解析。

scripts/ 目录的规模可以窥见这种复杂度:OpenClaw 有超过 200 个构建/检查/测试脚本,涵盖架构边界检查(check-architecture-smells.mjs)、导入边界验证(check-extension-package-tsc-boundary.mjs)、插件 SDK 导出同步(sync-plugin-sdk-exports.mjs)等。这些脚本本身就是一个工程系统。

六、贡献门槛与开发者体验

6.1 新增一个工具的完整流程

Hermes Agent:

  1. 创建 tools/my_tool.py,编写 handler + schema + registry.register()
  2. model_tools.py_modules 列表添加 "tools.my_tool"
  3. 如果是新 toolset,在 toolsets.py 添加定义
  4. 完成

OpenClaw:

  1. 创建 extensions/my-tool/ 目录
  2. 编写 openclaw.plugin.json 清单
  3. 编写 index.ts 入口,使用 definePluginEntry() 注册
  4. 编写工具实现,遵循 Plugin SDK 类型约束
  5. 配置 tsconfig.jsonpackage.json
  6. 在构建系统中注册新包
  7. 运行边界检查确保不违反导入规则
  8. 完成

6.2 调试体验

Hermes Agent 的调试路径是线性的:cli.pyrun_agent.pymodel_tools.pytools/registry.py → 具体工具文件。所有代码在同一进程空间,可以直接设断点。

OpenClaw 的调试需要理解 Gateway WebSocket 协议、插件激活生命周期、RPC 调用链。当问题出现在插件边界时,需要在多个包之间跳转。

七、结论

Hermes Agent 和 OpenClaw 的架构选择反映了两种不同的工程哲学:

Hermes Agent 选择了"简单直接"------Python 单体、自注册工具、Markdown Skills、线性调用链。这种架构的代价是弱隔离和有限的类型安全,但换来了极低的认知负担和贡献门槛。对于一个以"自我进化"为核心卖点的 Agent 框架,这种选择是合理的:当 Agent 自己可以创建 Skills 时,扩展机制的简单性比工程严谨性更重要。

OpenClaw 选择了"工程化治理"------TypeScript monorepo、正式的 Plugin SDK、严格的导入边界、150+ 个类型化子路径导出。这种架构的代价是高复杂度和陡峭的学习曲线,但换来了强类型安全、明确的 API 契约和成熟的第三方生态。对于一个以"平台完备性"为目标的产品,这种选择同样合理。

两种路线没有绝对的优劣。选择哪种架构,取决于项目的核心目标是"让 Agent 更聪明"还是"让平台更完善"。


本文基于 Hermes Agent v0.9.0 和 OpenClaw v2026.4.14-beta.1 的开源代码分析撰写。两个项目均采用 MIT 许可证。

相关推荐
冷色系里的一抹暖调3 小时前
OpenClaw Docker部署避坑指南:服务启动成功但网页打不开?
人工智能·docker·容器·openclaw
曹牧3 小时前
自动编程AI落地方案‌
人工智能
天云数据3 小时前
Harness革命:企业级AI从“失控野马”到“价值引擎”的跃迁
人工智能
汽车仪器仪表相关领域3 小时前
NHVOC-70系列固定污染源挥发性有机物监测系统:精准破局工业VOCs监测痛点,赋能环保合规升级
大数据·人工智能·安全性测试
克里斯蒂亚诺·罗纳尔达3 小时前
智能体学习23——资源感知优化(Resource-Aware Optimization)
人工智能·学习
橙露4 小时前
特征选择实战:方差、卡方、互信息法筛选有效特征
人工智能·深度学习·机器学习
TechMasterPlus4 小时前
LangGraph 实战指南:构建状态驱动的 LLM 应用架构
人工智能·架构
海森大数据4 小时前
数据与特征“协同进化”:机器学习加速发现高性能光合成过氧化氢COF催化剂
人工智能·机器学习
xiaotao1314 小时前
01-编程基础与数学基石: Python核心数据结构完全指南
数据结构·人工智能·windows·python