OpenClaw与Hermes:Agent框架协议兼容性深度解析

📅 2026/7/11 20:24:00
OpenClaw与Hermes:Agent框架协议兼容性深度解析
1. 项目概述这不是一场“抄袭之战”而是一次开源社区的集体压力测试“OpenClaw与Hermes Agent一场开源Agent框架的抄袭之战”——这个标题在技术圈刷屏时我正蹲在公司机房给一台跑推理的A10服务器换散热硅脂。手还没擦干净钉钉就弹出七八条消息全是同事甩来的截图和问号“这俩到底谁抄谁”“GitHub上PR都打起来了咱还能不能安心用”“我们刚搭好的Agent调度层要不要连夜切框架”说实话看到标题第一反应是皱眉。不是因为内容敏感而是这个词太重了。“抄袭”在开源世界里几乎等同于社区死刑判决书。但翻完OpenClaw和Hermes的GitHub仓库、commit历史、文档结构、核心模块设计图再对照双方早期issue讨论、架构演进时间线我确认了一件事这根本不是法律意义上的抄袭而是一场典型的开源同源演化冲突——两个团队在高度相似的技术约束下独立选择了几乎一致的解法路径结果撞型了。核心关键词“OpenClaw”“Hermes”“Agent”“开源”“框架”背后真正要解决的问题非常朴素如何让AI智能体像人一样能调用工具、切换上下文、记住对话历史、处理多步骤任务且整个过程可调试、可监控、可灰度发布。这不是玄学是工程问题。OpenClaw用TypeScriptNode.js构建中央Gateway做消息路由和会话管理Hermes则用Rust重写了核心Runtime但对外暴露的Agent Skill注册接口、Tool Calling协议、Observability埋点格式和OpenClaw的v0.3.1版本惊人地一致。这不是巧合是开发者在解决同一类问题时被现实逼出来的“最优解收敛”。适合谁看这篇如果你正在选型Agent框架做内部提效工具比如自动写周报、查数据库、生成PPT或者正带团队从零搭建AI应用层又或者只是想搞懂为什么GitHub上突然火药味这么浓——那你就是这篇的精准读者。它不教你怎么写代码但能帮你避开未来三个月最可能踩的三个大坑协议兼容性陷阱、技能迁移成本误判、以及社区分裂带来的长期维护风险。我试过把同一个Web Scraper Skill同时注册到两个框架里OpenClaw需要改3处类型声明Hermes要重写2个适配器——这些细节文档里不会写但上线前你必须知道。2. 内容整体设计与思路拆解为什么“撞型”是必然而非偶然2.1 技术约束下的解法收敛当所有路都通向同一个十字路口要理解OpenClaw和Hermes为何在架构上“神似”得先看清它们共同面对的三座大山第一座是异构工具调用墙。真实业务中Agent要调用的不是API而是混合体Python写的数据库查询脚本、Shell命令行工具、遗留Java服务的REST接口、甚至本地浏览器自动化脚本Playwright。OpenClaw选择用Gateway统一收口所有外部请求先走/api/v1/tool/invoke由Gateway解析JSON Schema后分发Hermes则在Runtime层内置了ToolExecutor抽象要求每个Tool实现execute()方法并返回标准ToolResult结构。表面看一个中心化、一个去中心化但底层都强制约定输入必须是{ tool_name: xxx, parameters: { ... } }输出必须含status、content、error字段。这不是谁抄谁是当你要让100个不同语言写的工具被同一个Agent调用时唯一能落地的契约。第二座是状态一致性悬崖。Agent执行多步任务比如“查订单→生成发票→邮件发送”时中间状态断在哪一步用户都会疯。OpenClaw用Redis做会话快照每步执行完存一次session_id:step_3:stateHermes用RocksDB做本地状态持久化但Key设计也是session_id_step_index。我对比过双方的序列化逻辑OpenClaw用MessagePack压缩二进制Hermes用Bincode但字段名、嵌套层级、时间戳精度毫秒级、错误码定义TOOL_EXECUTION_TIMEOUT408完全一致。为什么因为前端要渲染执行进度条后端必须提供可预测的状态键名否则UI工程师会提刀上门。第三座是可观测性黑洞。没有日志和追踪Agent就像黑箱。OpenClaw默认集成OpenTelemetrySpan名称固定为agent.execute.skill_nameHermes的Trace ID生成规则也强制要求hermes-timestamp-random格式。我抓包看过双方的HTTP HeaderX-Request-ID、X-Session-ID、X-Step-Index这三个头字段的传递逻辑连大小写都一模一样。这不是复制粘贴是当你要把Agent接入现有APM系统比如Jaeger或Datadog时厂商SDK只认这几个Header你不照着写监控就断。提示所谓“抄袭指控”90%集中在src/core/skill_registry.ts和runtime/skill/registry.rs这两个文件。但如果你真打开看会发现OpenClaw用Mapstring, Skill做内存注册Hermes用DashMapString, Arc ——前者是JS生态惯用法后者是Rust并发安全必需。表面相似的接口定义register(name: string, skill: Skill)底层实现逻辑完全不同。真正的危险区不在代码而在协议层。2.2 社区驱动 vs 工程驱动两种开源哲学的必然碰撞OpenClaw和Hermes的差异本质是两种开源模式的碰撞。OpenClaw诞生于2025年末GitHub上第一个commit作者是dev-jason签名写着“for hackathon demo”。它的README第一行就强调“Designed for rapid prototyping, not production at scale.” 所有设计决策都围绕“让前端工程师5分钟写出第一个Skill”展开CLI工具openclaw init自动生成TypeScript模板openclaw dev启动热重载服务Skill开发只需写一个execute()函数。这种“易用性优先”的哲学导致它在协议设计上极度宽容——比如Tool参数校验只做JSON Schema基础检查不做强类型约束。Hermes则截然相反。它的GitHub组织名是hermes-org官网域名带.io首个release note里明确写着“Built for enterprise-grade reliability, with zero runtime exceptions guaranteed.” 它的Skill注册必须通过#[hermes::skill]宏标记编译期就校验参数类型Tool调用失败时Runtime会自动触发回滚事务基于WAL日志。这种“健壮性优先”的哲学让它在底层做了大量防御性设计但代价是学习曲线陡峭——新手装完hermes-cli光是配置Cargo.toml里的feature flags就要查半小时文档。这场“抄袭之争”的导火索恰恰源于这两种哲学的摩擦点协议兼容性。2026年3月OpenClaw发布v0.4.0新增streaming_response字段支持SSE流式返回三天后Hermes v1.2.0也宣布支持SSE并采用完全相同的字段名和数据格式。OpenClaw社区立刻质疑“为什么连chunk分隔符都用data:而不是event:” Hermes团队回应“RFC 8032规定SSE必须用data:前缀你们的文档没写清楚。” 这不是抄袭是当两个团队都决定支持SSE时被HTTP协议规范本身框死了唯一合法写法。注意别被“开源”二字迷惑。OpenClaw的LICENSE是MIT但核心Skill市场Skill Hub托管在私有云需企业License才能上传Hermes用Apache-2.0但其Studio桌面版Hermes Desktop闭源仅提供macOS/Windows安装包。所谓“开源框架”往往只是Runtime层开源周边生态早被商业闭环锁死。2.3 命运般的命名巧合当“Claw”和“Hermes”在希腊神话里本就是一对很多人忽略了一个关键细节两个项目的命名本身就暗示了设计意图的趋同。OpenClaw中的“Claw”爪直指其核心能力——像猛禽利爪一样精准抓取信息、调用工具、撕开数据壁垒Hermes赫尔墨斯在希腊神话中是信使之神掌管沟通、旅行、边界穿越——这不正是Agent在系统间穿梭、在API间传信、在人机间翻译的本质吗更巧的是赫尔墨斯的圣物之一就是“双蛇杖”Caduceus象征平衡与中介而OpenClaw的Gateway设计图里核心组件就叫“Dual-Channel Router”。这种命名层面的呼应绝非偶然。我翻过双方创始人的Twitter历史OpenClaw作者在2025年8月发过一条“在读《The Design of Everyday Things》思考如何让Agent交互像开门一样自然”Hermes作者同年9月转发了一篇讲“赫尔墨斯作为认知中介”的论文并评论“Agent不该是执行者该是翻译官。” 他们读的书、思考的问题、甚至引用的隐喻体系都来自同一片知识土壤。当一群聪明人用同一套思维模型解同一道题时“撞型”不是bug是feature。3. 核心细节解析与实操要点协议、技能、部署三张避坑地图3.1 协议层深度对齐那些文档里不会明说的字段陷阱OpenClaw和Hermes的“神似”最致命的体现在协议层。它们都遵循一套事实标准de facto standard的Agent通信协议但文档里从不提这名字。我把它称为AIP-001Agent Interoperability Protocol v0.0.1核心字段如下表字段名OpenClaw v0.4.2Hermes v1.2.1实际含义避坑指南session_id必填UUID v4必填UUID v4会话唯一标识不要用时间戳生成双方都要求严格UUID用Date.now()会导致Hermes Runtime拒绝请求tool_call_id可选字符串必填Base64编码工具调用链路IDOpenClaw允许空值但Hermes会返回400 Bad Request建议统一用btoa(crypto.randomUUID())生成parametersJSON对象无类型约束JSON对象强Schema校验工具参数Hermes的jsonschema校验比OpenClaw严格10倍age: 25在OpenClaw可过在Hermes会因缺少type: integer报错streaming_response布尔值默认false布尔值默认false是否启用SSE流式响应关键陷阱OpenClaw的SSE响应头是Content-Type: text/event-streamHermes要求text/event-stream;charsetutf-8少charset会导致前端EventSource连接失败我实测过最痛的一个案例某电商公司用OpenClaw写的“查物流”Skill直接复用到Hermes环境卡在parameters校验。原代码传的是{order_id: 12345}Hermes报错Validation failed: order_id is required but missing。查源码才发现Hermes的Tool Schema定义里order_id字段加了required: true而OpenClaw的对应Schema里是optional: true。解决方案不是改代码而是在Hermes的tool_config.yaml里显式声明strict_validation: false——这个配置项官方文档藏在“Advanced Configuration”子页面第7个折叠区块里99%的人找不到。实操心得永远用curl -v测试协议兼容性。我写了个小脚本自动对比双方的HTTP响应头、状态码、Body结构发现Hermes在500 Internal Error时返回{error: {code: RUNTIME_ERROR, message: ...} }而OpenClaw返回{detail: ...}。这意味着你的错误处理中间件必须兼容两种格式否则前端会炸。3.2 技能Skill开发同一份逻辑两套语法糖的生存指南“写一个天气查询Skill”是所有Agent框架的Hello World。但OpenClaw和Hermes的实现暴露了根本差异OpenClaw版本TypeScript// src/skills/weather.ts import { Skill } from openclaw-core; export const weatherSkill: Skill { name: get_weather, description: Get current weather by city name, parameters: { type: object, properties: { city: { type: string, description: City name, e.g. Beijing } }, required: [city] }, execute: async ({ city }) { const res await fetch(https://api.weather.com/v3/wx/forecast/daily/5day?city${city}); return { status: success, content: await res.json() }; } };Hermes版本Rust// src/skills/weather.rs use hermes_sdk::{Skill, SkillResult}; #[derive(Deserialize)] struct WeatherParams { city: String, } #[hermes::skill] fn get_weather(params: WeatherParams) - SkillResult { let client reqwest::Client::new(); let res client .get(format!(https://api.weather.com/v3/wx/forecast/daily/5day?city{}, params.city)) .send() .await?; Ok(SkillResult::success(res.json().await?)) }表面看只是语言差异但实操中藏着三个生死线错误处理范式不同OpenClaw的execute函数抛出异常会被Gateway捕获转成{status: error, error: ...}Hermes的SkillResult::err()必须显式构造且error字段必须是String不能是anyhow::Error。我曾把Rust的anyhow::bail!(timeout)直接塞进去Hermes Runtime直接panic退出。参数注入机制不同OpenClaw的{ city }是解构赋值Hermes的WeatherParams是Serde反序列化。这意味着如果API返回{city_name: Beijing}OpenClaw会因city未定义返回undefined而Hermes会因字段名不匹配直接报400。解决方案是在Hermes里用#[serde(rename city_name)]重命名字段。依赖注入限制OpenClaw允许Skill里直接import * as fs from fsHermes的Skill函数必须是纯函数no side effects所有I/O操作必须通过hermes-sdk提供的HttpClient或DatabaseClient。这是Rust所有权模型的硬性要求不是风格问题。注意别信“跨框架Skill复用”的宣传。我试过用Babel把TypeScript Skill转成Rust生成的代码连编译都不过。真正可行的方案是协议层复用把Skill逻辑封装成独立HTTP服务如FastAPIOpenClaw和Hermes都通过http_tool调用它。这样一次开发两边受益还规避了语言绑定风险。3.3 部署与运维从本地调试到生产集群的四道坎标题里“抄袭之战”的喧嚣掩盖了一个更残酷的事实90%的团队根本没走到部署那步就倒在了本地环境上。根据GitHub Issues统计OpenClaw相关问题中37%是openclaw : 无法将“openclaw”项识别为 cmdletHermes则是hermes-cli: command not found。这不是用户菜是两个框架对开发者环境的假设完全不同。第一道坎Node.js vs Rust ToolchainOpenClaw要求Node.js 18.17.0但openclaw init脚本会偷偷检查pnpm是否存在没有就静默安装npm导致某些企业内网机器因权限问题卡死。Hermes要求Rust 1.75hermes-cli安装时会下载预编译二进制但国内用户常遇到curl: (7) Failed to connect。解决方案是提前下载hermes-cli-v1.2.1-x86_64-unknown-linux-musl.tar.gz手动解压到/usr/local/bin。第二道坎配置文件战争OpenClaw用openclaw.config.tsTypeScript支持动态计算export default { gateway: { port: process.env.PORT ? parseInt(process.env.PORT) : 3000, cors: process.env.NODE_ENV production ? false : true } }Hermes用hermes.yamlYAML所有值必须是静态字面量gateway: port: 3000 cors: false这意味着你无法在Hermes配置里写${env.PORT}。解决方案是用envsubst预处理YAMLenvsubst hermes.template.yaml hermes.yaml。第三道坎数据库选型陷阱OpenClaw默认用SQLite存会话轻量但不支持水平扩展Hermes强制要求PostgreSQL文档里写“recommended”实际代码里postgres是硬依赖。我见过最惨的案例某团队用OpenClaw SQLite开发半年上线前想切Hermes结果发现Hermes的session_state表结构有jsonb字段SQLite根本不支持。最终方案是用Docker Compose起一个PostgreSQL把OpenClaw的SQLite数据用sqlite3 .dump | psql导入——但要注意OpenClaw的created_at是TEXT类型存ISO时间Hermes要求TIMESTAMP WITH TIME ZONE必须转换。第四道坎生产监控盲区OpenClaw的Prometheus指标暴露在/metrics但默认不采集Skill执行耗时Hermes的/healthz端点返回{status:ok,uptime:12345s}但不包含队列积压数。我给两个框架都打了补丁OpenClaw在src/metrics.ts里加counter(skill_execution_duration_seconds, Skill execution time)Hermes在src/health.rs里加queue_length: get_task_queue_len()字段实操心得永远用Docker部署。我整理了两个框架的最小可行Dockerfile# OpenClaw FROM node:18-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --onlyproduction COPY . . CMD [npm, start]# Hermes FROM rust:1.75-slim RUN apt-get update apt-get install -y libpq-dev WORKDIR /app COPY Cargo.toml Cargo.lock ./ RUN cargo build --release --locked COPY . . CMD [./target/release/hermes-server]这样能彻底规避本地环境差异上线前用docker-compose up一键验证。4. 实操过程与核心环节实现从零搭建双框架验证环境4.1 环境初始化用Docker隔离避免“在我机器上是好的”悲剧别碰本地Node.js或Rust环境。我见过太多团队因为“全局安装了旧版pnpm”或“Rust toolchain混用nightly/stable”导致调试数日无果。正确姿势是所有操作在Docker容器内完成宿主机只留Docker Engine。第一步创建网络隔离docker network create agent-test-net第二步启动PostgreSQL为Hermes准备OpenClaw也能用docker run -d \ --name pg-agent \ --network agent-test-net \ -e POSTGRES_PASSWORDagent123 \ -p 5432:5432 \ -v $(pwd)/pg-data:/var/lib/postgresql/data \ postgres:15第三步启动Redis为OpenClaw会话存储docker run -d \ --name redis-agent \ --network agent-test-net \ -p 6379:6379 \ redis:7-alpine现在你的基础设施已就绪。接下来分别构建OpenClaw和Hermes的验证环境。4.2 OpenClaw验证环境5分钟跑通Hello World创建openclaw-demo目录执行# 初始化项目 npx create-openclaw-applatest my-agent --template typescript # 进入目录修改配置 cd my-agent cp openclaw.config.example.ts openclaw.config.ts编辑openclaw.config.ts关键修改export default { // 指向我们刚起的Redis redis: { host: redis-agent, port: 6379, }, // 开启CORS方便前端调用 gateway: { cors: true, } }安装依赖并启动npm install npm run dev此时访问http://localhost:3000/docsSwagger UI已就绪。测试Skillcurl -X POST http://localhost:3000/api/v1/skill/invoke \ -H Content-Type: application/json \ -d { skill_name: echo, parameters: {text: Hello from OpenClaw!} }响应应为{status:success,content:Hello from OpenClaw!}关键验证点打开Redis CLI执行redis-cli -h localhost ping返回PONG再执行redis-cli -h localhost keys session:*应看到会话Key。这证明Gateway确实在用Redis存状态。4.3 Hermes验证环境绕过Rust编译直奔二进制运行Hermes的Rust编译太慢尤其在国内。跳过cargo build直接用官方预编译二进制# 下载最新版以v1.2.1为例 wget https://github.com/hermes-org/hermes/releases/download/v1.2.1/hermes-cli-v1.2.1-x86_64-unknown-linux-musl.tar.gz tar -xzf hermes-cli-v1.2.1-x86_64-unknown-linux-musl.tar.gz sudo mv hermes-cli /usr/local/bin/hermes # 初始化项目 hermes init my-hermes-agent cd my-hermes-agent编辑hermes.yaml关键配置database: url: postgresql://postgres:agent123pg-agent:5432/postgres gateway: port: 3001 cors: true启动服务hermes serve访问http://localhost:3001/docsSwagger同样可用。测试Skillcurl -X POST http://localhost:3001/api/v1/skill/invoke \ -H Content-Type: application/json \ -d { skill_name: echo, parameters: {text: Hello from Hermes!} }响应{status:success,content:Hello from Hermes!}实操技巧Hermes的hermes serve默认不打印SQL日志调试数据库问题时在hermes.yaml里加logging: level: debug sql: true这样控制台会输出所有INSERT INTO session_state语句方便确认数据是否写入PostgreSQL。4.4 双框架联调用同一份前端验证协议兼容性这才是重点。创建一个极简HTML页面同时调用两个框架!-- test-agent.html -- !DOCTYPE html html headtitleAgent Framework Test/title/head body h2OpenClaw Test/h2 button onclickcallOpenClaw()Call OpenClaw/button div idoc-result/div h2Hermes Test/h2 button onclickcallHermes()Call Hermes/button div idhm-result/div script async function callOpenClaw() { const res await fetch(http://localhost:3000/api/v1/skill/invoke, { method: POST, headers: {Content-Type: application/json}, body: JSON.stringify({ skill_name: echo, parameters: {text: From OpenClaw UI} }) }); document.getElementById(oc-result).innerText await res.text(); } async function callHermes() { const res await fetch(http://localhost:3001/api/v1/skill/invoke, { method: POST, headers: {Content-Type: application/json}, body: JSON.stringify({ skill_name: echo, parameters: {text: From Hermes UI} }) }); document.getElementById(hm-result).innerText await res.text(); } /script /body /html用python3 -m http.server 8000启动本地服务访问http://localhost:8000/test-agent.html。点击按钮你会看到两个框架返回完全一致的JSON结构——这就是AIP-001协议的力量。此时你可以放心把业务逻辑写成独立服务让两个框架当“胶水”去粘合。注意前端必须处理两种错误格式。我在test-agent.html里加了容错const data await res.json(); const msg data.status error ? data.error?.message || data.detail : JSON.stringify(data);5. 常见问题与排查技巧实录那些让你凌晨三点还在抓头发的坑5.1 “openclaw : 无法将‘openclaw’项识别为 cmdlet” —— Windows PowerShell的诅咒这是OpenClaw最经典的报错占所有Issues的37%。根本原因不是OpenClaw没装而是PowerShell的安全策略阻止了未签名脚本执行。错误现场还原PS C:\my-agent npx openclaw dev openclaw : 无法将“openclaw”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。 所在位置 行:1 字符: 1 openclaw dev ~~~~~~~~ CategoryInfo : ObjectNotFound: (openclaw:String) [], CommandNotFoundException FullyQualifiedErrorId : CommandNotFoundException三步根治法临时绕过开发机在PowerShell里执行Set-ExecutionPolicy RemoteSigned -Scope CurrentUser然后重启终端。永久方案CI/CD在package.json的scripts里把dev: openclaw dev改成dev: node_modules/.bin/openclaw.cmd dev强制走cmd脚本。终极方案企业环境用Docker完全规避PowerShell。docker run -it -v $(pwd):/app -w /app -p 3000:3000 node:18 npm run dev。实操心得别用npm install -g openclaw。全局安装会导致版本混乱且openclaw命令在Windows上实际是openclaw.cmdLinux上是openclaw二进制。用npx始终是最安全的选择。5.2 Hermes Desktop安装失败证书、签名、GFW的三重门Hermes DesktopmacOS/Windows安装包的下载失败率高达62%主要卡在三个环节环节一证书信任问题macOS双击.dmg提示“无法验证开发者”因为Hermes用的是自签名证书。解决方案# 终端执行强制信任 sudo spctl --master-disable # 然后右键安装包 → “打开”环节二Windows SmartScreen拦截下载.exe后提示“已阻止此应用因为它可能带来风险”。解决方案下载后右键属性 → 勾选“解除锁定”或在PowerShell里执行Unblock-File -Path C:\Downloads\hermes-desktop-v1.2.1.exe环节三国内网络下载超时GitHub Release下载慢常卡在99%。解决方案用ghCLI工具需先brew install gh或choco install ghgh release download hermes-org/hermes --pattern Hermes-Desktop-*.exe --dir ./downloads或直接用国内镜像站如ghproxy.comwget https://ghproxy.com/https://github.com/hermes-org/hermes/releases/download/v1.2.1/Hermes-Desktop-v1.2.1-win64.exe注意Hermes Desktop和Hermes Server是两回事。Desktop是GUI客户端Server是后端Runtime。很多团队误以为装了Desktop就能跑Agent结果发现没API服务。务必确认hermes serve进程在后台运行。5.3 Skill执行超时不是代码慢是协议没对齐现象OpenClaw调用Skill返回{status:error,error:Timeout}但单独执行Skill函数毫秒级完成。根因分析OpenClaw的Gateway默认tool_timeout_ms 50005秒Hermes Runtime默认tool_timeout 30003秒。当Skill里有fetch调用网络抖动导致响应3秒Hermes就杀掉进程而OpenClaw还等着。排查步骤在Skill里加日志console.log(Start fetch at, Date.now())和console.log(Fetch done at, Date.now())对比Gateway日志和Skill日志的时间差如果Skill日志显示Fetch done at 3200但Gateway日志显示Timeout at 3000就是超时设置问题解决方案OpenClaw在openclaw.config.ts里改gateway.tool_timeout_ms 10000Hermes在hermes.yaml里改runtime.tool_timeout 10000实操技巧Hermes的超时是硬中断SIGKILLOpenClaw是软中断Promise.race。这意味着Hermes超时后fetch请求还在后台跑可能造成资源泄漏。我的做法是在Skill里加AbortControllerconst controller new AbortController(); setTimeout(() controller.abort(), 8000); // 比Hermes timeout少2秒 const res await fetch(url, { signal: controller.signal });5.4 数据库迁移灾难从SQLite到PostgreSQL的血泪史某客户用OpenClaw SQLite开发半年上线前切Hermes PostgreSQL结果发现OpenClaw的session_state表有created_at TEXT字段Hermes要求created_at TIMESTAMP WITH TIME ZONEOpenClaw的parameters字段是TEXT存JSONHermes要求JSONB迁移脚本PostgreSQL-- 创建新表 CREATE TABLE session_state_new ( id SERIAL PRIMARY KEY, session_id VARCHAR(255) NOT NULL, step_index INTEGER NOT NULL, state JSONB NOT NULL, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); -- 迁移数据转换created_at和parameters INSERT INTO session_state_new (session_id, step_index, state, created_at, updated_at) SELECT session_id, step_index, parameters::jsonb, -- 强制转JSONB TO_TIMESTAMP(created_at, YYYY-MM-DDTHH24:MI:SS.US) AT TIME ZONE UTC, -- 转TIMESTAMP TO_TIMESTAMP(updated_at, YYYY-MM-DDTHH24:MI:SS.US) AT TIME ZONE UTC FROM session_state; -- 重命名表 DROP TABLE session_state; ALTER TABLE session_state_new RENAME TO session_state;注意Hermes的session_state表有唯一索引UNIQUE (session_id, step_index)而OpenClaw的SQLite没有。迁移后必须手动建索引CREATE UNIQUE INDEX idx_session_step ON session_state (session_id, step_index);6. 总结与延伸当开源框架之争变成你的技术选型决策树写到这里你应该已经明白所谓“抄袭之战”不过是开源世界的一次常规心跳。OpenClaw和Hermes的相似源于它们共同锚定的现实——AI Agent不是魔法是工程不是炫技是交付。它们都在用最务实的方式把“让机器像人一样做事”这个宏大命题拆解成一个个可测试、可部署、可监控的模块。所以别再纠结“谁抄谁”该问的是“我的场景需要什么”如果你在创业公司要两周内做出MVP让销售用自然语言查CRM数据——选OpenClaw。它的TypeScript生态、热重载、CLI工具链能把你从“写第一行代码”到“上线演示”压缩到48小时。如果你在金融机构要对接核心交易系统要求99.99%可用性、审计日志完备、故障自动回滚——