Runtime 原生能力抽象:Hermes 接入现状、OpenClaw 能力差距与后续演进 #254
Replies: 12 comments
基于代码库现状的分析与建议我对照当前代码库做了一轮排查,补充一些观察和建议。 当前抽象基础的实际状态
对各议题的倾向
第一阶段实施建议补充
总结Discussion 准确识别了核心问题:OpenClaw 既是 runtime,又被当成了默认产品模型。第一阶段"只做抽象声明、不实现 Hermes 完整能力"的策略正确。 从代码看主要差距是三点:
先解决这三点,就为后续接入更多 runtime 打下坚实基础。 |
基于代码库现状的技术讨论结合代码库做了一轮排查,补充一些具体观察和建议。 一、代码层面几个值得特别注意的细节
config_rel_path: str = ".openclaw/openclaw.json"
supports_channel_plugins: bool = True
data_dir_container_path: str = "/root/.openclaw"
has_web_ui: bool = True注册新 runtime 如果漏覆盖某个字段,会静默继承 OpenClaw 行为而不会报错。这在代码层面直接体现了"OpenClaw 被当成默认产品模型"的问题。 前端 fallback 也是 OpenClaw export function getRuntimeCaps(runtime: string): RuntimeCapabilities {
return CAPS[runtime] ?? CAPS.openclaw
}未知 runtime 直接 fallback 到 openclaw caps,导致即便后端声明某能力不支持,前端也可能展示为"支持"。 两套
这两套不只是"分裂",而是根本没在描述同一件事,后续会持续引发概念混淆。 Hermes 的 GeneInstallAdapter 实际上是空实现 代码里没有 二、对各议题的倾向
三、第一阶段最需要解决的三件事比起"新增 adapter",第一阶段更核心的工作是统一三个表达层: 1. 能力声明统一到 在 2. 统一 unsupported 契约 当前存在三种不一致的处理方式:
需要统一成:adapter 返回结构化 unsupported 结果 → API 层统一捕获 → 返回可识别错误码 → 前端展示明确原因。禁止静默忽略。 3. 把有"OpenClaw 语义"的字段默认值改为 四、不建议在第一阶段合并的东西不要在第一阶段合并后端两套 五、一个值得单独讨论的架构问题
这个问题背后有一个更深的架构问题:NoDeskClaw 平台应该在多大程度上"标准化"不同 runtime 的行为? 如果 Hermes 的工具调用模型和 OpenClaw 根本不同(例如 Hermes 用 skill 调用而不是 tool call),强行映射 |
第一阶段落地草案:Capabilities / Unsupported Contract /
|
实施路径:建议的 PR 拆分计划与协作对齐既然第一阶段的架构设计、字段定义和接口形状都已经理清,为了避免改动范围过大(爆炸半径失控),我建议将接下来的工作拆分为 3 个解耦的 PR 逐步推进。这样前后端可以并行开发,也能更稳妥地落地。 PR 1: 基础框架与能力声明 (Backend)目标:建立 Truth Source,移除 OpenClaw 默认语义
(此 PR 纯底层和接口层,不影响任何现有业务逻辑,可快速合并)。 PR 2: 消费能力声明与 UI 降级 (Frontend)目标:前端不再依靠猜测或写死,严格听从后端指挥
(此 PR 依赖 PR 1 的接口结构,但可以依据 mock 数据并行开发)。 PR 3: 清理静默忽略与散落分支 (Backend)目标:堵住“假装成功”的漏洞,收敛逻辑分支
总结通过这 3 个 PR,我们可以在不改变 OpenClaw 现有行为、也不强迫 Hermes 立刻补齐功能的前提下,彻底理顺 NoDeskClaw 的多 Runtime 架构底座。 如果大家对这个落地路线没有异议,我们就可以直接按照这个 PR 拆分计划开始认领开发任务了。 |
补充:关于架构健壮性与 Gene 生态演进的深度思考在 PR 拆分计划的基础上,为了确保这套抽象层在未来长期保持健壮,建议我们在实施 PR 1 和 PR 3 时额外考虑以下几个细节: 1. Capability 的“软声明”与“硬校验”目前的方案主要是后端声明、前端消费。但为了防止 API 绕过或逻辑遗漏,后端在执行具体逻辑(如
2. Gene Manifest 的“去 OpenClaw 化”引导我们要打破“OpenClaw 即默认模型”,
3. 跨 Runtime 协同的能力感知当不同引擎的员工进行协作时(例如 OpenClaw 员工给 Hermes 员工发送包含工具调用请求的消息),如果目标引擎能力不对等,目前的协议层处理较为被动。
4. 关于
|
补充:测试策略与回归保障前面几条评论已经把"做什么"和"怎么拆 PR"讲得很清楚了。这里补充一个容易被忽略但对第一阶段至关重要的维度:如何验证我们"只做抽象不改行为"的承诺没有被打破。 1. OpenClaw 行为的回归保障第一阶段的核心约束是"不改变 OpenClaw 当前行为"。但 PR 1 要动 建议:在 PR 1 合并前,先补一组 Snapshot Test / Contract Test:
这类测试写起来非常快(10 分钟以内),但可以在整个重构周期内持续充当"安全网"。 2. Unsupported Contract 的完整性验证我们承诺"禁止静默忽略",但如何确保这个承诺在代码层面被持续遵守? 建议:增加一个 架构测试(Architecture Test) 或 lint 规则:
class GeneInstallAdapter(ABC):
async def allow_tools(self, fs: RemoteFS, tool_names: list[str]) -> None:
"""默认:不支持工具白名单。子类需覆盖以提供实现。"""
raise UnsupportedCapabilityError(
runtime_id=self.runtime_id,
capability="tool_allow",
message_key="errors.runtime.unsupported_capability",
)这比当前"要求所有子类实现 abstractmethod 但允许空实现"更安全——空实现本身就是 bug 来源。 3. Capability 矩阵的测试覆盖当前的 capabilities 定义只是一个 dict,容易出现"改了代码逻辑但忘了更新 capabilities 声明"的问题。 建议:增加一组集成测试,通过直接调用 Service 方法来验证 capabilities 声明的准确性: @pytest.mark.parametrize("runtime_id,capability,should_support", [
("openclaw", "genes", True),
("openclaw", "tool_allow", True),
("hermes", "genes", False),
("hermes", "tool_allow", False),
("hermes", "evolution_log", True), # 平台能力,所有 runtime 都应为 true
])
def test_capability_declaration_matches_behavior(runtime_id, capability, should_support):
spec = RUNTIME_REGISTRY.get(runtime_id)
assert spec.capabilities[capability] == should_support这样如果有人给 Hermes 实现了 4. 前端降级逻辑的 E2E 验证前端的改造涉及"后端返回 capabilities → 前端据此显隐 UI"这条链路。如果只做单元测试,容易漏掉"后端返回了但前端没正确消费"的场景。 建议:在 PR 2 中,至少增加 2 个 E2E 场景:
总结测试策略的核心原则:让"不改变行为"和"禁止静默忽略"这两个承诺成为可被 CI 持续验证的硬约束,而不是靠开发者自觉遵守的软约定。 以上测试建议的实现成本都不高,但对于保障整个第一阶段重构的安全性至关重要。建议在 PR 1 中就先把 OpenClaw snapshot test 和 capability 矩阵测试就位,作为后续所有改动的安全网。 |
沉淀成制度:新 Runtime 准入检查清单前面几条评论已经把"这次怎么做"讲清楚了。但这套设计的真正价值,是让未来接入第四个、第五个 runtime 时,不需要重新发起一次 Discussion,而是有一套标准化的准入契约可以遵循。 为什么需要一份 Checklist当前接入 Hermes 遇到的所有问题(默认值继承、静默忽略、capabilities 分裂、前端 fallback 错误等),本质上都是因为没有一份明确的"新 runtime 要做什么"的约定。今后再接入任何 runtime,如果没有这份 Checklist,同样的问题会以不同形式重现。 建议的新 Runtime 准入 Checklist1. 注册阶段(RuntimeSpec 必填字段)以下字段在 PR 1 完成后应变为强制要求,不允许依赖默认值:
2. Adapter 实现阶段
3. Capabilities 声明与行为一致性
4. 前端能力消费验证
5. Gene Manifest 兼容性声明
Checklist 的维护建议建议将这份 Checklist 作为一个独立文件放入代码库(如 这样,本次 Discussion 的所有设计成果就不仅仅是一次"补 Hermes 能力"的技术方案,而是沉淀成了 NoDeskClaw 多 Runtime 生态的长期架构规范。 |
收口总结:已决事项、开放议题与执行时间线本 Discussion 经过 7 轮深入讨论,已经从"发现问题"完整推进到"可执行方案"。为了正式收口并转入执行阶段,这里做一次全局总结。 一、已达成共识(可直接执行,无需再议)
二、需要转出为独立 Discussion 的开放议题以下议题在本次讨论中被反复提及但刻意未做最终决策,建议各自开新 Discussion 深入讨论:
三、建议的执行时间线四、本 Discussion 状态建议本 Discussion 的目标("把 runtime 能力边界抽象出来"的方案设计)已经完成。建议:
感谢所有参与讨论的同学,这是一次非常高质量的架构对齐。接下来就是动手写代码了。 |
补充:Gene 生态兼容性策略与 Unsupported 可观测性前面的讨论集中在平台架构层面,这里补充两个偏"运营侧"但对落地成功同样关键的维度。 1. 现有 Gene 生态的兼容性处理GeneHub 中已经有大量发布的 Gene,它们的 manifest 深度绑定了 OpenClaw 语义( 建议:Gene 兼容性元数据在 Gene manifest 中增加(或在 GeneHub 元数据中标注)一个 # gene.yaml
name: my-awesome-gene
supported_runtimes:
- openclaw
- hermes # 如果该 Gene 已经适配 Hermes平台侧行为:
建议:渐进式兼容策略
这样用户不会在 Hermes 实例上看到大量 "安装失败" 的 Gene,而是看到 "部分功能受限" 的合理提示。 2. Unsupported Contract 的生产可观测性Unsupported Contract 上线后,我们需要回答以下问题:
建议:增加结构化指标在 await emit_metric("runtime.unsupported_capability_hit", {
"runtime_id": runtime_id,
"capability": capability,
"operation": operation,
"gene_id": gene_id, # 如果是 Gene 安装触发的
"instance_id": instance_id,
})这些指标可以:
建议:在管理后台增加一个 Dashboard 视图展示:
3. 对 GeneHub / Gene 开发者的通知策略架构改完了,但如果 Gene 开发者不知道发生了什么变化,生态迁移不会自动发生。 建议:
总结这两个角度(Gene 生态兼容性 + 可观测性)确保了:
这些是"架构做完后让它真正 work"的最后一公里。 |
最终执行口径补充:命名、fallback、warnings 边界与 DoD在前面 9 条评论基础上,我认为本 Discussion 已经完成方案收敛,可以进入 PR 执行阶段。为避免实现时出现理解偏差,这里补充最终执行口径。 1. Capability 命名与分层第一阶段新增的是产品能力层 capability,用于驱动平台功能入口、API 行为和 unsupported 表达,例如:
它和后端现有协议层能力(如 streaming、tool_use、multi_turn)不是同一层概念。 建议实现时避免直接复用已有协议层
这样可以避免后续接入 2. 前端 fallback 策略前端本地 fallback 只能作为旧后端或接口异常时的兜底,不能继续 fallback 到 OpenClaw。 建议策略:
这可以避免新 runtime 被前端误判为支持 OpenClaw-only 功能。 3. warnings 与 hard error 的边界第一阶段需要区分两类场景: Gene 安装兼容场景为了兼容现有 Gene 生态,建议优先采用:
目标是避免老 Gene 在 Hermes 等 runtime 上被大量硬失败打断,同时让用户清楚知道哪些能力没有生效。 明确 OpenClaw-only 操作场景例如 repo channel plugin deploy、npm channel install、upload channel plugin 等明确依赖 OpenClaw plugin 机制的操作,建议直接返回结构化错误:
也就是说:Gene 生态兼容优先 warnings;明确不可执行的操作使用 hard error。 4. Definition of Done第一阶段可以按以下 DoD 判断是否完成:
5. 执行建议本 Discussion 不建议继续扩展实现范围。后续执行应保持第一阶段边界:
如果没有新的反对意见,可以按照评论中的 3 个 PR 拆分进入执行。 |
收口状态:进入执行阶段本 Discussion 已完成方案收敛,不再继续扩展第一阶段范围。 后续按 3 个 PR 推进:
第一阶段继续保持边界:只做能力抽象、能力输出、前端消费、unsupported 可见化、测试和准入文档,不实现 Hermes 对 OpenClaw 的完整等价能力。 |
补充:通用层仍残留 OpenClaw 硬编码,需要纳入下一阶段抽象范围在继续检查 runtime 抽象后,发现除了此前讨论的 Hermes 能力缺口外,通用层仍有一些 OpenClaw-first 的实现没有完全迁出。这部分不是单纯补 Hermes 功能,而是下一阶段 runtime adapter 化需要覆盖的新范围。 新发现的残留范围
原逻辑在员工加入办公室时只部署 OpenClaw channel plugin,非 OpenClaw runtime 会直接跳过。这个会影响 Hermes 加入办公室后的消息通路、learning 通道、workspace context 注入。 当前已开始修正方向:
例如 startup plugin sync、channel account repair 目前仍只扫描 OpenClaw 实例。这类逻辑应该改成 runtime-aware repair job:
建议的下一阶段抽象建议把本次补充范围纳入第二阶段:
当前执行口径第一阶段继续保持“先抽象,再补等价能力”的方向。已经发现的 OpenClaw 硬编码不必一次性全部实现为 Hermes 等价功能,但需要明确归类到 runtime adapter 层,避免后续继续在 service/API/frontend 里堆 |
Uh oh!
There was an error while loading. Please reload this page.
背景
NoDeskClaw 当前正在从单一 OpenClaw 运行时,逐步演进为可接入多个 AI 员工 runtime 的平台。当前已有或正在接入的 runtime 包括:
在 Hermes 接入和前后端联调过程中,我们发现:目前很多 AI 员工相关能力仍然以 OpenClaw 为默认模型,包括路径、配置文件、Channel plugin、Gene manifest、备份、进化日志和 Web UI/gateway 等。
这说明问题不只是“补 Hermes 某几个缺失功能”,而是需要先把 runtime 能力边界抽象出来,避免后续每接入一个 Agent runtime 都继续堆
runtime == "openclaw"/runtime == "hermes"分支。当前情况
当前已经存在的 runtime 抽象基础
代码里已经有一些抽象雏形:
RuntimeSpecGeneInstallAdapterRuntimeConfigAdapterunified_channel_schema这些是好的基础,但目前能力声明还不完整,很多产品能力仍然散落在 service/API/frontend 的硬编码判断里。
Hermes 当前已经可用的能力
基于现有联调,Hermes 当前已经可以覆盖一部分 NoDeskClaw 场景:
.hermes/*目录结构,而不是 OpenClaw 的.openclaw/*。也就是说,Hermes 不是不可用,而是已经具备基础 Agent 协同能力。
Hermes 相比 OpenClaw 当前仍然缺失的能力
1. evolutionLog 能力不等价
OpenClaw 侧有进化日志相关能力,前端也有
EvolutionLog页面。但 Hermes 当前:
evolutionLog=false;evolution_events表和 Gene 安装事件记录机制,但 Hermes 还没有被产品层视为支持该能力。需要讨论:
evolution log应该是所有 runtime 的产品能力,还是 OpenClaw runtime-specific 能力?2. Channel plugin discovery / repo sync 不支持
OpenClaw 当前有完整的 channel plugin 机制:
openclaw-channel-*;.openclaw/openclaw.json的 plugin 配置。Hermes 当前:
.openclaw/extensions这套 plugin 加载机制。需要讨论:Channel plugin 是否要从 OpenClaw plugin 规范抽象成 runtime-agnostic plugin 规范?
3.
tool_allow在 Hermes 中没有等价语义OpenClaw 的 Gene manifest 可以通过
tool_allow写入 OpenClaw 配置,让工具进入允许列表。Hermes 当前:
HermesGeneInstallAdapter.allow_tools()只是记录日志并忽略;需要讨论:Hermes 的
tool_allow应该映射为:4.
runtime_config/openclaw_config在 Hermes 中没有等价语义OpenClaw 可以把 Gene manifest 中的:
runtime_configopenclaw_config合并到
.openclaw/openclaw.json。Hermes 当前:
HermesGeneInstallAdapter.apply_config()只记录日志并忽略;.hermes/config.yaml;需要讨论:是否要定义跨 runtime 的标准
runtime_config字段,而不是继续沿用 OpenClaw 配置结构。5. 没有
.openclaw/openclaw.json配置注入语义OpenClaw 的很多能力围绕:
.openclaw/openclaw.jsonplugins.entriesplugins.load.pathstools.allowskills.load.extraDirsgateway.auth.tokenHermes 使用:
.hermes/config.yaml.hermes/.env.hermes/skills.hermes/scripts当前没有一层统一配置 patch adapter 来处理这些差异。
需要讨论:是否只允许 runtime-native 配置,还是提供 OpenClaw legacy manifest 的兼容翻译层。
6. Web UI / gateway 能力不等价
OpenClaw 有 Web UI/gateway 访问模型。
Hermes 当前:
has_web_ui、gateway port、endpoint URL 等能力现在还没有统一抽象清楚;需要讨论:是否需要拆分:
web_uigatewayhealth_endpointconfig_endpoint7. 备份目录不同
OpenClaw 当前备份目录主要是:
.openclaw.deskclaw/toolsHermes 当前主要是:
.hermes这意味着:
8. 前端 capability 与后端 RuntimeSpec 分裂
前端当前也维护了一份 runtime capability,例如:
这些信息和后端
RuntimeSpec存在重复。问题是:
二者可能不一致。
长期应该以后端 runtime capability 为准,前端只保留 fallback。
当前瓶颈
1. runtime 判断散落
很多地方仍然直接判断:
这会导致后续接入新 runtime 时,每个功能都要到处补分支。
2. unsupported 没有统一表达
当前有些地方直接抛 “仅支持 OpenClaw”,有些地方静默忽略,有些地方前端隐藏入口。
需要统一成:
3. OpenClaw 既是 runtime,又被当成默认产品模型
很多概念其实是产品能力,但现在被绑定到了 OpenClaw:
需要把这些能力从 OpenClaw 里抽出来,变成 runtime-agnostic 的产品层能力。
建议的第一阶段抽象
第一阶段不实现 Hermes 完整能力,只做抽象层和能力声明。
RuntimeCapabilities
用于声明 runtime 支持哪些产品能力:
genesevolution_logllm_configchannel_configchannel_plugin_discoveryrepo_channel_syncnpm_channel_installupload_channel_pluginweb_uigatewaybackupruntime_config_patchtool_allowRuntimePathPolicy
用于声明 runtime 的路径策略:
data_rootconfig_pathskills_dirscripts_dirworkspace_dirbackup_dirsbackup_exclude_patternscompat_dirsRuntimeConfigPatchAdapter
用于处理 Gene manifest 中的配置补丁:
runtime_configopenclaw_configHermes 当前可以先返回 unsupported,不做真实合并。
ChannelPluginAdapter
用于抽象:
OpenClaw adapter 迁移现有逻辑;Hermes/Nanobot 先使用 unsupported adapter。
RuntimeBackupPolicy
用于抽象:
第一阶段可以只迁移读取入口,不改变当前备份行为。
后续工作拆分维度
后续 runtime 接入与改造建议按以下维度拆分:
RuntimeCapabilities:产品能力声明。RuntimePathPolicy:路径与目录策略。RuntimeConfigPatchAdapter:配置补丁处理。ChannelPluginAdapter:Channel 插件生命周期。RuntimeBackupPolicy:备份与恢复策略。Frontend Capability Consumption:前端能力消费。Unsupported Contract:不支持能力的统一表达。Unsupported Contract 建议
所有 runtime 不支持的能力,都应该通过同一套链路表达:
这可以避免 “安装成功但配置无效” 或 “员工报告成功但工具没有注册” 这类问题。
第一阶段目标
不在第一阶段做的事情
tool_allow。.openclaw/openclaw.json伪造到 Hermes 中。后续讨论点
tool_allow应该映射到什么机制?runtime_config/openclaw_config是否需要定义跨 runtime 标准字段?All reactions