OmX OpenClaw 通知网关集成指南:从 prompt 模板调优到 clawdbot 生产级命令网关配置
本文以 docs/openclaw-integration.ko.md 的 "Prompt tuning guide (concise + context-aware)" 章节为骨架,结合 OmX(Oh My codeX)仓库中
src/openclaw/的源码实现与测试用例展开。更完整的网关/钩子/验证全景文档见 English guide。
导读:OmX 通过 notifications.openclaw 配置,把会话生命周期事件(session-start / session-idle / ask-user-question / stop / session-end)以指令(instruction)模板的形式投递给 OpenClaw 网关,从而驱动 clawdbot 等 agent 主动跟进开发任务。本文聚焦"简洁 + 上下文感知"的 prompt 调优:如何改写 5 个 hook 的 instruction 模板、如何选用上下文 token 与 verbosity 级别、如何落地 clawdbot agent 命令网关的生产配置,并深入 src/openclaw/ 源码,讲清激活门、模板插值、shell 安全与超时优先级等底层原理。读完你就能直接在 ~/.codex/.omx-config.json 中复刻一套可运行、可排障的 OpenClaw 集成配置。
一、为什么 prompt 模板是 OpenClaw 集成的质量杠杆
对于 OpenClaw 集成而言,最关键的调优点就是 hook 的 instruction 模板。它不是简单的一句话转发文本,而是会被投递给远端 agent(如 clawdbot)并驱动其行动的指令。指令越简洁、上下文越明确,agent 的响应越精准、越少发散。
在 OmX 的配置模型中,模板统一挂载在以下 5 个键下(这也是韩国语/中文等多语言团队最常改动的区域):
notifications.openclaw.hooks["session-start"].instructionnotifications.openclaw.hooks["session-idle"].instructionnotifications.openclaw.hooks["ask-user-question"].instructionnotifications.openclaw.hooks["stop"].instructionnotifications.openclaw.hooks["session-end"].instruction
这 5 个事件在源码中被枚举为合法的 hook 事件集合,见 src/openclaw/config.ts 与 src/openclaw/types.ts:
const VALID_HOOK_EVENTS: OpenClawHookEvent[] = [
"session-start",
"session-end",
"session-idle",
"ask-user-question",
"stop",
];
从源码结构看,
pre-tool-use、post-tool-use、keyword-detector等 OMC 专属事件被刻意排除(src/openclaw/types.ts 的注释说明了原因:Codex CLI 原生不支持这些事件)。
二、推荐上下文 token:让每条通知自带可追踪坐标
为了让远端 agent 能精准定位会话、定向操作 tmux,模板中应注入以下 token(由 OmX 在投递前完成插值):
| Token | 时机 | 用途 |
|---|---|---|
{{sessionId}} |
始终包含 | 跨日志追踪,关联 OMX 会话 |
{{tmuxSession}} |
始终包含 | 直接定位并跟进 tmux 会话 |
{{projectName}} |
相关时包含 | 标明项目(目录 basename) |
{{question}} |
ask-user-question 时 |
携带待回答的问题文本 |
{{reason}} |
session-end 时 |
携带结束原因 |
除上述外,src/openclaw/dispatcher.ts 的注释还列出了 {{projectPath}}、{{prompt}}、{{contextSummary}}、{{timestamp}}、{{event}}、{{instruction}}、{{replyChannel}} / {{replyTarget}} / {{replyThread}} 等变量。插值实现 interpolateInstruction 用正则 /\{\{(\w+)\}\}/g 匹配占位符,未解析的变量会被替换为空字符串(src/openclaw/dispatcher.ts),因此漏传的 token 不会导致投递失败,但会丢失上下文——这正是文档强调"始终包含 sessionId / tmuxSession"的原因。
结构化指令格式([event|exec] 前缀)
生产环境建议使用 clawdbot 易于解析的结构化格式:
[event|exec]
project={{projectName}} session={{sessionId}} tmux={{tmuxSession}}
필드1: 값
필드2: 값
[event|exec]前缀表明这是一个需要 agent 采取行动的可执行 hook;- 后续字段名可使用团队主要语言(韩文团队常用
요약、우선순위、주의사항、성과、검증、다음)提供统一结构,便于 agent 稳定提取字段。
三、verbosity 策略:三种档位怎么选
| 级别 | 行为 | 适用场景 |
|---|---|---|
minimal |
极短通知,高信噪比 | 只想收到"发生了什么"的轻量提醒 |
session |
简洁的操作上下文 | 推荐默认,覆盖 start/idle/stop/end 及 tmux tail |
verbose |
扩展到状态 + 动作 + 风险 | 需要 agent 输出更丰富叙事时 |
在 src/notifications/types.ts 中,verbosity 实际枚举为 "verbose" | "agent" | "session" | "minimal",其中 session 是默认档位(同文件 L135 注释说明默认值为 "session"),并注明:
verbose:包含全部文本/工具调用输出;session:start/idle/stop/end + tmux tail 片段(默认);minimal:仅 start/stop/end,不含 idle 与 tmux tail。
生产级的 executive-summary verbose 档位完整配置如下(可直接放入 notifications 块):
{
"notifications": {
"verbosity": "verbose",
"openclaw": {
"hooks": {
"session-start": {
"enabled": true,
"gateway": "local",
"instruction": "[session-start|exec]\nproject={{projectName}} session={{sessionId}} tmux={{tmuxSession}}\n요약: 시작 맥락 1문장\n우선순위: 지금 할 일 1~2개\n주의사항: 리스크/의존성(없으면 없음)"
},
"session-idle": {
"enabled": true,
"gateway": "local",
"instruction": "[session-idle|exec]\nsession={{sessionId}} tmux={{tmuxSession}}\n요약: idle 원인 1문장\n복구계획: 즉시 조치 1~2개\n의사결정: 사용자 입력 필요 여부"
},
"ask-user-question": {
"enabled": true,
"gateway": "local",
"instruction": "[ask-user-question|exec]\nsession={{sessionId}} tmux={{tmuxSession}} question={{question}}\n핵심질문: 필요한 답변 1문장\n영향: 미응답 시 영향 1문장\n권장응답: 가장 빠른 답변 형태"
},
"stop": {
"enabled": true,
"gateway": "local",
"instruction": "[session-stop|exec]\nsession={{sessionId}} tmux={{tmuxSession}}\n요약: 중단 사유\n현재상태: 저장/미완료 항목\n재개: 첫 액션 1개"
},
"session-end": {
"enabled": true,
"gateway": "local",
"instruction": "[session-end|exec]\nproject={{projectName}} session={{sessionId}} tmux={{tmuxSession}} reason={{reason}}\n성과: 완료 결과 1~2문장\n검증: 확인/테스트 결과\n다음: 후속 액션 1~2개"
}
}
}
}
}
注意:模板中的 \n 在 JSON 中就是真实换行;每个字段只要求 1~2 句,约束 agent 输出密度,避免长篇大论淹没关键信息。
四、生产配置最佳实践:clawdbot 命令网关
当目标是触发 agent 轮次(而非普通消息/Webhook 转发)时,使用 type: "command" 的命令网关,让 clawdbot agent 真正"跑一轮"。文档推荐的配置如下:
{
"notifications": {
"openclaw": {
"gateways": {
"local": {
"type": "command",
"command": "(clawdbot agent --session-id omx-hooks --message {{instruction}} --thinking minimal --deliver --reply-channel discord --reply-to 'channel:1468539002985644084' --timeout 120 --json >>/tmp/omx-openclaw-agent.jsonl 2>&1 || true)",
"timeout": 120000
}
}
}
}
}
关键设置说明(务必逐条理解):
|| true:clawdbot 失败时不让 OMX 会话被阻塞——hook 投递失败不应拖垮开发主流程;>>/tmp/omx-openclaw-agent.jsonl:以 append 模式写结构化 JSONL 日志,便于长期聚合与分析(不要用>覆盖,否则历史丢失);--reply-to 'channel:CHANNEL_ID':用频道 ID 而非频道别名(如#omc-dev),确保 Discord 投递稳定——别名在 bot 未缓存频道时可能失败;timeout: 120000:2 分钟超时,给 clawdbot agent 完成一轮思考 + 投递留足时间。
命令网关超时优先级(重要)
命令网关超时的解析优先级在源码 src/openclaw/dispatcher.ts 中实现:
gateways.<name>.timeout > OMX_OPENCLAW_COMMAND_TIMEOUT_MS > 默认 5000ms
并且运行时会 clamp 到安全区间 [100ms, 300000ms](MIN_COMMAND_TIMEOUT_MS = 100,MAX_COMMAND_TIMEOUT_MS = 300_000,见 src/openclaw/dispatcher.ts),防止接近 0 的误配置和失控的长驻进程。对于 clawdbot agent 工作流,务必使用 120000(2 分钟),否则可能被默认 5 秒超时提前杀死。
启用所需的环境变量(激活门)
在 shell profile 中导出(避免把密钥写死在 JSON 里):
# 优先用环境变量导出 token(不要在 JSON 中硬编码密钥)
export HOOKS_TOKEN="your-openclaw-hooks-token"
# OpenClaw 投递管道必需
export OMX_OPENCLAW=1
# 命令网关额外必需
export OMX_OPENCLAW_COMMAND=1
# 可选的命令网关全局默认超时(毫秒)
# 优先级:gateway timeout > env 覆盖 > 5000 默认
export OMX_OPENCLAW_COMMAND_TIMEOUT_MS=120000
源码层面,getOpenClawConfig() 的第一道闸就是 process.env.OMX_OPENCLAW !== "1" 时直接返回 null(src/openclaw/config.ts);wakeCommandGateway() 在 OMX_OPENCLAW_COMMAND !== "1" 时返回失败结果 "Command gateway disabled"(src/openclaw/dispatcher.ts)。两道独立闸门的设计意图很明确:HTTP 投递与命令执行的安全边界是分开的。
五、查看与排障:JSONL 日志命令
# JSONL 日志中查看最近条目(提取时间戳与状态)
tail -n 120 /tmp/omx-openclaw-agent.jsonl | jq -s '.[] | {timestamp: (.timestamp // .time), status: (.status // .error // "ok")}'
# 搜索错误
rg '"error"|"failed"|"timeout"' /tmp/omx-openclaw-agent.jsonl | tail -20
若投递看起来异常,可先临时去掉输出重定向直接观察命令输出,再决定是否重试。
手动重试用例(生产已验证参数)
clawdbot agent --session-id omx-hooks \
--message "OMX hook retry 점검: session={{sessionId}} tmux={{tmuxSession}}" \
--thinking minimal --deliver --reply-channel discord --reply-to 'channel:1468539002985644084' \
--timeout 120 --json
六、快速更新模板:一条 jq 命令完成 5 个 hook 改写
不想手写整段 JSON?用下面这条 jq 命令一次性更新 $HOME/.codex/.omx-config.json(注意 shell 中 \n 需写作 \\n):
CONFIG_FILE="$HOME/.codex/.omx-config.json"
jq '.notifications.verbosity = "verbose" |
.notifications.openclaw.hooks["session-start"].instruction = "[session-start|exec]\nproject={{projectName}} session={{sessionId}} tmux={{tmuxSession}}\n요약: 시작 맥락 1문장\n우선순위: 지금 할 일 1~2개\n주의사항: 리스크/의존성(없으면 없음)" |
.notifications.openclaw.hooks["session-idle"].instruction = "[session-idle|exec]\nsession={{sessionId}} tmux={{tmuxSession}}\n요약: idle 원인 1문장\n복구계획: 즉시 조치 1~2개\n의사결정: 사용자 입력 필요 여부" |
.notifications.openclaw.hooks["ask-user-question"].instruction = "[ask-user-question|exec]\nsession={{sessionId}} tmux={{tmuxSession}} question={{question}}\n핵심질문: 필요한 답변 1문장\n영향: 미응답 시 영향 1문장\n권장응답: 가장 빠른 답변 형태" |
.notifications.openclaw.hooks["stop"].instruction = "[session-stop|exec]\nsession={{sessionId}} tmux={{tmuxSession}}\n요약: 중단 사유\n현재상태: 저장/미완료 항목\n재개: 첫 액션 1개" |
.notifications.openclaw.hooks["session-end"].instruction = "[session-end|exec]\nproject={{projectName}} session={{sessionId}} tmux={{tmuxSession}} reason={{reason}}\n성과: 완료 결과 1~2문장\n검증: 확인/테스트 결과\n다음: 후속 액션 1~2개"' "$CONFIG_FILE" > "$CONFIG_FILE.tmp" && mv "$CONFIG_FILE.tmp" "$CONFIG_FILE"
先写临时文件再原子 mv 覆盖,避免 jq 失败时破坏原配置。
七、源码级原理:OmX 的 OpenClaw 投递链路
从 src/openclaw/index.ts 的 wakeOpenClaw() 入口,可以看到完整链路:
- 读配置:
getOpenClawConfig()依次尝试OMX_OPENCLAW_CONFIG独立文件 →notifications.openclaw→custom_cli_command/custom_webhook_command别名归一化(src/openclaw/config.ts),首次读取后缓存; - 解析映射:
resolveGateway()按事件查hooks映射,校验网关存在性与类型必填字段(src/openclaw/config.ts); - 构造上下文:仅白名单字段会被带入模板(src/openclaw/index.ts),防止敏感数据泄漏到网关 payload——这一点在 src/openclaw/types.ts 中通过显式枚举字段、无索引签名的方式在类型层面强制保证;
- 模板插值:
interpolateInstruction()展开{{var}},未解析变量置空;若未显式提供tmuxSession,会自动探测当前 tmux 会话(getCurrentTmuxSession()); - 投递:HTTP 网关走
wakeGateway()(校验 URL 必须 HTTPS,仅 localhost/127.0.0.1/::1 允许 HTTP,见 src/openclaw/dispatcher.ts);命令网关走wakeCommandGateway()。
Shell 安全设计(值得单独强调)
命令网关把 {{instruction}} 等变量插值进命令字符串时,所有变量值会先经 shellEscapeArg() 单引号包裹转义(src/openclaw/dispatcher.ts),防止注入。执行方式按是否含 shell 元字符(/[\|&;><$()]/`)二选一:
- 无元字符:直接用 argv 方式执行(
execFile语义),避免不必要的 shell 解释; - 有元字符:才回退到
sh -c,且经 src/runtime/process-tree.ts 以进程组方式运行,超时/父进程退出时能级联清理 shell 包装器与后代进程(SIGTERM 后 1 秒宽限再 SIGKILL)。
给配置者的实操提醒:文档与源码注释都强调——模板变量会被插值进命令串,请保持模板简单,避免在用户衍生内容中出现 shell 元字符。
八、验证与排障速查
生产接入后,先用最小烟测确认管道通畅:
# token 是否存在
test -n "$HOOKS_TOKEN" && echo "token ok" || echo "token missing"
# 网关可达性
curl -sS -o /dev/null -w "HTTP %{http_code}\n" http://127.0.0.1:18789 || echo "gateway unreachable"
# 激活门检查
test "$OMX_OPENCLAW" = "1" && echo "OMX_OPENCLAW=1" || echo "missing OMX_OPENCLAW=1"
test "$OMX_OPENCLAW_COMMAND" = "1" && echo "OMX_OPENCLAW_COMMAND=1" || echo "missing OMX_OPENCLAW_COMMAND=1"
常见失败信号与对策:
| 现象 | 原因与对策 |
|---|---|
| 401/403 | Bearer token 缺失/无效,检查 HOOKS_TOKEN |
| 404 | 路径写错,核对 /hooks/agent 与 /hooks/wake |
| 5xx | 网关运行期故障,查 JSONL 日志 |
| 超时 / connection refused | 主机/端口/防火墙问题 |
| 命令网关被禁用 | 同时设置 OMX_OPENCLAW=1 与 OMX_OPENCLAW_COMMAND=1 |
| 命令被 SIGTERM 杀死 | 提高 gateways.<name>.timeout(clawdbot 建议 120000)或设置 OMX_OPENCLAW_COMMAND_TIMEOUT_MS |
| hook 失败阻塞会话 | 命令末尾补 || true |
| 日志缺失 | 用 .jsonl 扩展名 + >> 追加写入 |
| Discord 投递失败 | 用 --reply-to 'channel:CHANNEL_ID' 替代频道别名 |
以上配置行为均有仓库测试佐证,例如 src/openclaw/tests/config.test.ts 覆盖了:未设置 OMX_OPENCLAW 时返回 null、OMX_OPENCLAW_CONFIG 独立文件加载、enabled: false / 非法 JSON 返回 null、resolveGateway 对未映射/禁用/缺 url 网关的判定,以及显式 notifications.openclaw 覆盖通用别名(explicitOverridesAliases)的归一化逻辑。
九、相关文档与源码入口
- 英文完整集成指南(含网关/钩子/验证):docs/openclaw-integration.md
- 配置读取与归一化:src/openclaw/config.ts
- HTTP / 命令网关投递与超时解析:src/openclaw/dispatcher.ts
- 公开入口
wakeOpenClaw:src/openclaw/index.ts - 类型与 payload 定义:src/openclaw/types.ts
- 配置读取 / 别名归一化测试:src/openclaw/tests/config.test.ts
- 通知系统其余配置(含 verbosity 默认值):src/notifications/types.ts
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust4.21 K637- DDeepSeek-V4.1-FlashDeepSeek-V4.1-Flash 是一个多模态混合专家(MoE)模型,拥有 5520 亿骨干参数,并支持最多一百万 token 的上下文长度。该模型原生支持图像和文本输入,并以自回归方式生成文本Python270
cherry-studio🍒 Cherry Studio 是一款支持多个 LLM 提供商的桌面客户端TypeScript2 K146
hello-agents📚 《从零开始构建智能体》——从零开始的智能体原理与实践教程Python46066
new-apiAI模型聚合管理中转分发系统,一个应用管理您的所有AI模型,支持将多种大模型转为统一格式调用,支持OpenAI、Claude、Gemini等格式,可供个人或者企业内部管理与分发渠道使用。🍥 A Unified AI Model Management & Distribution System. Aggregate all your LLMs into one app and access them via an OpenAI-compatible API, with native support for Claude (Messages) and Gemini formats.Go20143
JeecgBoot🔥企业级低代码平台集成了AI应用平台,帮助企业快速实现低代码开发和构建AI应用!前后端分离架构 SpringBoot,SpringCloud、Mybatis,Ant Design4、 Vue3.0、TS+vite!强大的代码生成器让前后端代码一键生成,无需写任何代码! 引领AI低代码开发模式: AI生成->OnlineCoding-> 代码生成-> 手工MERGE,显著的提高效率,又不失灵活~Java34051