拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

OpenClaw 人人养虾:openclaw hooks 从零到一实战指南

OpenClaw 人人养虾:openclaw hooks 从零到一实战指南

1. OpenClaw hooks 是什么?能帮你自动做什么

OpenClaw hooks 是 OpenClaw 里的事件钩子机制,说白了就是给系统装上一排“感应开关”:当某个事件发生时,比如收到新消息、会话结束、工具调用完成,OpenClaw 会自动去执行你写好的脚本。你不用一直盯着程序跑,也不用轮询状态,事件一触发,逻辑自己就跑起来了。它适合谁?适合想把重复动作自动化的人,比如收到消息自动记日志、Agent 报错自动通知、会话结束自动备份记录,这些场景都能用 hooks 接住。

我先把核心概念讲清楚,不然后面配置容易懵。OpenClaw hooks 有两个关键点:事件类型和钩子脚本。事件类型决定“什么时候触发”,钩子脚本决定“触发后干什么”。OpenClaw 内置了一批事件,常见的有message.received(收到新消息)、message.sent(消息发送完成)、session.started(新会话开始)、session.ended(会话结束)、agent.error(Agent 发生错误)、tool.executed(工具调用完成)、channel.connected(渠道连接成功)、channel.disconnected(渠道断开)。你写的脚本放在~/.openclaw/hooks/目录下,OpenClaw 启动时会扫描这个目录,把发现的钩子注册进来。

管理这些钩子靠的是openclaw hooks命令族,它有几个子命令:list列出所有已发现的钩子,enable启用指定钩子,disable禁用指定钩子,info查看钩子详情。这几个命令是你日常调试的主力,尤其是list和info,排查问题时几乎离不开。

为什么值得花时间学 hooks?因为它把“被动响应”变成了“主动自动化”。举个例子,你运营一个客服 Agent,每次收到消息都想知道内容,手动翻日志太累。写一个message.received钩子,把消息写进本地文件,或者推送到你的监控面板,整个过程零人工。再比如 Agent 出错时,你希望第一时间知道,agent.error钩子就能触发通知脚本。这些都不是理论,是能直接跑起来的。

不过 hooks 本身只负责“触发”,脚本里如果要调用大模型能力,比如让 Agent 分析消息内容、生成摘要,就需要一个稳定的 API 通道。这里我用 TaoToken 来统一管理 Key 和调用入口,后面第三节会给完整配置。先把 hooks 的基础操作跑通,再接入模型调用,顺序别乱。

这一节你先记住三件事:hooks 是事件驱动的自动化机制,脚本放~/.openclaw/hooks/,管理命令是openclaw hooks list/enable/disable/info。下一节我们把环境准备好,把第一个钩子跑起来。

2. 前置准备:TaoToken 统一 Key 与 OpenClaw 环境

在写第一个 hook 之前,得先把两件事搞定:OpenClaw 本身能跑,以及模型调用通道配好。很多人卡在第二步,因为脚本里一旦要调模型,Key 管理、Base URL、模型 ID 三样缺一不可。我用 TaoToken 来做统一入口,原因是它把 Key 和 API 通道收敛到一处,脚本里不用散落多个密钥,换模型也不用改一堆文件。

先确认 OpenClaw 已安装并能执行命令。打开终端,输入:

openclaw --version

如果能看到版本号,说明主程序就绪。接着确认 hooks 目录存在:

ls -la ~/.openclaw/hooks/

目录不存在就手动建一个:

mkdir -p ~/.openclaw/hooks

然后是 TaoToken 的接入准备。你需要拿到两样东西:API Key 和 Base URL。API Key 在控制台的 API Keys 页面创建,地址是https://taotoken.net/api-keys,创建后复制保存,后面配置里要用。Base URL 固定为https://taotoken.net/api,注意这个地址不带任何查询参数,直接写进配置即可。

模型 ID 根据你要用的模型填,比如对话类、代码类各有对应 ID,在模型对话页面能看到当前可用的模型列表,地址是https://taotoken.net/chat。如果你打算长期跑编码类 Agent,可以了解 Coding Plan,入口在https://taotoken.net/coding-plan。这些链接先记着,配置时按需取用。

环境变量方式是最省事的做法。在~/.bashrc或~/.zshrc里加两行:

export TAOTOKEN_API_KEY="你的API Key" export TAOTOKEN_BASE_URL="https://taotoken.net/api"

保存后执行source ~/.bashrc让配置生效。验证一下:

echo $TAOTOKEN_API_KEY

能打印出 Key 就说明环境变量没问题。这样做的好处是钩子脚本里直接读环境变量,不用把密钥硬编码进代码,安全性和可维护性都好很多。

还有一点容易被忽略:Node.js 环境。OpenClaw 的钩子脚本通常是.js文件,需要 Node 运行时。确认一下:

node --version

建议用 Node 18 以上版本。如果版本太低,钩子脚本里的现代语法可能报错。到这里,OpenClaw 命令可用、hooks 目录就绪、TaoToken 的 Key 和 Base URL 准备好、Node 环境正常,四件事齐了。下一节直接写配置和脚本。

3. 可复制配置:写第一个 hook 并接入 TaoToken

这一节是核心,我会给出一份能直接复制的钩子脚本,以及配套的配置片段。目标场景很明确:当 OpenClaw 收到新消息(message.received)时,触发脚本,把消息内容通过 TaoToken 的 API 通道发给模型做一次摘要,然后把摘要写到本地日志。这个场景覆盖了事件触发、脚本执行、模型调用三个环节,跑通它,其他钩子就是换事件名和换逻辑的事。

先建脚本文件:

touch ~/.openclaw/hooks/log-messages.js

然后用编辑器打开,写入以下内容:

// ~/.openclaw/hooks/log-messages.js const fs = require('fs'); const path = require('path'); const LOG_FILE = path.join(process.env.HOME, '.openclaw', 'hooks', 'messages.log'); const API_KEY = process.env.TAOTOKEN_API_KEY; const BASE_URL = process.env.TAOTOKEN_BASE_URL || 'https://taotoken.net/api'; const MODEL_ID = '你的模型ID'; module.exports = { name: 'log-messages', event: 'message.received', priority: 100, enabled: true, async handler(context) { const { message } = context; const timestamp = new Date().toISOString(); const raw = `[${timestamp}] ${JSON.stringify(message)}\n`; fs.appendFileSync(LOG_FILE, raw); try { const resp = await fetch(`${BASE_URL}/v1/chat/completions`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${API_KEY}` }, body: JSON.stringify({ model: MODEL_ID, messages: [ { role: 'system', content: '你是一个消息摘要助手,用一句话概括用户消息。' }, { role: 'user', content: message.content || '' } ] }) }); const data = await resp.json(); const summary = data.choices?.[0]?.message?.content || '无摘要'; fs.appendFileSync(LOG_FILE, ` 摘要: ${summary}\n`); } catch (err) { fs.appendFileSync(LOG_FILE, ` 摘要失败: ${err.message}\n`); } } };

这份脚本做了两件事:先把原始消息追加到messages.log,再调用 TaoToken 的/v1/chat/completions接口拿摘要,追加到同一文件。注意MODEL_ID要替换成你在模型对话页面看到的实际模型 ID,别照抄占位符。

如果你更习惯用配置文件声明钩子,OpenClaw 也支持在~/.openclaw/config.json里登记。参考片段如下:

{ "hooks": { "log-messages": { "event": "message.received", "script": "~/.openclaw/hooks/log-messages.js", "priority": 100, "enabled": true } }, "api": { "baseUrl": "https://taotoken.net/api", "apiKeyEnv": "TAOTOKEN_API_KEY", "defaultModel": "你的模型ID" } }

这份 JSON 里,hooks段声明钩子名、事件、脚本路径、优先级和启用状态;api段把 Base URL、Key 的环境变量名、默认模型统一登记。这样脚本里读process.env.TAOTOKEN_API_KEY,配置里读api.baseUrl,两边一致,不会出现 Key 写错地方的问题。

三件套再强调一遍:Base URL 是https://taotoken.net/api,Key 从 API Keys 页面创建后放进环境变量,Model ID 从模型对话页面获取。这三样在脚本和配置里必须对齐,任何一处写错都会导致调用失败。

写完脚本和配置后,先别急着启用,用openclaw hooks list确认 OpenClaw 是否发现了这个钩子。如果没发现,检查文件名和路径是否在~/.openclaw/hooks/下,以及脚本是否导出了name和event字段。下一节我们做触发验证。

4. 验证请求:触发 hook 并确认成功结果

配置写完,接下来是验证。验证分两步:先确认钩子被正确发现和启用,再实际触发一次事件,看日志里有没有预期输出。

第一步,列出所有钩子:

openclaw hooks list

正常输出类似:

NAME EVENT STATUS PRIORITY log-messages message.received enabled 100

如果log-messages出现在列表里且状态是enabled,说明发现和注册都成功。如果状态是disabled,执行:

openclaw hooks enable log-messages

再查一次确认状态变了。如果列表里根本没有这个钩子,回到上一节检查脚本路径和导出字段。

第二步,查看钩子详情,确认事件和脚本路径对得上:

openclaw hooks info log-messages

输出会包含事件类型、状态、优先级、脚本路径、最近运行时间和运行次数。这里重点看Script字段指向的路径是不是你实际写的文件,以及Event是不是message.received。

第三步,实际触发。触发方式取决于你的 OpenClaw 运行环境,最直接的办法是发一条测试消息给 Agent。发完之后,查看日志文件:

cat ~/.openclaw/hooks/messages.log

如果看到类似下面的内容,说明整条链路跑通了:

[2025-01-15T14:30:22.000Z] {"content":"你好,帮我看看这个报错"} 摘要: 用户请求协助排查一个报错信息。

原始消息和模型摘要都写进去了,说明事件触发、脚本执行、TaoToken 调用三个环节全部正常。如果只有原始消息没有摘要,说明模型调用那一步出了问题,往下看第五节排查。

也可以用 JSON 格式输出钩子列表,方便脚本化检查:

openclaw hooks list --json

按事件类型过滤:

openclaw hooks list --event message.received

按状态过滤:

openclaw hooks list --status enabled

这几个过滤命令在钩子多了以后特别有用,能快速定位某个事件下挂了哪些钩子。验证通过后,你可以把log-messages的逻辑复制成其他钩子,比如把事件换成agent.error,逻辑换成发通知,就是一个错误告警钩子。事件类型列表在前面第一节已经列过,按需取用即可。

5. 常见报错排查:401、local proxy failed 与 choices 读取失败

钩子跑不起来,报错通常集中在几类。这一节我按真实遇到的顺序列出来,对照着查。

第一类,401 未授权。日志里出现401 Unauthorized或者invalid api key,基本是 Key 的问题。检查三处:环境变量TAOTOKEN_API_KEY是否真的导出成功,脚本里读取的变量名是否和导出的一致,Key 是否在 API Keys 页面被删除或过期。用echo $TAOTOKEN_API_KEY确认终端里能打印出来,如果打印为空,说明source没生效或者写错了文件。另外注意 Key 前后不要有空格,复制时容易带上。

第二类,local proxy failed或连接超时。这类报错说明请求根本没发到 TaoToken,或者网络层被拦了。先确认 Base URL 写的是https://taotoken.net/api,不要多加斜杠或路径。再确认脚本里拼接的完整地址是${BASE_URL}/v1/chat/completions,路径拼错也会导致连接失败。如果本机有网络策略限制,检查是否能正常访问该域名。这类问题不要往 Key 上想,方向是地址和网络。

第三类,reading 'choices'或Cannot read properties of undefined。这个报错说明接口返回了,但返回结构里没有choices字段,脚本去读data.choices[0]就崩了。常见原因是模型 ID 写错,接口返回了错误信息而不是正常补全结果。解决办法是在脚本里先判断resp.ok,不 ok 就把返回体打出来:

if (!resp.ok) { const errText = await resp.text(); fs.appendFileSync(LOG_FILE, ` 接口错误 ${resp.status}: ${errText}\n`); return; }

这样能看到具体错误信息,而不是被choices的报错掩盖。模型 ID 从模型对话页面核对,别用猜测的值。

第四类,OAuth 相关报错。如果你用的是需要 OAuth 授权的客户端,比如某些编码工具,报错里可能出现OAuth token expired或invalid_grant。这类问题不在 hooks 脚本本身,而在客户端的授权配置。检查客户端的授权文件是否过期,重新走一次授权流程。如果是 Codex 这类工具,授权信息通常在auth.json里,确认里面的字段完整。这类报错和 hooks 无关,但会表现为“钩子没触发”,容易误判,所以单独列出来。

第五类,钩子被发现但没执行。openclaw hooks list能看到,但触发事件后日志没变化。检查优先级是否被其他钩子拦截,以及事件名是否拼写正确。message.received和message.recieved差一个字母就不会触发。用openclaw hooks info <name>看Last Run时间,如果一直是初始值,说明根本没被调用。

排查顺序建议:先看openclaw hooks list确认发现和启用,再看日志文件确认脚本是否执行,最后看接口返回确认模型调用是否成功。三段式定位,比盲目改配置快得多。

6. 把 hooks 用起来:从单钩子到自动化流程

跑通第一个钩子之后,真正的价值在于组合。单个log-messages只是记录,把多个钩子按事件串起来,就能形成自动化流程。比如session.started触发初始化脚本,message.received触发摘要和日志,agent.error触发告警,session.ended触发归档。四个钩子各管一段,互不干扰,靠事件驱动衔接。

优先级字段在这里很关键。同一个事件下挂多个钩子时,priority决定执行顺序,数值小的先跑。比如你希望先记录原始消息再生成摘要,就把记录钩子的优先级设成 50,摘要钩子设成 100。如果顺序反了,摘要可能基于不完整的数据。这个细节在钩子多了以后特别重要,建议一开始就规划好优先级。

脚本里的模型调用统一走 TaoToken 的通道,好处是换模型只改一个MODEL_ID,不用动请求逻辑。如果你要长期跑编码类 Agent,Coding Plan 的入口在https://taotoken.net/coding-plan,适合把多个钩子的模型调用收敛到一套配额里管理。需要新建 Key 或者轮换 Key,去https://taotoken.net/api-keys。接入细节和参数说明在文档里,地址是https://taotoken.net/doc。想先试试模型返回效果,模型对话页面在https://taotoken.net/chat,可以直接对话验证。

最后给一个实用建议:钩子脚本里所有外部调用都加 try/catch,并且把错误写进日志。钩子是在事件触发时执行的,一旦抛异常没人接,可能影响主流程。把错误吞掉并记录,比让整个事件处理崩掉要好。日志文件定期清理,避免无限增长。做到这两点,hooks 就能稳定长期运行。

返回列表