first commit

This commit is contained in:
2026-02-28 23:01:30 +08:00
commit 3956ee4806
415 changed files with 74538 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
---
read_when:
- 设置认证过期监控或告警
- 自动化 Claude Code / Codex OAuth 刷新检查
summary: 监控模型提供商的 OAuth 过期状态
title: 认证监控
x-i18n:
generated_at: "2026-02-03T10:03:53Z"
model: claude-opus-4-5
provider: pi
source_hash: eef179af9545ed7ab881f3ccbef998869437fb50cdb4088de8da7223b614fa2b
source_path: automation/auth-monitoring.md
workflow: 15
---
# 认证监控
OpenClaw 通过 `openclaw models status` 提供 OAuth 过期健康状态。请使用该命令进行自动化和告警;脚本是为手机工作流程提供的可选附加功能。
## 推荐方式CLI 检查(可移植)
```bash
openclaw models status --check
```
退出码:
- `0`:正常
- `1`:凭证过期或缺失
- `2`即将过期24 小时内)
此方式适用于 cron/systemd无需额外脚本。
## 可选脚本(运维 / 手机工作流程)
这些脚本位于 `scripts/` 目录下,属于**可选**内容。它们假定你可以通过 SSH 访问 Gateway 网关主机,并针对 systemd + Termux 进行了调优。
- `scripts/claude-auth-status.sh` 现在使用 `openclaw models status --json` 作为数据来源(如果 CLI 不可用则回退到直接读取文件),因此请确保 `openclaw` 在定时器的 `PATH` 中。
- `scripts/auth-monitor.sh`cron/systemd 定时器目标发送告警ntfy 或手机)。
- `scripts/systemd/openclaw-auth-monitor.{service,timer}`systemd 用户定时器。
- `scripts/claude-auth-status.sh`Claude Code + OpenClaw 认证检查器(完整/json/简洁模式)。
- `scripts/mobile-reauth.sh`:通过 SSH 引导的重新认证流程。
- `scripts/termux-quick-auth.sh`:一键小部件状态查看 + 打开认证 URL。
- `scripts/termux-auth-widget.sh`:完整的引导式小部件流程。
- `scripts/termux-sync-widget.sh`:同步 Claude Code 凭证 → OpenClaw。
如果你不需要手机自动化或 systemd 定时器,可以跳过这些脚本。

View File

@@ -0,0 +1,424 @@
---
read_when:
- 调度后台任务或唤醒
- 配置需要与心跳一起或并行运行的自动化
- 在心跳和定时任务之间做选择
summary: Gateway网关调度器的定时任务与唤醒
title: 定时任务
x-i18n:
generated_at: "2026-02-01T19:37:32Z"
model: claude-opus-4-5
provider: pi
source_hash: d43268b0029f1b13d0825ddcc9c06a354987ea17ce02f3b5428a9c68bf936676
source_path: automation/cron-jobs.md
workflow: 14
---
# 定时任务Gateway网关调度器
> **定时任务还是心跳?** 请参阅[定时任务与心跳对比](/automation/cron-vs-heartbeat)了解何时使用哪种方式。
定时任务是 Gateway网关内置的调度器。它持久化任务、在合适的时间唤醒智能体并可选择将输出发送回聊天。
如果你想要 _"每天早上运行"__"20 分钟后提醒智能体"_,定时任务就是对应的机制。
## 简要概述
- 定时任务运行在 **Gateway网关内部**(而非模型内部)。
- 任务持久化存储在 `~/.openclaw/cron/` 下,因此重启不会丢失计划。
- 两种执行方式:
- **主会话**:入队一个系统事件,然后在下一次心跳时运行。
- **隔离式**:在 `cron:<jobId>` 中运行专用智能体轮次,可投递摘要(默认 announce或不投递。
- 唤醒是一等功能:任务可以请求"立即唤醒"或"下次心跳时"。
## 快速开始(可操作)
创建一个一次性提醒,验证其存在,然后立即运行:
```bash
openclaw cron add \
--name "Reminder" \
--at "2026-02-01T16:00:00Z" \
--session main \
--system-event "Reminder: check the cron docs draft" \
--wake now \
--delete-after-run
openclaw cron list
openclaw cron run <job-id> --force
openclaw cron runs --id <job-id>
```
调度一个带投递功能的周期性隔离任务:
```bash
openclaw cron add \
--name "Morning brief" \
--cron "0 7 * * *" \
--tz "America/Los_Angeles" \
--session isolated \
--message "Summarize overnight updates." \
--announce \
--channel slack \
--to "channel:C1234567890"
```
## 工具调用等价形式Gateway网关定时任务工具
有关规范的 JSON 结构和示例,请参阅[工具调用的 JSON 模式](/automation/cron-jobs#json-schema-for-tool-calls)。
## 定时任务的存储位置
定时任务默认持久化存储在 Gateway网关主机的 `~/.openclaw/cron/jobs.json` 中。Gateway网关将文件加载到内存中并在更改时写回因此仅在 Gateway网关停止时手动编辑才是安全的。请优先使用 `openclaw cron add/edit` 或定时任务工具调用 API 进行更改。
## 新手友好概述
将定时任务理解为:**何时**运行 + **做什么**
1. **选择调度计划**
- 一次性提醒 → `schedule.kind = "at"`CLI`--at`
- 重复任务 → `schedule.kind = "every"``schedule.kind = "cron"`
- 如果你的 ISO 时间戳省略了时区,将被视为 **UTC**
2. **选择运行位置**
- `sessionTarget: "main"` → 在下一次心跳时使用主会话上下文运行。
- `sessionTarget: "isolated"` → 在 `cron:<jobId>` 中运行专用智能体轮次。
3. **选择负载**
- 主会话 → `payload.kind = "systemEvent"`
- 隔离会话 → `payload.kind = "agentTurn"`
可选:一次性任务(`schedule.kind = "at"`)默认会在成功运行后删除。设置
`deleteAfterRun: false` 可保留它(成功后会禁用)。
## 概念
### 任务
定时任务是一条存储记录,包含:
- 一个**调度计划**(何时运行),
- 一个**负载**(做什么),
- 可选的**投递**(输出发送到哪里)。
- 可选的**智能体绑定**`agentId`在指定智能体下运行任务如果缺失或未知Gateway网关会回退到默认智能体。
任务通过稳定的 `jobId` 标识(用于 CLI/Gateway网关 API
在智能体工具调用中,`jobId` 是规范字段;旧版 `id` 仍可兼容使用。
一次性任务默认会在成功运行后自动删除;设置 `deleteAfterRun: false` 可保留它。
### 调度计划
定时任务支持三种调度类型:
- `at`一次性时间戳ISO 8601 字符串)。
- `every`:固定间隔(毫秒)。
- `cron`5 字段 cron 表达式,可选 IANA 时区。
Cron 表达式使用 `croner`。如果省略时区,将使用 Gateway网关主机的本地时区。
### 主会话与隔离式执行
#### 主会话任务(系统事件)
主会话任务入队一个系统事件,并可选择唤醒心跳运行器。它们必须使用 `payload.kind = "systemEvent"`
- `wakeMode: "next-heartbeat"`(默认):事件等待下一次计划心跳。
- `wakeMode: "now"`:事件触发立即心跳运行。
当你需要正常的心跳提示 + 主会话上下文时,这是最佳选择。参见[心跳](/gateway/heartbeat)。
#### 隔离任务(专用定时会话)
隔离任务在会话 `cron:<jobId>` 中运行专用智能体轮次。
关键行为:
- 提示以 `[cron:<jobId> <任务名称>]` 为前缀,便于追踪。
- 每次运行都会启动一个**全新的会话 ID**(不继承之前的对话)。
- 如果未指定 `delivery`隔离任务会默认以“announce”方式投递摘要。
- `delivery.mode` 可选 `announce`(投递摘要)或 `none`(内部运行)。
对于嘈杂、频繁或"后台杂务"类任务,使用隔离任务可以避免污染你的主聊天记录。
### 负载结构(运行内容)
支持两种负载类型:
- `systemEvent`:仅限主会话,通过心跳提示路由。
- `agentTurn`:仅限隔离会话,运行专用智能体轮次。
常用 `agentTurn` 字段:
- `message`:必填文本提示。
- `model` / `thinking`:可选覆盖(见下文)。
- `timeoutSeconds`:可选超时覆盖。
### 模型和思维覆盖
隔离任务(`agentTurn`)可以覆盖模型和思维级别:
- `model`:提供商/模型字符串(例如 `anthropic/claude-sonnet-4-20250514`)或别名(例如 `opus`
- `thinking`:思维级别(`off``minimal``low``medium``high``xhigh`;仅限 GPT-5.2 + Codex 模型)
注意:你也可以在主会话任务上设置 `model`,但这会更改共享的主会话模型。我们建议仅对隔离任务使用模型覆盖,以避免意外的上下文切换。
优先级解析顺序:
1. 任务负载覆盖(最高优先级)
2. 钩子特定默认值(例如 `hooks.gmail.model`
3. 智能体配置默认值
### 投递(渠道 + 目标)
隔离任务可以通过顶层 `delivery` 配置投递输出:
- `delivery.mode``announce`(投递摘要)或 `none`
- `delivery.channel``whatsapp` / `telegram` / `discord` / `slack` / `mattermost`(插件)/ `signal` / `imessage` / `last`
- `delivery.to`:渠道特定的接收目标
- `delivery.bestEffort`:投递失败时避免任务失败
当启用 announce 投递时,该轮次会抑制消息工具发送;请使用 `delivery.channel`/`delivery.to` 来指定目标。
如果省略 `delivery.channel``delivery.to`,定时任务会回退到主会话的“最后路由”(智能体最后回复的位置)。
目标格式提醒:
- Slack/Discord/Mattermost插件目标应使用明确前缀例如 `channel:<id>``user:<id>`)以避免歧义。
- Telegram 主题应使用 `:topic:` 格式(见下文)。
#### Telegram 投递目标(主题/论坛帖子)
Telegram 通过 `message_thread_id` 支持论坛主题。对于定时任务投递,你可以将主题/帖子编码到 `to` 字段中:
- `-1001234567890`(仅聊天 ID
- `-1001234567890:topic:123`(推荐:明确的主题标记)
- `-1001234567890:123`(简写:数字后缀)
带前缀的目标如 `telegram:...` / `telegram:group:...` 也可接受:
- `telegram:group:-1001234567890:topic:123`
## 工具调用的 JSON 模式
直接调用 Gateway网关 `cron.*` 工具(智能体工具调用或 RPC时使用这些结构。CLI 标志接受人类可读的时间格式如 `20m`,但工具调用应使用 ISO 8601 字符串作为 `schedule.at`,并使用毫秒作为 `schedule.everyMs`
### cron.add 参数
一次性主会话任务(系统事件):
```json
{
"name": "Reminder",
"schedule": { "kind": "at", "at": "2026-02-01T16:00:00Z" },
"sessionTarget": "main",
"wakeMode": "now",
"payload": { "kind": "systemEvent", "text": "Reminder text" },
"deleteAfterRun": true
}
```
带投递的周期性隔离任务:
```json
{
"name": "Morning brief",
"schedule": { "kind": "cron", "expr": "0 7 * * *", "tz": "America/Los_Angeles" },
"sessionTarget": "isolated",
"wakeMode": "next-heartbeat",
"payload": {
"kind": "agentTurn",
"message": "Summarize overnight updates."
},
"delivery": {
"mode": "announce",
"channel": "slack",
"to": "channel:C1234567890",
"bestEffort": true
}
}
```
说明:
- `schedule.kind``at``at`)、`every``everyMs`)或 `cron``expr`,可选 `tz`)。
- `schedule.at` 接受 ISO 8601可省略时区省略时按 UTC 处理)。
- `everyMs` 为毫秒数。
- `sessionTarget` 必须为 `"main"``"isolated"`,且必须与 `payload.kind` 匹配。
- 可选字段:`agentId``description``enabled``deleteAfterRun``delivery`
- `wakeMode` 省略时默认为 `"next-heartbeat"`
### cron.update 参数
```json
{
"jobId": "job-123",
"patch": {
"enabled": false,
"schedule": { "kind": "every", "everyMs": 3600000 }
}
}
```
说明:
- `jobId` 是规范字段;`id` 可兼容使用。
- 在补丁中使用 `agentId: null` 可清除智能体绑定。
### cron.run 和 cron.remove 参数
```json
{ "jobId": "job-123", "mode": "force" }
```
```json
{ "jobId": "job-123" }
```
## 存储与历史
- 任务存储:`~/.openclaw/cron/jobs.json`Gateway网关管理的 JSON
- 运行历史:`~/.openclaw/cron/runs/<jobId>.jsonl`JSONL自动清理
- 覆盖存储路径:配置中的 `cron.store`
## 配置
```json5
{
cron: {
enabled: true, // 默认 true
store: "~/.openclaw/cron/jobs.json",
maxConcurrentRuns: 1, // 默认 1
},
}
```
完全禁用定时任务:
- `cron.enabled: false`(配置)
- `OPENCLAW_SKIP_CRON=1`(环境变量)
## CLI 快速开始
一次性提醒UTC ISO成功后自动删除
```bash
openclaw cron add \
--name "Send reminder" \
--at "2026-01-12T18:00:00Z" \
--session main \
--system-event "Reminder: submit expense report." \
--wake now \
--delete-after-run
```
一次性提醒(主会话,立即唤醒):
```bash
openclaw cron add \
--name "Calendar check" \
--at "20m" \
--session main \
--system-event "Next heartbeat: check calendar." \
--wake now
```
周期性隔离任务(投递到 WhatsApp
```bash
openclaw cron add \
--name "Morning status" \
--cron "0 7 * * *" \
--tz "America/Los_Angeles" \
--session isolated \
--message "Summarize inbox + calendar for today." \
--announce \
--channel whatsapp \
--to "+15551234567"
```
周期性隔离任务(投递到 Telegram 主题):
```bash
openclaw cron add \
--name "Nightly summary (topic)" \
--cron "0 22 * * *" \
--tz "America/Los_Angeles" \
--session isolated \
--message "Summarize today; send to the nightly topic." \
--announce \
--channel telegram \
--to "-1001234567890:topic:123"
```
带模型和思维覆盖的隔离任务:
```bash
openclaw cron add \
--name "Deep analysis" \
--cron "0 6 * * 1" \
--tz "America/Los_Angeles" \
--session isolated \
--message "Weekly deep analysis of project progress." \
--model "opus" \
--thinking high \
--announce \
--channel whatsapp \
--to "+15551234567"
```
智能体选择(多智能体配置):
```bash
# 将任务绑定到智能体 "ops"(如果该智能体不存在则回退到默认智能体)
openclaw cron add --name "Ops sweep" --cron "0 6 * * *" --session isolated --message "Check ops queue" --agent ops
# 切换或清除现有任务的智能体
openclaw cron edit <jobId> --agent ops
openclaw cron edit <jobId> --clear-agent
```
手动运行(调试):
```bash
openclaw cron run <jobId> --force
```
编辑现有任务(补丁字段):
```bash
openclaw cron edit <jobId> \
--message "Updated prompt" \
--model "opus" \
--thinking low
```
运行历史:
```bash
openclaw cron runs --id <jobId> --limit 50
```
不创建任务直接发送系统事件:
```bash
openclaw system event --mode now --text "Next heartbeat: check battery."
```
## Gateway网关 API 接口
- `cron.list``cron.status``cron.add``cron.update``cron.remove`
- `cron.run`(强制或到期)、`cron.runs`
如需不创建任务直接发送系统事件,请使用 [`openclaw system event`](/cli/system)。
## 故障排除
### "没有任何任务运行"
- 检查定时任务是否已启用:`cron.enabled``OPENCLAW_SKIP_CRON`
- 检查 Gateway网关是否持续运行定时任务运行在 Gateway网关进程内部
- 对于 `cron` 调度:确认时区(`--tz`)与主机时区的关系。
### Telegram 投递到了错误的位置
- 对于论坛主题,使用 `-100…:topic:<id>` 以确保明确无歧义。
- 如果你在日志或存储的"最后路由"目标中看到 `telegram:...` 前缀,这是正常的;定时任务投递接受这些前缀并仍能正确解析主题 ID。

View File

@@ -0,0 +1,286 @@
---
read_when:
- 决定如何调度周期性任务
- 设置后台监控或通知
- 优化定期检查的 token 用量
summary: 选择心跳还是定时任务进行自动化的指南
title: 定时任务与心跳对比
x-i18n:
generated_at: "2026-02-01T19:38:18Z"
model: claude-opus-4-5
provider: pi
source_hash: 5f71a63181baa41b1c307eb7bfac561df7943d4627077dfa2861eb9f76ab086b
source_path: automation/cron-vs-heartbeat.md
workflow: 14
---
# 定时任务与心跳:何时使用哪种方式
心跳和定时任务都可以按计划运行任务。本指南帮助你根据使用场景选择合适的机制。
## 快速决策指南
| 使用场景 | 推荐方式 | 原因 |
| ------------------------- | -------------------------- | ---------------------------------------- |
| 每 30 分钟检查收件箱 | 心跳 | 可与其他检查批量处理,具备上下文感知能力 |
| 每天上午 9 点准时发送报告 | 定时任务(隔离式) | 需要精确定时 |
| 监控日历中即将到来的事件 | 心跳 | 天然适合周期性感知 |
| 运行每周深度分析 | 定时任务(隔离式) | 独立任务,可使用不同模型 |
| 20 分钟后提醒我 | 定时任务(主会话,`--at` | 精确定时的一次性任务 |
| 后台项目健康检查 | 心跳 | 搭载在现有周期上 |
## 心跳:周期性感知
心跳在**主会话**中以固定间隔运行默认30 分钟)。它的设计目的是让智能体检查各种事项并呈现重要信息。
### 何时使用心跳
- **多个周期性检查**:与其设置 5 个独立的定时任务分别检查收件箱、日历、天气、通知和项目状态,不如用一次心跳批量处理所有内容。
- **上下文感知决策**:智能体拥有完整的主会话上下文,因此可以智能判断哪些紧急、哪些可以等待。
- **对话连续性**:心跳运行共享同一会话,因此智能体记得最近的对话,可以自然地进行后续跟进。
- **低开销监控**:一次心跳替代多个小型轮询任务。
### 心跳优势
- **批量处理多项检查**:一次智能体轮次可以同时审查收件箱、日历和通知。
- **减少 API 调用**:一次心跳比 5 个隔离式定时任务更经济。
- **上下文感知**:智能体了解你一直在做什么,可以据此排定优先级。
- **智能抑制**:如果没有需要关注的事项,智能体回复 `HEARTBEAT_OK`,不会投递任何消息。
- **自然定时**:会根据队列负载略有漂移,但对大多数监控来说没有问题。
### 心跳示例HEARTBEAT.md 检查清单
```md
# Heartbeat checklist
- Check email for urgent messages
- Review calendar for events in next 2 hours
- If a background task finished, summarize results
- If idle for 8+ hours, send a brief check-in
```
智能体在每次心跳时读取此清单,并在一次轮次中处理所有项目。
### 配置心跳
```json5
{
agents: {
defaults: {
heartbeat: {
every: "30m", // 间隔
target: "last", // 告警投递目标
activeHours: { start: "08:00", end: "22:00" }, // 可选
},
},
},
}
```
完整配置请参阅[心跳](/gateway/heartbeat)。
## 定时任务:精确调度
定时任务在**精确时间**运行,可以在隔离会话中运行而不影响主会话上下文。
### 何时使用定时任务
- **需要精确定时**"每周一上午 9:00 发送"(而不是"大约 9 点左右")。
- **独立任务**:不需要对话上下文的任务。
- **不同的模型/思维级别**:需要更强大模型的深度分析。
- **一次性提醒**:使用 `--at` 实现"20 分钟后提醒我"。
- **嘈杂/频繁的任务**:会把主会话历史搞得杂乱的任务。
- **外部触发器**:无论智能体是否处于活跃状态都应独立运行的任务。
### 定时任务优势
- **精确定时**:支持带时区的 5 字段 cron 表达式。
- **会话隔离**:在 `cron:<jobId>` 中运行,不会污染主会话历史。
- **模型覆盖**:可按任务使用更便宜或更强大的模型。
- **投递控制**:隔离任务默认以 `announce` 投递摘要,可选 `none` 仅内部运行。
- **无需智能体上下文**:即使主会话空闲或已压缩,也能运行。
- **一次性支持**`--at` 用于精确的未来时间戳。
### 定时任务示例:每日早间简报
```bash
openclaw cron add \
--name "Morning briefing" \
--cron "0 7 * * *" \
--tz "America/New_York" \
--session isolated \
--message "Generate today's briefing: weather, calendar, top emails, news summary." \
--model opus \
--announce \
--channel whatsapp \
--to "+15551234567"
```
这会在纽约时间每天早上 7:00 准时运行,使用 Opus 保证质量,并直接投递到 WhatsApp。
### 定时任务示例:一次性提醒
```bash
openclaw cron add \
--name "Meeting reminder" \
--at "20m" \
--session main \
--system-event "Reminder: standup meeting starts in 10 minutes." \
--wake now \
--delete-after-run
```
完整 CLI 参考请参阅[定时任务](/automation/cron-jobs)。
## 决策流程图
```
任务是否需要在精确时间运行?
是 -> 使用定时任务
否 -> 继续...
任务是否需要与主会话隔离?
是 -> 使用定时任务(隔离式)
否 -> 继续...
此任务能否与其他周期性检查批量处理?
是 -> 使用心跳(添加到 HEARTBEAT.md
否 -> 使用定时任务
这是一次性提醒吗?
是 -> 使用定时任务配合 --at
否 -> 继续...
是否需要不同的模型或思维级别?
是 -> 使用定时任务(隔离式)配合 --model/--thinking
否 -> 使用心跳
```
## 组合使用
最高效的配置是**两者结合**
1. **心跳**处理常规监控(收件箱、日历、通知),每 30 分钟批量处理一次。
2. **定时任务**处理精确调度(每日报告、每周回顾)和一次性提醒。
### 示例:高效自动化配置
**HEARTBEAT.md**(每 30 分钟检查一次):
```md
# Heartbeat checklist
- Scan inbox for urgent emails
- Check calendar for events in next 2h
- Review any pending tasks
- Light check-in if quiet for 8+ hours
```
**定时任务**(精确定时):
```bash
# 每天早上 7 点的早间简报
openclaw cron add --name "Morning brief" --cron "0 7 * * *" --session isolated --message "..." --announce
# 每周一上午 9 点的项目回顾
openclaw cron add --name "Weekly review" --cron "0 9 * * 1" --session isolated --message "..." --model opus
# 一次性提醒
openclaw cron add --name "Call back" --at "2h" --session main --system-event "Call back the client" --wake now
```
## Lobster带审批的确定性工作流
Lobster 是用于**多步骤工具管道**的工作流运行时,适用于需要确定性执行和明确审批的场景。当任务不只是单次智能体轮次,且你需要可恢复的带人工检查点的工作流时,使用它。
### 何时适合使用 Lobster
- **多步骤自动化**:你需要一个固定的工具调用管道,而不是一次性提示。
- **审批关卡**:副作用应暂停直到你批准,然后继续执行。
- **可恢复运行**:继续暂停的工作流而无需重新运行之前的步骤。
### 如何与心跳和定时任务配合
- **心跳/定时任务**决定*何时*运行。
- **Lobster** 定义运行开始后*执行哪些步骤*。
对于计划性工作流,使用定时任务或心跳触发一次调用 Lobster 的智能体轮次。对于临时工作流,直接调用 Lobster。
### 操作说明(来自代码)
- Lobster 以**本地子进程**`lobster` CLI在工具模式下运行并返回 **JSON 信封**
- 如果工具返回 `needs_approval`,你需要使用 `resumeToken``approve` 标志来恢复。
- 该工具是**可选插件**;建议通过 `tools.alsoAllow: ["lobster"]` 附加启用。
- 如果传入 `lobsterPath`,必须是**绝对路径**。
完整用法和示例请参阅 [Lobster](/tools/lobster)。
## 主会话与隔离会话
心跳和定时任务都可以与主会话交互,但方式不同:
| | 心跳 | 定时任务(主会话) | 定时任务(隔离式) |
| ------ | ------------------------ | ---------------------- | --------------------- |
| 会话 | 主会话 | 主会话(通过系统事件) | `cron:<jobId>` |
| 历史 | 共享 | 共享 | 每次运行全新 |
| 上下文 | 完整 | 完整 | 无(从零开始) |
| 模型 | 主会话模型 | 主会话模型 | 可覆盖 |
| 输出 | 非 `HEARTBEAT_OK` 时投递 | 心跳提示 + 事件 | announce 摘要(默认) |
### 何时使用主会话定时任务
当你需要以下场景时,使用 `--session main` 配合 `--system-event`
- 提醒/事件出现在主会话上下文中
- 智能体在下一次心跳时带着完整上下文处理它
- 不需要单独的隔离运行
```bash
openclaw cron add \
--name "Check project" \
--every "4h" \
--session main \
--system-event "Time for a project health check" \
--wake now
```
### 何时使用隔离式定时任务
当你需要以下场景时,使用 `--session isolated`
- 无先前上下文的全新环境
- 不同的模型或思维设置
- 输出可通过 `announce` 直接投递摘要(或用 `none` 仅内部运行)
- 不会把主会话搞得杂乱的历史记录
```bash
openclaw cron add \
--name "Deep analysis" \
--cron "0 6 * * 0" \
--session isolated \
--message "Weekly codebase analysis..." \
--model opus \
--thinking high \
--announce
```
## 成本考量
| 机制 | 成本特征 |
| ------------------ | ---------------------------------------------- |
| 心跳 | 每 N 分钟一次轮次;随 HEARTBEAT.md 大小扩展 |
| 定时任务(主会话) | 将事件添加到下一次心跳(无隔离轮次) |
| 定时任务(隔离式) | 每个任务一次完整智能体轮次;可使用更便宜的模型 |
**建议**
- 保持 `HEARTBEAT.md` 精简以减少 token 开销。
- 将类似的检查批量放入心跳,而不是创建多个定时任务。
- 如果只需要内部处理,在心跳上使用 `target: "none"`
- 对常规任务使用隔离式定时任务配合更便宜的模型。
## 相关内容
- [心跳](/gateway/heartbeat) - 完整的心跳配置
- [定时任务](/automation/cron-jobs) - 完整的定时任务 CLI 和 API 参考
- [系统](/cli/system) - 系统事件 + 心跳控制

View File

@@ -0,0 +1,249 @@
---
read_when:
- 将 Gmail 收件箱触发器接入 OpenClaw
- 为智能体唤醒设置 Pub/Sub 推送
summary: 通过 gogcli 将 Gmail Pub/Sub 推送接入 OpenClaw webhooks
title: Gmail PubSub
x-i18n:
generated_at: "2026-02-03T07:43:25Z"
model: claude-opus-4-5
provider: pi
source_hash: dfb92133b69177e4e984b7d072f5dc28aa53a9e0cf984a018145ed811aa96195
source_path: automation/gmail-pubsub.md
workflow: 15
---
# Gmail Pub/Sub -> OpenClaw
目标Gmail watch -> Pub/Sub 推送 -> `gog gmail watch serve` -> OpenClaw webhook。
## 前置条件
- 已安装并登录 `gcloud`[安装指南](https://docs.cloud.google.com/sdk/docs/install-sdk))。
- 已安装 `gog` (gogcli) 并为 Gmail 账户授权([gogcli.sh](https://gogcli.sh/))。
- 已启用 OpenClaw hooks参见 [Webhooks](/automation/webhook))。
- 已登录 `tailscale`[tailscale.com](https://tailscale.com/))。支持的设置使用 Tailscale Funnel 作为公共 HTTPS 端点。
其他隧道服务也可以使用,但需要自行配置/不受支持,需要手动接入。
目前,我们支持的是 Tailscale。
示例 hook 配置(启用 Gmail 预设映射):
```json5
{
hooks: {
enabled: true,
token: "OPENCLAW_HOOK_TOKEN",
path: "/hooks",
presets: ["gmail"],
},
}
```
要将 Gmail 摘要投递到聊天界面,请用设置了 `deliver` 以及可选的 `channel`/`to` 的映射覆盖预设:
```json5
{
hooks: {
enabled: true,
token: "OPENCLAW_HOOK_TOKEN",
presets: ["gmail"],
mappings: [
{
match: { path: "gmail" },
action: "agent",
wakeMode: "now",
name: "Gmail",
sessionKey: "hook:gmail:{{messages[0].id}}",
messageTemplate: "New email from {{messages[0].from}}\nSubject: {{messages[0].subject}}\n{{messages[0].snippet}}\n{{messages[0].body}}",
model: "openai/gpt-5.2-mini",
deliver: true,
channel: "last",
// to: "+15551234567"
},
],
},
}
```
如果你想使用固定渠道,请设置 `channel` + `to`。否则 `channel: "last"` 会使用上次的投递路由(默认回退到 WhatsApp
要为 Gmail 运行强制使用更便宜的模型,请在映射中设置 `model``provider/model` 或别名)。如果你强制启用了 `agents.defaults.models`,请将其包含在内。
要专门为 Gmail hooks 设置默认模型和思考级别,请在配置中添加 `hooks.gmail.model` / `hooks.gmail.thinking`
```json5
{
hooks: {
gmail: {
model: "openrouter/meta-llama/llama-3.3-70b-instruct:free",
thinking: "off",
},
},
}
```
注意事项:
- 映射中的每个 hook 的 `model`/`thinking` 仍会覆盖这些默认值。
- 回退顺序:`hooks.gmail.model``agents.defaults.model.fallbacks` → 主模型(认证/速率限制/超时)。
- 如果设置了 `agents.defaults.models`Gmail 模型必须在允许列表中。
- Gmail hook 内容默认使用外部内容安全边界包装。
要禁用(危险),请设置 `hooks.gmail.allowUnsafeExternalContent: true`
要进一步自定义负载处理,请添加 `hooks.mappings` 或在 `hooks.transformsDir` 下添加 JS/TS 转换模块(参见 [Webhooks](/automation/webhook))。
## 向导(推荐)
使用 OpenClaw 助手将所有内容接入在一起(在 macOS 上通过 brew 安装依赖):
```bash
openclaw webhooks gmail setup \
--account openclaw@gmail.com
```
默认设置:
- 使用 Tailscale Funnel 作为公共推送端点。
-`openclaw webhooks gmail run` 写入 `hooks.gmail` 配置。
- 启用 Gmail hook 预设(`hooks.presets: ["gmail"]`)。
路径说明:当启用 `tailscale.mode`OpenClaw 会自动将 `hooks.gmail.serve.path` 设置为 `/`,并将公共路径保持在 `hooks.gmail.tailscale.path`(默认 `/gmail-pubsub`),因为 Tailscale 在代理之前会剥离设置的路径前缀。
如果你需要后端接收带前缀的路径,请将 `hooks.gmail.tailscale.target`(或 `--tailscale-target`)设置为完整 URL`http://127.0.0.1:8788/gmail-pubsub`,并匹配 `hooks.gmail.serve.path`
想要自定义端点?使用 `--push-endpoint <url>``--tailscale off`
平台说明:在 macOS 上,向导通过 Homebrew 安装 `gcloud``gogcli``tailscale`;在 Linux 上请先手动安装它们。
Gateway 网关自动启动(推荐):
-`hooks.enabled=true` 且设置了 `hooks.gmail.account`Gateway 网关会在启动时运行 `gog gmail watch serve` 并自动续期 watch。
- 设置 `OPENCLAW_SKIP_GMAIL_WATCHER=1` 可退出(如果你自己运行守护进程则很有用)。
- 不要同时运行手动守护进程,否则会遇到 `listen tcp 127.0.0.1:8788: bind: address already in use`
手动守护进程(启动 `gog gmail watch serve` + 自动续期):
```bash
openclaw webhooks gmail run
```
## 一次性设置
1. 选择**拥有 `gog` 使用的 OAuth 客户端**的 GCP 项目。
```bash
gcloud auth login
gcloud config set project <project-id>
```
注意Gmail watch 要求 Pub/Sub 主题与 OAuth 客户端位于同一项目中。
2. 启用 API
```bash
gcloud services enable gmail.googleapis.com pubsub.googleapis.com
```
3. 创建主题:
```bash
gcloud pubsub topics create gog-gmail-watch
```
4. 允许 Gmail push 发布:
```bash
gcloud pubsub topics add-iam-policy-binding gog-gmail-watch \
--member=serviceAccount:gmail-api-push@system.gserviceaccount.com \
--role=roles/pubsub.publisher
```
## 启动 watch
```bash
gog gmail watch start \
--account openclaw@gmail.com \
--label INBOX \
--topic projects/<project-id>/topics/gog-gmail-watch
```
保存输出中的 `history_id`(用于调试)。
## 运行推送处理程序
本地示例(共享 token 认证):
```bash
gog gmail watch serve \
--account openclaw@gmail.com \
--bind 127.0.0.1 \
--port 8788 \
--path /gmail-pubsub \
--token <shared> \
--hook-url http://127.0.0.1:18789/hooks/gmail \
--hook-token OPENCLAW_HOOK_TOKEN \
--include-body \
--max-bytes 20000
```
注意事项:
- `--token` 保护推送端点(`x-gog-token``?token=`)。
- `--hook-url` 指向 OpenClaw `/hooks/gmail`(已映射;隔离运行 + 摘要发送到主线程)。
- `--include-body``--max-bytes` 控制发送到 OpenClaw 的正文片段。
推荐:`openclaw webhooks gmail run` 封装了相同的流程并自动续期 watch。
## 暴露处理程序(高级,不受支持)
如果你需要非 Tailscale 隧道,请手动接入并在推送订阅中使用公共 URL不受支持无保护措施
```bash
cloudflared tunnel --url http://127.0.0.1:8788 --no-autoupdate
```
使用生成的 URL 作为推送端点:
```bash
gcloud pubsub subscriptions create gog-gmail-watch-push \
--topic gog-gmail-watch \
--push-endpoint "https://<public-url>/gmail-pubsub?token=<shared>"
```
生产环境:使用稳定的 HTTPS 端点并配置 Pub/Sub OIDC JWT然后运行
```bash
gog gmail watch serve --verify-oidc --oidc-email <svc@...>
```
## 测试
向被监视的收件箱发送一条消息:
```bash
gog gmail send \
--account openclaw@gmail.com \
--to openclaw@gmail.com \
--subject "watch test" \
--body "ping"
```
检查 watch 状态和历史记录:
```bash
gog gmail watch status --account openclaw@gmail.com
gog gmail history --account openclaw@gmail.com --since <historyId>
```
## 故障排除
- `Invalid topicName`:项目不匹配(主题不在 OAuth 客户端项目中)。
- `User not authorized`:主题缺少 `roles/pubsub.publisher`
- 空消息Gmail push 仅提供 `historyId`;通过 `gog gmail history` 获取。
## 清理
```bash
gog gmail watch stop --account openclaw@gmail.com
gcloud pubsub subscriptions delete gog-gmail-watch-push
gcloud pubsub topics delete gog-gmail-watch
```

882
content/automation/hooks.md Normal file
View File

@@ -0,0 +1,882 @@
---
read_when:
- 你想为 /new、/reset、/stop 和智能体生命周期事件实现事件驱动自动化
- 你想构建、安装或调试 hooks
summary: Hooks用于命令和生命周期事件的事件驱动自动化
title: Hooks
x-i18n:
generated_at: "2026-02-03T07:50:59Z"
model: claude-opus-4-5
provider: pi
source_hash: 853227a0f1abd20790b425fa64dda60efc6b5f93c1b13ecd2dcb788268f71d79
source_path: automation/hooks.md
workflow: 15
---
# Hooks
Hooks 提供了一个可扩展的事件驱动系统用于响应智能体命令和事件自动执行操作。Hooks 从目录中自动发现,可以通过 CLI 命令管理,类似于 OpenClaw 中 Skills 的工作方式。
## 入门指南
Hooks 是在事件发生时运行的小脚本。有两种类型:
- **Hooks**(本页):当智能体事件触发时在 Gateway 网关内运行,如 `/new``/reset``/stop` 或生命周期事件。
- **Webhooks**:外部 HTTP webhooks让其他系统触发 OpenClaw 中的工作。参见 [Webhook Hooks](/automation/webhook) 或使用 `openclaw webhooks` 获取 Gmail 助手命令。
Hooks 也可以捆绑在插件中;参见 [插件](/tools/plugin#plugin-hooks)。
常见用途:
- 重置会话时保存记忆快照
- 保留命令审计跟踪用于故障排除或合规
- 会话开始或结束时触发后续自动化
- 事件触发时向智能体工作区写入文件或调用外部 API
如果你能写一个小的 TypeScript 函数,你就能写一个 hook。Hooks 会自动发现,你可以通过 CLI 启用或禁用它们。
## 概述
hooks 系统允许你:
- 在发出 `/new` 时将会话上下文保存到记忆
- 记录所有命令以供审计
- 在智能体生命周期事件上触发自定义自动化
- 在不修改核心代码的情况下扩展 OpenClaw 的行为
## 入门
### 捆绑的 Hooks
OpenClaw 附带三个自动发现的捆绑 hooks
- **💾 session-memory**:当你发出 `/new` 时将会话上下文保存到智能体工作区(默认 `~/.openclaw/workspace/memory/`
- **📝 command-logger**:将所有命令事件记录到 `~/.openclaw/logs/commands.log`
- **🚀 boot-md**:当 Gateway 网关启动时运行 `BOOT.md`(需要启用内部 hooks
列出可用的 hooks
```bash
openclaw hooks list
```
启用一个 hook
```bash
openclaw hooks enable session-memory
```
检查 hook 状态:
```bash
openclaw hooks check
```
获取详细信息:
```bash
openclaw hooks info session-memory
```
### 新手引导
在新手引导期间(`openclaw onboard`),你将被提示启用推荐的 hooks。向导会自动发现符合条件的 hooks 并呈现供选择。
## Hook 发现
Hooks 从三个目录自动发现(按优先级顺序):
1. **工作区 hooks**`<workspace>/hooks/`(每智能体,最高优先级)
2. **托管 hooks**`~/.openclaw/hooks/`(用户安装,跨工作区共享)
3. **捆绑 hooks**`<openclaw>/dist/hooks/bundled/`(随 OpenClaw 附带)
托管 hook 目录可以是**单个 hook** 或 **hook 包**(包目录)。
每个 hook 是一个包含以下内容的目录:
```
my-hook/
├── HOOK.md # 元数据 + 文档
└── handler.ts # 处理程序实现
```
## Hook 包npm/archives
Hook 包是标准的 npm 包,通过 `package.json` 中的 `openclaw.hooks` 导出一个或多个 hooks。使用以下命令安装
```bash
openclaw hooks install <path-or-spec>
```
示例 `package.json`
```json
{
"name": "@acme/my-hooks",
"version": "0.1.0",
"openclaw": {
"hooks": ["./hooks/my-hook", "./hooks/other-hook"]
}
}
```
每个条目指向包含 `HOOK.md``handler.ts`(或 `index.ts`)的 hook 目录。
Hook 包可以附带依赖;它们将安装在 `~/.openclaw/hooks/<id>` 下。
## Hook 结构
### HOOK.md 格式
`HOOK.md` 文件在 YAML frontmatter 中包含元数据,加上 Markdown 文档:
```markdown
---
name: my-hook
description: "Short description of what this hook does"
homepage: https://docs.openclaw.ai/automation/hooks#my-hook
metadata:
{ "openclaw": { "emoji": "🔗", "events": ["command:new"], "requires": { "bins": ["node"] } } }
---
# My Hook
Detailed documentation goes here...
## What It Does
- Listens for `/new` commands
- Performs some action
- Logs the result
## Requirements
- Node.js must be installed
## Configuration
No configuration needed.
```
### 元数据字段
`metadata.openclaw` 对象支持:
- **`emoji`**CLI 的显示表情符号(例如 `"💾"`
- **`events`**:要监听的事件数组(例如 `["command:new", "command:reset"]`
- **`export`**:要使用的命名导出(默认为 `"default"`
- **`homepage`**:文档 URL
- **`requires`**:可选要求
- **`bins`**PATH 中需要的二进制文件(例如 `["git", "node"]`
- **`anyBins`**:这些二进制文件中至少有一个必须存在
- **`env`**:需要的环境变量
- **`config`**:需要的配置路径(例如 `["workspace.dir"]`
- **`os`**:需要的平台(例如 `["darwin", "linux"]`
- **`always`**:绕过资格检查(布尔值)
- **`install`**:安装方法(对于捆绑 hooks`[{"id":"bundled","kind":"bundled"}]`
### 处理程序实现
`handler.ts` 文件导出一个 `HookHandler` 函数:
```typescript
import type { HookHandler } from "../../src/hooks/hooks.js";
const myHandler: HookHandler = async (event) => {
// Only trigger on 'new' command
if (event.type !== "command" || event.action !== "new") {
return;
}
console.log(`[my-hook] New command triggered`);
console.log(` Session: ${event.sessionKey}`);
console.log(` Timestamp: ${event.timestamp.toISOString()}`);
// Your custom logic here
// Optionally send message to user
event.messages.push("✨ My hook executed!");
};
export default myHandler;
```
#### 事件上下文
每个事件包含:
```typescript
{
type: 'command' | 'session' | 'agent' | 'gateway',
action: string, // e.g., 'new', 'reset', 'stop'
sessionKey: string, // Session identifier
timestamp: Date, // When the event occurred
messages: string[], // Push messages here to send to user
context: {
sessionEntry?: SessionEntry,
sessionId?: string,
sessionFile?: string,
commandSource?: string, // e.g., 'whatsapp', 'telegram'
senderId?: string,
workspaceDir?: string,
bootstrapFiles?: WorkspaceBootstrapFile[],
cfg?: OpenClawConfig
}
}
```
## 事件类型
### 命令事件
当发出智能体命令时触发:
- **`command`**:所有命令事件(通用监听器)
- **`command:new`**:当发出 `/new` 命令时
- **`command:reset`**:当发出 `/reset` 命令时
- **`command:stop`**:当发出 `/stop` 命令时
### 智能体事件
- **`agent:bootstrap`**在注入工作区引导文件之前hooks 可以修改 `context.bootstrapFiles`
### Gateway 网关事件
当 Gateway 网关启动时触发:
- **`gateway:startup`**:在渠道启动和 hooks 加载之后
### 工具结果 Hooks插件 API
这些 hooks 不是事件流监听器;它们让插件在 OpenClaw 持久化工具结果之前同步调整它们。
- **`tool_result_persist`**:在工具结果写入会话记录之前转换它们。必须是同步的;返回更新后的工具结果负载或 `undefined` 保持原样。参见 [智能体循环](/concepts/agent-loop)。
### 未来事件
计划中的事件类型:
- **`session:start`**:当新会话开始时
- **`session:end`**:当会话结束时
- **`agent:error`**:当智能体遇到错误时
- **`message:sent`**:当消息被发送时
- **`message:received`**:当消息被接收时
## 创建自定义 Hooks
### 1. 选择位置
- **工作区 hooks**`<workspace>/hooks/`):每智能体,最高优先级
- **托管 hooks**`~/.openclaw/hooks/`):跨工作区共享
### 2. 创建目录结构
```bash
mkdir -p ~/.openclaw/hooks/my-hook
cd ~/.openclaw/hooks/my-hook
```
### 3. 创建 HOOK.md
```markdown
---
name: my-hook
description: "Does something useful"
metadata: { "openclaw": { "emoji": "🎯", "events": ["command:new"] } }
---
# My Custom Hook
This hook does something useful when you issue `/new`.
```
### 4. 创建 handler.ts
```typescript
import type { HookHandler } from "../../src/hooks/hooks.js";
const handler: HookHandler = async (event) => {
if (event.type !== "command" || event.action !== "new") {
return;
}
console.log("[my-hook] Running!");
// Your logic here
};
export default handler;
```
### 5. 启用并测试
```bash
# Verify hook is discovered
openclaw hooks list
# Enable it
openclaw hooks enable my-hook
# Restart your gateway process (menu bar app restart on macOS, or restart your dev process)
# Trigger the event
# Send /new via your messaging channel
```
## 配置
### 新配置格式(推荐)
```json
{
"hooks": {
"internal": {
"enabled": true,
"entries": {
"session-memory": { "enabled": true },
"command-logger": { "enabled": false }
}
}
}
}
```
### 每 Hook 配置
Hooks 可以有自定义配置:
```json
{
"hooks": {
"internal": {
"enabled": true,
"entries": {
"my-hook": {
"enabled": true,
"env": {
"MY_CUSTOM_VAR": "value"
}
}
}
}
}
}
```
### 额外目录
从额外目录加载 hooks
```json
{
"hooks": {
"internal": {
"enabled": true,
"load": {
"extraDirs": ["/path/to/more/hooks"]
}
}
}
}
```
### 遗留配置格式(仍然支持)
旧配置格式仍然有效以保持向后兼容:
```json
{
"hooks": {
"internal": {
"enabled": true,
"handlers": [
{
"event": "command:new",
"module": "./hooks/handlers/my-handler.ts",
"export": "default"
}
]
}
}
}
```
**迁移**:对新 hooks 使用基于发现的新系统。遗留处理程序在基于目录的 hooks 之后加载。
## CLI 命令
### 列出 Hooks
```bash
# List all hooks
openclaw hooks list
# Show only eligible hooks
openclaw hooks list --eligible
# Verbose output (show missing requirements)
openclaw hooks list --verbose
# JSON output
openclaw hooks list --json
```
### Hook 信息
```bash
# Show detailed info about a hook
openclaw hooks info session-memory
# JSON output
openclaw hooks info session-memory --json
```
### 检查资格
```bash
# Show eligibility summary
openclaw hooks check
# JSON output
openclaw hooks check --json
```
### 启用/禁用
```bash
# Enable a hook
openclaw hooks enable session-memory
# Disable a hook
openclaw hooks disable command-logger
```
## 捆绑的 Hooks
### session-memory
当你发出 `/new` 时将会话上下文保存到记忆。
**事件**`command:new`
**要求**:必须配置 `workspace.dir`
**输出**`<workspace>/memory/YYYY-MM-DD-slug.md`(默认为 `~/.openclaw/workspace`
**功能**
1. 使用预重置会话条目定位正确的记录
2. 提取最后 15 行对话
3. 使用 LLM 生成描述性文件名 slug
4. 将会话元数据保存到带日期的记忆文件
**示例输出**
```markdown
# Session: 2026-01-16 14:30:00 UTC
- **Session Key**: agent:main:main
- **Session ID**: abc123def456
- **Source**: telegram
```
**文件名示例**
- `2026-01-16-vendor-pitch.md`
- `2026-01-16-api-design.md`
- `2026-01-16-1430.md`(如果 slug 生成失败则回退到时间戳)
**启用**
```bash
openclaw hooks enable session-memory
```
### command-logger
将所有命令事件记录到集中审计文件。
**事件**`command`
**要求**:无
**输出**`~/.openclaw/logs/commands.log`
**功能**
1. 捕获事件详情(命令操作、时间戳、会话键、发送者 ID、来源
2. 以 JSONL 格式追加到日志文件
3. 在后台静默运行
**示例日志条目**
```jsonl
{"timestamp":"2026-01-16T14:30:00.000Z","action":"new","sessionKey":"agent:main:main","senderId":"+1234567890","source":"telegram"}
{"timestamp":"2026-01-16T15:45:22.000Z","action":"stop","sessionKey":"agent:main:main","senderId":"user@example.com","source":"whatsapp"}
```
**查看日志**
```bash
# View recent commands
tail -n 20 ~/.openclaw/logs/commands.log
# Pretty-print with jq
cat ~/.openclaw/logs/commands.log | jq .
# Filter by action
grep '"action":"new"' ~/.openclaw/logs/commands.log | jq .
```
**启用**
```bash
openclaw hooks enable command-logger
```
### boot-md
当 Gateway 网关启动时运行 `BOOT.md`(在渠道启动之后)。
必须启用内部 hooks 才能运行。
**事件**`gateway:startup`
**要求**:必须配置 `workspace.dir`
**功能**
1. 从你的工作区读取 `BOOT.md`
2. 通过智能体运行器运行指令
3. 通过 message 工具发送任何请求的出站消息
**启用**
```bash
openclaw hooks enable boot-md
```
## 最佳实践
### 保持处理程序快速
Hooks 在命令处理期间运行。保持它们轻量:
```typescript
// ✓ Good - async work, returns immediately
const handler: HookHandler = async (event) => {
void processInBackground(event); // Fire and forget
};
// ✗ Bad - blocks command processing
const handler: HookHandler = async (event) => {
await slowDatabaseQuery(event);
await evenSlowerAPICall(event);
};
```
### 优雅处理错误
始终包装有风险的操作:
```typescript
const handler: HookHandler = async (event) => {
try {
await riskyOperation(event);
} catch (err) {
console.error("[my-handler] Failed:", err instanceof Error ? err.message : String(err));
// Don't throw - let other handlers run
}
};
```
### 尽早过滤事件
如果事件不相关则尽早返回:
```typescript
const handler: HookHandler = async (event) => {
// Only handle 'new' commands
if (event.type !== "command" || event.action !== "new") {
return;
}
// Your logic here
};
```
### 使用特定事件键
尽可能在元数据中指定确切事件:
```yaml
metadata: { "openclaw": { "events": ["command:new"] } } # Specific
```
而不是:
```yaml
metadata: { "openclaw": { "events": ["command"] } } # General - more overhead
```
## 调试
### 启用 Hook 日志
Gateway 网关在启动时记录 hook 加载:
```
Registered hook: session-memory -> command:new
Registered hook: command-logger -> command
Registered hook: boot-md -> gateway:startup
```
### 检查发现
列出所有发现的 hooks
```bash
openclaw hooks list --verbose
```
### 检查注册
在你的处理程序中,记录它被调用的时间:
```typescript
const handler: HookHandler = async (event) => {
console.log("[my-handler] Triggered:", event.type, event.action);
// Your logic
};
```
### 验证资格
检查为什么 hook 不符合条件:
```bash
openclaw hooks info my-hook
```
在输出中查找缺失的要求。
## 测试
### Gateway 网关日志
监控 Gateway 网关日志以查看 hook 执行:
```bash
# macOS
./scripts/clawlog.sh -f
# Other platforms
tail -f ~/.openclaw/gateway.log
```
### 直接测试 Hooks
隔离测试你的处理程序:
```typescript
import { test } from "vitest";
import { createHookEvent } from "./src/hooks/hooks.js";
import myHandler from "./hooks/my-hook/handler.js";
test("my handler works", async () => {
const event = createHookEvent("command", "new", "test-session", {
foo: "bar",
});
await myHandler(event);
// Assert side effects
});
```
## 架构
### 核心组件
- **`src/hooks/types.ts`**:类型定义
- **`src/hooks/workspace.ts`**:目录扫描和加载
- **`src/hooks/frontmatter.ts`**HOOK.md 元数据解析
- **`src/hooks/config.ts`**:资格检查
- **`src/hooks/hooks-status.ts`**:状态报告
- **`src/hooks/loader.ts`**:动态模块加载器
- **`src/cli/hooks-cli.ts`**CLI 命令
- **`src/gateway/server-startup.ts`**:在 Gateway 网关启动时加载 hooks
- **`src/auto-reply/reply/commands-core.ts`**:触发命令事件
### 发现流程
```
Gateway 网关启动
扫描目录(工作区 → 托管 → 捆绑)
解析 HOOK.md 文件
检查资格bins、env、config、os
从符合条件的 hooks 加载处理程序
为事件注册处理程序
```
### 事件流程
```
用户发送 /new
命令验证
创建 hook 事件
触发 hook所有注册的处理程序
命令处理继续
会话重置
```
## 故障排除
### Hook 未被发现
1. 检查目录结构:
```bash
ls -la ~/.openclaw/hooks/my-hook/
# Should show: HOOK.md, handler.ts
```
2. 验证 HOOK.md 格式:
```bash
cat ~/.openclaw/hooks/my-hook/HOOK.md
# Should have YAML frontmatter with name and metadata
```
3. 列出所有发现的 hooks
```bash
openclaw hooks list
```
### Hook 不符合条件
检查要求:
```bash
openclaw hooks info my-hook
```
查找缺失的:
- 二进制文件(检查 PATH
- 环境变量
- 配置值
- 操作系统兼容性
### Hook 未执行
1. 验证 hook 已启用:
```bash
openclaw hooks list
# Should show ✓ next to enabled hooks
```
2. 重启你的 Gateway 网关进程以重新加载 hooks。
3. 检查 Gateway 网关日志中的错误:
```bash
./scripts/clawlog.sh | grep hook
```
### 处理程序错误
检查 TypeScript/import 错误:
```bash
# Test import directly
node -e "import('./path/to/handler.ts').then(console.log)"
```
## 迁移指南
### 从遗留配置到发现
**之前**
```json
{
"hooks": {
"internal": {
"enabled": true,
"handlers": [
{
"event": "command:new",
"module": "./hooks/handlers/my-handler.ts"
}
]
}
}
}
```
**之后**
1. 创建 hook 目录:
```bash
mkdir -p ~/.openclaw/hooks/my-hook
mv ./hooks/handlers/my-handler.ts ~/.openclaw/hooks/my-hook/handler.ts
```
2. 创建 HOOK.md
```markdown
---
name: my-hook
description: "My custom hook"
metadata: { "openclaw": { "emoji": "🎯", "events": ["command:new"] } }
---
# My Hook
Does something useful.
```
3. 更新配置:
```json
{
"hooks": {
"internal": {
"enabled": true,
"entries": {
"my-hook": { "enabled": true }
}
}
}
}
```
4. 验证并重启你的 Gateway 网关进程:
```bash
openclaw hooks list
# Should show: 🎯 my-hook ✓
```
**迁移的好处**
- 自动发现
- CLI 管理
- 资格检查
- 更好的文档
- 一致的结构
## 另请参阅
- [CLI 参考hooks](/cli/hooks)
- [捆绑 Hooks README](https://github.com/openclaw/openclaw/tree/main/src/hooks/bundled)
- [Webhook Hooks](/automation/webhook)
- [配置](/gateway/configuration#hooks)

View File

@@ -0,0 +1,76 @@
---
read_when:
- 添加或修改投票支持
- 调试从 CLI 或 Gateway 网关发送的投票
summary: 通过 Gateway 网关 + CLI 发送投票
title: 投票
x-i18n:
generated_at: "2026-02-03T07:43:12Z"
model: claude-opus-4-5
provider: pi
source_hash: 760339865d27ec40def7996cac1d294d58ab580748ad6b32cc34d285d0314eaf
source_path: automation/poll.md
workflow: 15
---
# 投票
## 支持的渠道
- WhatsAppWeb 渠道)
- Discord
- MS TeamsAdaptive Cards
## CLI
```bash
# WhatsApp
openclaw message poll --target +15555550123 \
--poll-question "Lunch today?" --poll-option "Yes" --poll-option "No" --poll-option "Maybe"
openclaw message poll --target 123456789@g.us \
--poll-question "Meeting time?" --poll-option "10am" --poll-option "2pm" --poll-option "4pm" --poll-multi
# Discord
openclaw message poll --channel discord --target channel:123456789 \
--poll-question "Snack?" --poll-option "Pizza" --poll-option "Sushi"
openclaw message poll --channel discord --target channel:123456789 \
--poll-question "Plan?" --poll-option "A" --poll-option "B" --poll-duration-hours 48
# MS Teams
openclaw message poll --channel msteams --target conversation:19:abc@thread.tacv2 \
--poll-question "Lunch?" --poll-option "Pizza" --poll-option "Sushi"
```
选项:
- `--channel``whatsapp`(默认)、`discord``msteams`
- `--poll-multi`:允许选择多个选项
- `--poll-duration-hours`:仅限 Discord省略时默认为 24
## Gateway 网关 RPC
方法:`poll`
参数:
- `to`(字符串,必需)
- `question`(字符串,必需)
- `options`(字符串数组,必需)
- `maxSelections`(数字,可选)
- `durationHours`(数字,可选)
- `channel`(字符串,可选,默认:`whatsapp`
- `idempotencyKey`(字符串,必需)
## 渠道差异
- WhatsApp2-12 个选项,`maxSelections` 必须在选项数量范围内,忽略 `durationHours`
- Discord2-10 个选项,`durationHours` 限制在 1-768 小时之间(默认 24`maxSelections > 1` 启用多选Discord 不支持严格的选择数量限制。
- MS TeamsAdaptive Card 投票(由 OpenClaw 管理)。无原生投票 API`durationHours` 被忽略。
## 智能体工具Message
使用 `message` 工具的 `poll` 操作(`to``pollQuestion``pollOption`,可选 `pollMulti``pollDurationHours``channel`)。
注意Discord 没有"恰好选择 N 个"模式;`pollMulti` 映射为多选。
Teams 投票以 Adaptive Cards 形式渲染,需要 Gateway 网关保持在线
以将投票记录到 `~/.openclaw/msteams-polls.json`

View File

@@ -0,0 +1,8 @@
---
summary: 自动化故障排查:排查 cron 和 heartbeat 调度与投递问题
title: 自动化故障排查
---
# 自动化故障排查
该页面是英文文档的中文占位版本,完整内容请先参考英文版:[Automation Troubleshooting](/automation/troubleshooting)。

View File

@@ -0,0 +1,163 @@
---
read_when:
- 添加或更改 webhook 端点
- 将外部系统接入 OpenClaw
summary: 用于唤醒和隔离智能体运行的 Webhook 入口
title: Webhooks
x-i18n:
generated_at: "2026-02-03T07:43:23Z"
model: claude-opus-4-5
provider: pi
source_hash: f26b88864567be82366b1f66a4772ef2813c7846110c62fce6caf7313568265e
source_path: automation/webhook.md
workflow: 15
---
# Webhooks
Gateway 网关可以暴露一个小型 HTTP webhook 端点用于外部触发。
## 启用
```json5
{
hooks: {
enabled: true,
token: "shared-secret",
path: "/hooks",
},
}
```
注意事项:
-`hooks.enabled=true` 时,`hooks.token` 为必填项。
- `hooks.path` 默认为 `/hooks`
## 认证
每个请求必须包含 hook 令牌。推荐使用请求头:
- `Authorization: Bearer <token>`(推荐)
- `x-openclaw-token: <token>`
- `?token=<token>`(已弃用;会记录警告日志,将在未来的主要版本中移除)
## 端点
### `POST /hooks/wake`
请求体:
```json
{ "text": "System line", "mode": "now" }
```
- `text` **必填**(字符串):事件描述(例如"收到新邮件")。
- `mode` 可选(`now` | `next-heartbeat`):是否立即触发心跳(默认 `now`)或等待下一次定期检查。
效果:
- 为**主**会话加入一个系统事件队列
- 如果 `mode=now`,则立即触发心跳
### `POST /hooks/agent`
请求体:
```json
{
"message": "Run this",
"name": "Email",
"sessionKey": "hook:email:msg-123",
"wakeMode": "now",
"deliver": true,
"channel": "last",
"to": "+15551234567",
"model": "openai/gpt-5.2-mini",
"thinking": "low",
"timeoutSeconds": 120
}
```
- `message` **必填**(字符串):智能体要处理的提示或消息。
- `name` 可选字符串hook 的可读名称(例如"GitHub"),用作会话摘要的前缀。
- `sessionKey` 可选(字符串):用于标识智能体会话的键。默认为随机的 `hook:<uuid>`。使用一致的键可以在 hook 上下文中进行多轮对话。
- `wakeMode` 可选(`now` | `next-heartbeat`):是否立即触发心跳(默认 `now`)或等待下一次定期检查。
- `deliver` 可选(布尔值):如果为 `true`,智能体的响应将发送到消息渠道。默认为 `true`。仅为心跳确认的响应会自动跳过。
- `channel` 可选(字符串):用于投递的消息渠道。可选值:`last``whatsapp``telegram``discord``slack``mattermost`(插件)、`signal``imessage``msteams`。默认为 `last`
- `to` 可选(字符串):渠道的接收者标识符(例如 WhatsApp/Signal 的电话号码、Telegram 的聊天 ID、Discord/Slack/Mattermost插件的频道 ID、MS Teams 的会话 ID。默认为主会话中的最后一个接收者。
- `model` 可选(字符串):模型覆盖(例如 `anthropic/claude-3-5-sonnet` 或别名)。如果有限制,必须在允许的模型列表中。
- `thinking` 可选(字符串):思考级别覆盖(例如 `low``medium``high`)。
- `timeoutSeconds` 可选(数字):智能体运行的最大持续时间(秒)。
效果:
- 运行一个**隔离的**智能体回合(独立的会话键)
- 始终在**主**会话中发布摘要
- 如果 `wakeMode=now`,则立即触发心跳
### `POST /hooks/<name>`(映射)
自定义 hook 名称通过 `hooks.mappings` 解析(见配置)。映射可以将任意请求体转换为 `wake``agent` 操作,支持可选的模板或代码转换。
映射选项(摘要):
- `hooks.presets: ["gmail"]` 启用内置的 Gmail 映射。
- `hooks.mappings` 允许你在配置中定义 `match``action` 和模板。
- `hooks.transformsDir` + `transform.module` 加载 JS/TS 模块用于自定义逻辑。
- 使用 `match.source` 保持通用的接收端点(基于请求体的路由)。
- TS 转换需要 TS 加载器(例如 `bun``tsx`)或运行时预编译的 `.js`
- 在映射上设置 `deliver: true` + `channel`/`to` 可将回复路由到聊天界面(`channel` 默认为 `last`,回退到 WhatsApp
- `allowUnsafeExternalContent: true` 禁用该 hook 的外部内容安全包装(危险;仅用于受信任的内部来源)。
- `openclaw webhooks gmail setup``openclaw webhooks gmail run` 写入 `hooks.gmail` 配置。完整的 Gmail 监听流程请参阅 [Gmail Pub/Sub](/automation/gmail-pubsub)。
## 响应
- `200` 用于 `/hooks/wake`
- `202` 用于 `/hooks/agent`(异步运行已启动)
- `401` 认证失败
- `400` 请求体无效
- `413` 请求体过大
## 示例
```bash
curl -X POST http://127.0.0.1:18789/hooks/wake \
-H 'Authorization: Bearer SECRET' \
-H 'Content-Type: application/json' \
-d '{"text":"New email received","mode":"now"}'
```
```bash
curl -X POST http://127.0.0.1:18789/hooks/agent \
-H 'x-openclaw-token: SECRET' \
-H 'Content-Type: application/json' \
-d '{"message":"Summarize inbox","name":"Email","wakeMode":"next-heartbeat"}'
```
### 使用不同的模型
在智能体请求体(或映射)中添加 `model` 以覆盖该次运行的模型:
```bash
curl -X POST http://127.0.0.1:18789/hooks/agent \
-H 'x-openclaw-token: SECRET' \
-H 'Content-Type: application/json' \
-d '{"message":"Summarize inbox","name":"Email","model":"openai/gpt-5.2-mini"}'
```
如果你启用了 `agents.defaults.models` 限制,请确保覆盖的模型包含在其中。
```bash
curl -X POST http://127.0.0.1:18789/hooks/gmail \
-H 'Authorization: Bearer SECRET' \
-H 'Content-Type: application/json' \
-d '{"source":"gmail","messages":[{"from":"Ada","subject":"Hello","snippet":"Hi"}]}'
```
## 安全
- 将 hook 端点保持在 loopback、tailnet 或受信任的反向代理之后。
- 使用专用的 hook 令牌;不要复用 Gateway 网关认证令牌。
- 避免在 webhook 日志中包含敏感的原始请求体。
- Hook 请求体默认被视为不受信任并使用安全边界包装。如果你必须为特定 hook 禁用此功能,请在该 hook 的映射中设置 `allowUnsafeExternalContent: true`(危险)。