重构主控编排与运行时预热链路,统一工作区提示词/专家调度协议并补齐 wiki 记忆注入与写回闭环。

同时收敛启动与运维脚本默认行为(含 wiki worker)、更新 Admin 可观测性与相关测试,降低首轮时延并提高运行稳定性。

Made-with: Cursor
This commit is contained in:
oliver 2026-04-26 08:34:33 +08:00
parent 4a23b715a2
commit dbbe3add6a
14438 changed files with 2693620 additions and 2546 deletions

View file

@ -0,0 +1,8 @@
---
summary: "Redirect to /gateway/authentication"
title: "Auth Monitoring"
---
# Auth Monitoring
This page moved to [Authentication](/gateway/authentication). See [Authentication](/gateway/authentication) for auth monitoring documentation.

View file

@ -0,0 +1,8 @@
---
summary: "Redirect to Task Flow"
title: "ClawFlow"
---
# ClawFlow
ClawFlow was renamed to [Task Flow](/automation/taskflow). See [Task Flow](/automation/taskflow) for the current documentation.

View file

@ -0,0 +1,424 @@
---
summary: "Scheduled jobs, webhooks, and Gmail PubSub triggers for the Gateway scheduler"
read_when:
- Scheduling background jobs or wakeups
- Wiring external triggers (webhooks, Gmail) into OpenClaw
- Deciding between heartbeat and cron for scheduled tasks
title: "Scheduled Tasks"
---
# Scheduled Tasks (Cron)
Cron is the Gateway's built-in scheduler. It persists jobs, wakes the agent at the right time, and can deliver output back to a chat channel or webhook endpoint.
## Quick start
```bash
# Add a one-shot reminder
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
# Check your jobs
openclaw cron list
# See run history
openclaw cron runs --id <job-id>
```
## How cron works
- Cron runs **inside the Gateway** process (not inside the model).
- Jobs persist at `~/.openclaw/cron/jobs.json` so restarts do not lose schedules.
- All cron executions create [background task](/automation/tasks) records.
- One-shot jobs (`--at`) auto-delete after success by default.
- Isolated cron runs best-effort close tracked browser tabs/processes for their `cron:<jobId>` session when the run completes, so detached browser automation does not leave orphaned processes behind.
- Isolated cron runs also guard against stale acknowledgement replies. If the
first result is just an interim status update (`on it`, `pulling everything
together`, and similar hints) and no descendant subagent run is still
responsible for the final answer, OpenClaw re-prompts once for the actual
result before delivery.
<a id="maintenance"></a>
Task reconciliation for cron is runtime-owned: an active cron task stays live while the
cron runtime still tracks that job as running, even if an old child session row still exists.
Once the runtime stops owning the job and the 5-minute grace window expires, maintenance can
mark the task `lost`.
## Schedule types
| Kind | CLI flag | Description |
| ------- | --------- | ------------------------------------------------------- |
| `at` | `--at` | One-shot timestamp (ISO 8601 or relative like `20m`) |
| `every` | `--every` | Fixed interval |
| `cron` | `--cron` | 5-field or 6-field cron expression with optional `--tz` |
Timestamps without a timezone are treated as UTC. Add `--tz America/New_York` for local wall-clock scheduling.
Recurring top-of-hour expressions are automatically staggered by up to 5 minutes to reduce load spikes. Use `--exact` to force precise timing or `--stagger 30s` for an explicit window.
### Day-of-month and day-of-week use OR logic
Cron expressions are parsed by [croner](https://github.com/Hexagon/croner). When both the day-of-month and day-of-week fields are non-wildcard, croner matches when **either** field matches — not both. This is standard Vixie cron behavior.
```
# Intended: "9 AM on the 15th, only if it's a Monday"
# Actual: "9 AM on every 15th, AND 9 AM on every Monday"
0 9 15 * 1
```
This fires ~5–6 times per month instead of 0–1 times per month. OpenClaw uses Croner's default OR behavior here. To require both conditions, use Croner's `+` day-of-week modifier (`0 9 15 * +1`) or schedule on one field and guard the other in your job's prompt or command.
## Execution styles
| Style | `--session` value | Runs in | Best for |
| --------------- | ------------------- | ------------------------ | ------------------------------- |
| Main session | `main` | Next heartbeat turn | Reminders, system events |
| Isolated | `isolated` | Dedicated `cron:<jobId>` | Reports, background chores |
| Current session | `current` | Bound at creation time | Context-aware recurring work |
| Custom session | `session:custom-id` | Persistent named session | Workflows that build on history |
**Main session** jobs enqueue a system event and optionally wake the heartbeat (`--wake now` or `--wake next-heartbeat`). **Isolated** jobs run a dedicated agent turn with a fresh session. **Custom sessions** (`session:xxx`) persist context across runs, enabling workflows like daily standups that build on previous summaries.
For isolated jobs, runtime teardown now includes best-effort browser cleanup for that cron session. Cleanup failures are ignored so the actual cron result still wins.
When isolated cron runs orchestrate subagents, delivery also prefers the final
descendant output over stale parent interim text. If descendants are still
running, OpenClaw suppresses that partial parent update instead of announcing it.
### Payload options for isolated jobs
- `--message`: prompt text (required for isolated)
- `--model` / `--thinking`: model and thinking level overrides
- `--light-context`: skip workspace bootstrap file injection
- `--tools exec,read`: restrict which tools the job can use
`--model` uses the selected allowed model for that job. If the requested model
is not allowed, cron logs a warning and falls back to the job's agent/default
model selection instead. Configured fallback chains still apply, but a plain
model override with no explicit per-job fallback list no longer appends the
agent primary as a hidden extra retry target.
Model-selection precedence for isolated jobs is:
1. Gmail hook model override (when the run came from Gmail and that override is allowed)
2. Per-job payload `model`
3. Stored cron session model override
4. Agent/default model selection
Fast mode follows the resolved live selection too. If the selected model config
has `params.fastMode`, isolated cron uses that by default. A stored session
`fastMode` override still wins over config in either direction.
If an isolated run hits a live model-switch handoff, cron retries with the
switched provider/model and persists that live selection before retrying. When
the switch also carries a new auth profile, cron persists that auth profile
override too. Retries are bounded: after the initial attempt plus 2 switch
retries, cron aborts instead of looping forever.
## Delivery and output
| Mode | What happens |
| ---------- | -------------------------------------------------------- |
| `announce` | Deliver summary to target channel (default for isolated) |
| `webhook` | POST finished event payload to a URL |
| `none` | Internal only, no delivery |
Use `--announce --channel telegram --to "-1001234567890"` for channel delivery. For Telegram forum topics, use `-1001234567890:topic:123`. Slack/Discord/Mattermost targets should use explicit prefixes (`channel:<id>`, `user:<id>`).
For cron-owned isolated jobs, the runner owns the final delivery path. The
agent is prompted to return a plain-text summary, and that summary is then sent
through `announce`, `webhook`, or kept internal for `none`. `--no-deliver`
does not hand delivery back to the agent; it keeps the run internal.
If the original task explicitly says to message some external recipient, the
agent should note who/where that message should go in its output instead of
trying to send it directly.
Failure notifications follow a separate destination path:
- `cron.failureDestination` sets a global default for failure notifications.
- `job.delivery.failureDestination` overrides that per job.
- If neither is set and the job already delivers via `announce`, failure notifications now fall back to that primary announce target.
- `delivery.failureDestination` is only supported on `sessionTarget="isolated"` jobs unless the primary delivery mode is `webhook`.
## CLI examples
One-shot reminder (main session):
```bash
openclaw cron add \
--name "Calendar check" \
--at "20m" \
--session main \
--system-event "Next heartbeat: check calendar." \
--wake now
```
Recurring isolated job with delivery:
```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"
```
Isolated job with model and thinking override:
```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
```
## Webhooks
Gateway can expose HTTP webhook endpoints for external triggers. Enable in config:
```json5
{
hooks: {
enabled: true,
token: "shared-secret",
path: "/hooks",
},
}
```
### Authentication
Every request must include the hook token via header:
- `Authorization: Bearer <token>` (recommended)
- `x-openclaw-token: <token>`
Query-string tokens are rejected.
### POST /hooks/wake
Enqueue a system event for the main session:
```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"}'
```
- `text` (required): event description
- `mode` (optional): `now` (default) or `next-heartbeat`
### POST /hooks/agent
Run an isolated agent turn:
```bash
curl -X POST http://127.0.0.1:18789/hooks/agent \
-H 'Authorization: Bearer SECRET' \
-H 'Content-Type: application/json' \
-d '{"message":"Summarize inbox","name":"Email","model":"openai/gpt-5.4-mini"}'
```
Fields: `message` (required), `name`, `agentId`, `wakeMode`, `deliver`, `channel`, `to`, `model`, `thinking`, `timeoutSeconds`.
### Mapped hooks (POST /hooks/\<name\>)
Custom hook names are resolved via `hooks.mappings` in config. Mappings can transform arbitrary payloads into `wake` or `agent` actions with templates or code transforms.
### Security
- Keep hook endpoints behind loopback, tailnet, or trusted reverse proxy.
- Use a dedicated hook token; do not reuse gateway auth tokens.
- Keep `hooks.path` on a dedicated subpath; `/` is rejected.
- Set `hooks.allowedAgentIds` to limit explicit `agentId` routing.
- Keep `hooks.allowRequestSessionKey=false` unless you require caller-selected sessions.
- If you enable `hooks.allowRequestSessionKey`, also set `hooks.allowedSessionKeyPrefixes` to constrain allowed session key shapes.
- Hook payloads are wrapped with safety boundaries by default.
## Gmail PubSub integration
Wire Gmail inbox triggers to OpenClaw via Google PubSub.
**Prerequisites**: `gcloud` CLI, `gog` (gogcli), OpenClaw hooks enabled, Tailscale for the public HTTPS endpoint.
### Wizard setup (recommended)
```bash
openclaw webhooks gmail setup --account openclaw@gmail.com
```
This writes `hooks.gmail` config, enables the Gmail preset, and uses Tailscale Funnel for the push endpoint.
### Gateway auto-start
When `hooks.enabled=true` and `hooks.gmail.account` is set, the Gateway starts `gog gmail watch serve` on boot and auto-renews the watch. Set `OPENCLAW_SKIP_GMAIL_WATCHER=1` to opt out.
### Manual one-time setup
1. Select the GCP project that owns the OAuth client used by `gog`:
```bash
gcloud auth login
gcloud config set project <project-id>
gcloud services enable gmail.googleapis.com pubsub.googleapis.com
```
2. Create topic and grant Gmail push access:
```bash
gcloud pubsub topics create gog-gmail-watch
gcloud pubsub topics add-iam-policy-binding gog-gmail-watch \
--member=serviceAccount:gmail-api-push@system.gserviceaccount.com \
--role=roles/pubsub.publisher
```
3. Start the watch:
```bash
gog gmail watch start \
--account openclaw@gmail.com \
--label INBOX \
--topic projects/<project-id>/topics/gog-gmail-watch
```
### Gmail model override
```json5
{
hooks: {
gmail: {
model: "openrouter/meta-llama/llama-3.3-70b-instruct:free",
thinking: "off",
},
},
}
```
## Managing jobs
```bash
# List all jobs
openclaw cron list
# Edit a job
openclaw cron edit <jobId> --message "Updated prompt" --model "opus"
# Force run a job now
openclaw cron run <jobId>
# Run only if due
openclaw cron run <jobId> --due
# View run history
openclaw cron runs --id <jobId> --limit 50
# Delete a job
openclaw cron remove <jobId>
# Agent selection (multi-agent setups)
openclaw cron add --name "Ops sweep" --cron "0 6 * * *" --session isolated --message "Check ops queue" --agent ops
openclaw cron edit <jobId> --clear-agent
```
Model override note:
- `openclaw cron add|edit --model ...` changes the job's selected model.
- If the model is allowed, that exact provider/model reaches the isolated agent
run.
- If it is not allowed, cron warns and falls back to the job's agent/default
model selection.
- Configured fallback chains still apply, but a plain `--model` override with
no explicit per-job fallback list no longer falls through to the agent
primary as a silent extra retry target.
## Configuration
```json5
{
cron: {
enabled: true,
store: "~/.openclaw/cron/jobs.json",
maxConcurrentRuns: 1,
retry: {
maxAttempts: 3,
backoffMs: [60000, 120000, 300000],
retryOn: ["rate_limit", "overloaded", "network", "server_error"],
},
webhookToken: "replace-with-dedicated-webhook-token",
sessionRetention: "24h",
runLog: { maxBytes: "2mb", keepLines: 2000 },
},
}
```
Disable cron: `cron.enabled: false` or `OPENCLAW_SKIP_CRON=1`.
**One-shot retry**: transient errors (rate limit, overload, network, server error) retry up to 3 times with exponential backoff. Permanent errors disable immediately.
**Recurring retry**: exponential backoff (30s to 60m) between retries. Backoff resets after the next successful run.
**Maintenance**: `cron.sessionRetention` (default `24h`) prunes isolated run-session entries. `cron.runLog.maxBytes` / `cron.runLog.keepLines` auto-prune run-log files.
## Troubleshooting
### Command ladder
```bash
openclaw status
openclaw gateway status
openclaw cron status
openclaw cron list
openclaw cron runs --id <jobId> --limit 20
openclaw system heartbeat last
openclaw logs --follow
openclaw doctor
```
### Cron not firing
- Check `cron.enabled` and `OPENCLAW_SKIP_CRON` env var.
- Confirm the Gateway is running continuously.
- For `cron` schedules, verify timezone (`--tz`) vs the host timezone.
- `reason: not-due` in run output means manual run was checked with `openclaw cron run <jobId> --due` and the job was not due yet.
### Cron fired but no delivery
- Delivery mode is `none` means no external message is expected.
- Delivery target missing/invalid (`channel`/`to`) means outbound was skipped.
- Channel auth errors (`unauthorized`, `Forbidden`) mean delivery was blocked by credentials.
- If the isolated run returns only the silent token (`NO_REPLY` / `no_reply`),
OpenClaw suppresses direct outbound delivery and also suppresses the fallback
queued summary path, so nothing is posted back to chat.
- For cron-owned isolated jobs, do not expect the agent to use the message tool
as a fallback. The runner owns final delivery; `--no-deliver` keeps it
internal instead of allowing a direct send.
### Timezone gotchas
- Cron without `--tz` uses the gateway host timezone.
- `at` schedules without timezone are treated as UTC.
- Heartbeat `activeHours` uses configured timezone resolution.
## Related
- [Automation & Tasks](/automation) — all automation mechanisms at a glance
- [Background Tasks](/automation/tasks) — task ledger for cron executions
- [Heartbeat](/gateway/heartbeat) — periodic main-session turns
- [Timezone](/concepts/timezone) — timezone configuration

View file

@ -0,0 +1,8 @@
---
summary: "Redirect to /automation"
title: "Cron vs Heartbeat"
---
# Cron vs Heartbeat
This page moved to [Automation & Tasks](/automation). See [Automation & Tasks](/automation) for the decision guide comparing cron and heartbeat.

View file

@ -0,0 +1,8 @@
---
summary: "Redirect to /automation/cron-jobs"
title: "Gmail PubSub"
---
# Gmail PubSub
This page moved to [Scheduled Tasks](/automation/cron-jobs#gmail-pubsub-integration). See [Scheduled Tasks](/automation/cron-jobs#gmail-pubsub-integration) for Gmail PubSub documentation.

View file

@ -0,0 +1,319 @@
---
summary: "Hooks: event-driven automation for commands and lifecycle events"
read_when:
- You want event-driven automation for /new, /reset, /stop, and agent lifecycle events
- You want to build, install, or debug hooks
title: "Hooks"
---
# Hooks
Hooks are small scripts that run when something happens inside the Gateway. They are automatically discovered from directories and can be inspected with `openclaw hooks`.
There are two kinds of hooks in OpenClaw:
- **Internal hooks** (this page): run inside the Gateway when agent events fire, like `/new`, `/reset`, `/stop`, or lifecycle events.
- **Webhooks**: external HTTP endpoints that let other systems trigger work in OpenClaw. See [Webhooks](/automation/cron-jobs#webhooks).
Hooks can also be bundled inside plugins. `openclaw hooks list` shows both standalone hooks and plugin-managed hooks.
## Quick start
```bash
# List available hooks
openclaw hooks list
# Enable a hook
openclaw hooks enable session-memory
# Check hook status
openclaw hooks check
# Get detailed information
openclaw hooks info session-memory
```
## Event types
| Event | When it fires |
| ------------------------ | ------------------------------------------------ |
| `command:new` | `/new` command issued |
| `command:reset` | `/reset` command issued |
| `command:stop` | `/stop` command issued |
| `command` | Any command event (general listener) |
| `session:compact:before` | Before compaction summarizes history |
| `session:compact:after` | After compaction completes |
| `session:patch` | When session properties are modified |
| `agent:bootstrap` | Before workspace bootstrap files are injected |
| `gateway:startup` | After channels start and hooks are loaded |
| `message:received` | Inbound message from any channel |
| `message:transcribed` | After audio transcription completes |
| `message:preprocessed` | After all media and link understanding completes |
| `message:sent` | Outbound message delivered |
## Writing hooks
### Hook structure
Each hook is a directory containing two files:
```
my-hook/
├── HOOK.md # Metadata + documentation
└── handler.ts # Handler implementation
```
### HOOK.md format
```markdown
---
name: my-hook
description: "Short description of what this hook does"
metadata:
{ "openclaw": { "emoji": "🔗", "events": ["command:new"], "requires": { "bins": ["node"] } } }
---
# My Hook
Detailed documentation goes here.
```
**Metadata fields** (`metadata.openclaw`):
| Field | Description |
| ---------- | ---------------------------------------------------- |
| `emoji` | Display emoji for CLI |
| `events` | Array of events to listen for |
| `export` | Named export to use (defaults to `"default"`) |
| `os` | Required platforms (e.g., `["darwin", "linux"]`) |
| `requires` | Required `bins`, `anyBins`, `env`, or `config` paths |
| `always` | Bypass eligibility checks (boolean) |
| `install` | Installation methods |
### Handler implementation
```typescript
const handler = async (event) => {
if (event.type !== "command" || event.action !== "new") {
return;
}
console.log(`[my-hook] New command triggered`);
// Your logic here
// Optionally send message to user
event.messages.push("Hook executed!");
};
export default handler;
```
Each event includes: `type`, `action`, `sessionKey`, `timestamp`, `messages` (push to send to user), and `context` (event-specific data).
### Event context highlights
**Command events** (`command:new`, `command:reset`): `context.sessionEntry`, `context.previousSessionEntry`, `context.commandSource`, `context.workspaceDir`, `context.cfg`.
**Message events** (`message:received`): `context.from`, `context.content`, `context.channelId`, `context.metadata` (provider-specific data including `senderId`, `senderName`, `guildId`).
**Message events** (`message:sent`): `context.to`, `context.content`, `context.success`, `context.channelId`.
**Message events** (`message:transcribed`): `context.transcript`, `context.from`, `context.channelId`, `context.mediaPath`.
**Message events** (`message:preprocessed`): `context.bodyForAgent` (final enriched body), `context.from`, `context.channelId`.
**Bootstrap events** (`agent:bootstrap`): `context.bootstrapFiles` (mutable array), `context.agentId`.
**Session patch events** (`session:patch`): `context.sessionEntry`, `context.patch` (only changed fields), `context.cfg`. Only privileged clients can trigger patch events.
**Compaction events**: `session:compact:before` includes `messageCount`, `tokenCount`. `session:compact:after` adds `compactedCount`, `summaryLength`, `tokensBefore`, `tokensAfter`.
## Hook discovery
Hooks are discovered from these directories, in order of increasing override precedence:
1. **Bundled hooks**: shipped with OpenClaw
2. **Plugin hooks**: hooks bundled inside installed plugins
3. **Managed hooks**: `~/.openclaw/hooks/` (user-installed, shared across workspaces). Extra directories from `hooks.internal.load.extraDirs` share this precedence.
4. **Workspace hooks**: `<workspace>/hooks/` (per-agent, disabled by default until explicitly enabled)
Workspace hooks can add new hook names but cannot override bundled, managed, or plugin-provided hooks with the same name.
### Hook packs
Hook packs are npm packages that export hooks via `openclaw.hooks` in `package.json`. Install with:
```bash
openclaw plugins install <path-or-spec>
```
Npm specs are registry-only (package name + optional exact version or dist-tag). Git/URL/file specs and semver ranges are rejected.
## Bundled hooks
| Hook | Events | What it does |
| --------------------- | ------------------------------ | ----------------------------------------------------- |
| session-memory | `command:new`, `command:reset` | Saves session context to `<workspace>/memory/` |
| bootstrap-extra-files | `agent:bootstrap` | Injects additional bootstrap files from glob patterns |
| command-logger | `command` | Logs all commands to `~/.openclaw/logs/commands.log` |
| boot-md | `gateway:startup` | Runs `BOOT.md` when the gateway starts |
Enable any bundled hook:
```bash
openclaw hooks enable <hook-name>
```
<a id="session-memory"></a>
### session-memory details
Extracts the last 15 user/assistant messages, generates a descriptive filename slug via LLM, and saves to `<workspace>/memory/YYYY-MM-DD-slug.md`. Requires `workspace.dir` to be configured.
<a id="bootstrap-extra-files"></a>
### bootstrap-extra-files config
```json
{
"hooks": {
"internal": {
"entries": {
"bootstrap-extra-files": {
"enabled": true,
"paths": ["packages/*/AGENTS.md", "packages/*/TOOLS.md"]
}
}
}
}
}
```
Paths resolve relative to workspace. Only recognized bootstrap basenames are loaded (`AGENTS.md`, `SOUL.md`, `TOOLS.md`, `IDENTITY.md`, `USER.md`, `HEARTBEAT.md`, `BOOTSTRAP.md`, `MEMORY.md`).
<a id="command-logger"></a>
### command-logger details
Logs every slash command to `~/.openclaw/logs/commands.log`.
<a id="boot-md"></a>
### boot-md details
Runs `BOOT.md` from the active workspace when the gateway starts.
## Plugin hooks
Plugins can register hooks through the Plugin SDK for deeper integration: intercepting tool calls, modifying prompts, controlling message flow, and more. The Plugin SDK exposes 28 hooks covering model resolution, agent lifecycle, message flow, tool execution, subagent coordination, and gateway lifecycle.
For the complete plugin hook reference including `before_tool_call`, `before_agent_reply`, `before_install`, and all other plugin hooks, see [Plugin Architecture](/plugins/architecture#provider-runtime-hooks).
## Configuration
```json
{
"hooks": {
"internal": {
"enabled": true,
"entries": {
"session-memory": { "enabled": true },
"command-logger": { "enabled": false }
}
}
}
}
```
Per-hook environment variables:
```json
{
"hooks": {
"internal": {
"entries": {
"my-hook": {
"enabled": true,
"env": { "MY_CUSTOM_VAR": "value" }
}
}
}
}
}
```
Extra hook directories:
```json
{
"hooks": {
"internal": {
"load": {
"extraDirs": ["/path/to/more/hooks"]
}
}
}
}
```
<Note>
The legacy `hooks.internal.handlers` array config format is still supported for backwards compatibility, but new hooks should use the discovery-based system.
</Note>
## CLI reference
```bash
# List all hooks (add --eligible, --verbose, or --json)
openclaw hooks list
# Show detailed info about a hook
openclaw hooks info <hook-name>
# Show eligibility summary
openclaw hooks check
# Enable/disable
openclaw hooks enable <hook-name>
openclaw hooks disable <hook-name>
```
## Best practices
- **Keep handlers fast.** Hooks run during command processing. Fire-and-forget heavy work with `void processInBackground(event)`.
- **Handle errors gracefully.** Wrap risky operations in try/catch; do not throw so other handlers can run.
- **Filter events early.** Return immediately if the event type/action is not relevant.
- **Use specific event keys.** Prefer `"events": ["command:new"]` over `"events": ["command"]` to reduce overhead.
## Troubleshooting
### Hook not discovered
```bash
# Verify directory structure
ls -la ~/.openclaw/hooks/my-hook/
# Should show: HOOK.md, handler.ts
# List all discovered hooks
openclaw hooks list
```
### Hook not eligible
```bash
openclaw hooks info my-hook
```
Check for missing binaries (PATH), environment variables, config values, or OS compatibility.
### Hook not executing
1. Verify the hook is enabled: `openclaw hooks list`
2. Restart your gateway process so hooks reload.
3. Check gateway logs: `./scripts/clawlog.sh | grep hook`
## Related
- [CLI Reference: hooks](/cli/hooks)
- [Webhooks](/automation/cron-jobs#webhooks)
- [Plugin Architecture](/plugins/architecture#provider-runtime-hooks) — full plugin hook reference
- [Configuration](/gateway/configuration-reference#hooks)

View file

@ -0,0 +1,115 @@
---
summary: "Overview of automation mechanisms: tasks, cron, hooks, standing orders, and Task Flow"
read_when:
- Deciding how to automate work with OpenClaw
- Choosing between heartbeat, cron, hooks, and standing orders
- Looking for the right automation entry point
title: "Automation & Tasks"
---
# Automation & Tasks
OpenClaw runs work in the background through tasks, scheduled jobs, event hooks, and standing instructions. This page helps you choose the right mechanism and understand how they fit together.
## Quick decision guide
```mermaid
flowchart TD
START([What do you need?]) --> Q1{Schedule work?}
START --> Q2{Track detached work?}
START --> Q3{Orchestrate multi-step flows?}
START --> Q4{React to lifecycle events?}
START --> Q5{Give the agent persistent instructions?}
Q1 -->|Yes| Q1a{Exact timing or flexible?}
Q1a -->|Exact| CRON["Scheduled Tasks (Cron)"]
Q1a -->|Flexible| HEARTBEAT[Heartbeat]
Q2 -->|Yes| TASKS[Background Tasks]
Q3 -->|Yes| FLOW[Task Flow]
Q4 -->|Yes| HOOKS[Hooks]
Q5 -->|Yes| SO[Standing Orders]
```
| Use case | Recommended | Why |
| --------------------------------------- | ---------------------- | ------------------------------------------------ |
| Send daily report at 9 AM sharp | Scheduled Tasks (Cron) | Exact timing, isolated execution |
| Remind me in 20 minutes | Scheduled Tasks (Cron) | One-shot with precise timing (`--at`) |
| Run weekly deep analysis | Scheduled Tasks (Cron) | Standalone task, can use different model |
| Check inbox every 30 min | Heartbeat | Batches with other checks, context-aware |
| Monitor calendar for upcoming events | Heartbeat | Natural fit for periodic awareness |
| Inspect status of a subagent or ACP run | Background Tasks | Tasks ledger tracks all detached work |
| Audit what ran and when | Background Tasks | `openclaw tasks list` and `openclaw tasks audit` |
| Multi-step research then summarize | Task Flow | Durable orchestration with revision tracking |
| Run a script on session reset | Hooks | Event-driven, fires on lifecycle events |
| Execute code on every tool call | Hooks | Hooks can filter by event type |
| Always check compliance before replying | Standing Orders | Injected into every session automatically |
### Scheduled Tasks (Cron) vs Heartbeat
| Dimension | Scheduled Tasks (Cron) | Heartbeat |
| --------------- | ----------------------------------- | ------------------------------------- |
| Timing | Exact (cron expressions, one-shot) | Approximate (default every 30 min) |
| Session context | Fresh (isolated) or shared | Full main-session context |
| Task records | Always created | Never created |
| Delivery | Channel, webhook, or silent | Inline in main session |
| Best for | Reports, reminders, background jobs | Inbox checks, calendar, notifications |
Use Scheduled Tasks (Cron) when you need precise timing or isolated execution. Use Heartbeat when the work benefits from full session context and approximate timing is fine.
## Core concepts
### Scheduled tasks (cron)
Cron is the Gateway's built-in scheduler for precise timing. It persists jobs, wakes the agent at the right time, and can deliver output to a chat channel or webhook endpoint. Supports one-shot reminders, recurring expressions, and inbound webhook triggers.
See [Scheduled Tasks](/automation/cron-jobs).
### Tasks
The background task ledger tracks all detached work: ACP runs, subagent spawns, isolated cron executions, and CLI operations. Tasks are records, not schedulers. Use `openclaw tasks list` and `openclaw tasks audit` to inspect them.
See [Background Tasks](/automation/tasks).
### Task Flow
Task Flow is the flow orchestration substrate above background tasks. It manages durable multi-step flows with managed and mirrored sync modes, revision tracking, and `openclaw tasks flow list|show|cancel` for inspection.
See [Task Flow](/automation/taskflow).
### Standing orders
Standing orders grant the agent permanent operating authority for defined programs. They live in workspace files (typically `AGENTS.md`) and are injected into every session. Combine with cron for time-based enforcement.
See [Standing Orders](/automation/standing-orders).
### Hooks
Hooks are event-driven scripts triggered by agent lifecycle events (`/new`, `/reset`, `/stop`), session compaction, gateway startup, message flow, and tool calls. Hooks are automatically discovered from directories and can be managed with `openclaw hooks`.
See [Hooks](/automation/hooks).
### Heartbeat
Heartbeat is a periodic main-session turn (default every 30 minutes). It batches multiple checks (inbox, calendar, notifications) in one agent turn with full session context. Heartbeat turns do not create task records. Use `HEARTBEAT.md` for a small checklist, or a `tasks:` block when you want due-only periodic checks inside heartbeat itself. Empty heartbeat files skip as `empty-heartbeat-file`; due-only task mode skips as `no-tasks-due`.
See [Heartbeat](/gateway/heartbeat).
## How they work together
- **Cron** handles precise schedules (daily reports, weekly reviews) and one-shot reminders. All cron executions create task records.
- **Heartbeat** handles routine monitoring (inbox, calendar, notifications) in one batched turn every 30 minutes.
- **Hooks** react to specific events (tool calls, session resets, compaction) with custom scripts.
- **Standing orders** give the agent persistent context and authority boundaries.
- **Task Flow** coordinates multi-step flows above individual tasks.
- **Tasks** automatically track all detached work so you can inspect and audit it.
## Related
- [Scheduled Tasks](/automation/cron-jobs) — precise scheduling and one-shot reminders
- [Background Tasks](/automation/tasks) — task ledger for all detached work
- [Task Flow](/automation/taskflow) — durable multi-step flow orchestration
- [Hooks](/automation/hooks) — event-driven lifecycle scripts
- [Standing Orders](/automation/standing-orders) — persistent agent instructions
- [Heartbeat](/gateway/heartbeat) — periodic main-session turns
- [Configuration Reference](/gateway/configuration-reference) — all config keys

View file

@ -0,0 +1,8 @@
---
summary: "Redirect to /tools/message"
title: "Polls"
---
# Polls
This page moved to [Message tool](/cli/message). See [Message tool](/cli/message) for poll documentation.

View file

@ -0,0 +1,254 @@
---
summary: "Define permanent operating authority for autonomous agent programs"
read_when:
- Setting up autonomous agent workflows that run without per-task prompting
- Defining what the agent can do independently vs. what needs human approval
- Structuring multi-program agents with clear boundaries and escalation rules
title: "Standing Orders"
---
# Standing Orders
Standing orders grant your agent **permanent operating authority** for defined programs. Instead of giving individual task instructions each time, you define programs with clear scope, triggers, and escalation rules — and the agent executes autonomously within those boundaries.
This is the difference between telling your assistant "send the weekly report" every Friday vs. granting standing authority: "You own the weekly report. Compile it every Friday, send it, and only escalate if something looks wrong."
## Why Standing Orders?
**Without standing orders:**
- You must prompt the agent for every task
- The agent sits idle between requests
- Routine work gets forgotten or delayed
- You become the bottleneck
**With standing orders:**
- The agent executes autonomously within defined boundaries
- Routine work happens on schedule without prompting
- You only get involved for exceptions and approvals
- The agent fills idle time productively
## How They Work
Standing orders are defined in your [agent workspace](/concepts/agent-workspace) files. The recommended approach is to include them directly in `AGENTS.md` (which is auto-injected every session) so the agent always has them in context. For larger configurations, you can also place them in a dedicated file like `standing-orders.md` and reference it from `AGENTS.md`.
Each program specifies:
1. **Scope** — what the agent is authorized to do
2. **Triggers** — when to execute (schedule, event, or condition)
3. **Approval gates** — what requires human sign-off before acting
4. **Escalation rules** — when to stop and ask for help
The agent loads these instructions every session via the workspace bootstrap files (see [Agent Workspace](/concepts/agent-workspace) for the full list of auto-injected files) and executes against them, combined with [cron jobs](/automation/cron-jobs) for time-based enforcement.
<Tip>
Put standing orders in `AGENTS.md` to guarantee they're loaded every session. The workspace bootstrap automatically injects `AGENTS.md`, `SOUL.md`, `TOOLS.md`, `IDENTITY.md`, `USER.md`, `HEARTBEAT.md`, `BOOTSTRAP.md`, and `MEMORY.md` — but not arbitrary files in subdirectories.
</Tip>
## Anatomy of a Standing Order
```markdown
## Program: Weekly Status Report
**Authority:** Compile data, generate report, deliver to stakeholders
**Trigger:** Every Friday at 4 PM (enforced via cron job)
**Approval gate:** None for standard reports. Flag anomalies for human review.
**Escalation:** If data source is unavailable or metrics look unusual (>2σ from norm)
### Execution Steps
1. Pull metrics from configured sources
2. Compare to prior week and targets
3. Generate report in Reports/weekly/YYYY-MM-DD.md
4. Deliver summary via configured channel
5. Log completion to Agent/Logs/
### What NOT to Do
- Do not send reports to external parties
- Do not modify source data
- Do not skip delivery if metrics look bad — report accurately
```
## Standing Orders + Cron Jobs
Standing orders define **what** the agent is authorized to do. [Cron jobs](/automation/cron-jobs) define **when** it happens. They work together:
```
Standing Order: "You own the daily inbox triage"
↓
Cron Job (8 AM daily): "Execute inbox triage per standing orders"
↓
Agent: Reads standing orders → executes steps → reports results
```
The cron job prompt should reference the standing order rather than duplicating it:
```bash
openclaw cron add \
--name daily-inbox-triage \
--cron "0 8 * * 1-5" \
--tz America/New_York \
--timeout-seconds 300 \
--announce \
--channel bluebubbles \
--to "+1XXXXXXXXXX" \
--message "Execute daily inbox triage per standing orders. Check mail for new alerts. Parse, categorize, and persist each item. Report summary to owner. Escalate unknowns."
```
## Examples
### Example 1: Content & Social Media (Weekly Cycle)
```markdown
## Program: Content & Social Media
**Authority:** Draft content, schedule posts, compile engagement reports
**Approval gate:** All posts require owner review for first 30 days, then standing approval
**Trigger:** Weekly cycle (Monday review → mid-week drafts → Friday brief)
### Weekly Cycle
- **Monday:** Review platform metrics and audience engagement
- **Tuesday–Thursday:** Draft social posts, create blog content
- **Friday:** Compile weekly marketing brief → deliver to owner
### Content Rules
- Voice must match the brand (see SOUL.md or brand voice guide)
- Never identify as AI in public-facing content
- Include metrics when available
- Focus on value to audience, not self-promotion
```
### Example 2: Finance Operations (Event-Triggered)
```markdown
## Program: Financial Processing
**Authority:** Process transaction data, generate reports, send summaries
**Approval gate:** None for analysis. Recommendations require owner approval.
**Trigger:** New data file detected OR scheduled monthly cycle
### When New Data Arrives
1. Detect new file in designated input directory
2. Parse and categorize all transactions
3. Compare against budget targets
4. Flag: unusual items, threshold breaches, new recurring charges
5. Generate report in designated output directory
6. Deliver summary to owner via configured channel
### Escalation Rules
- Single item > $500: immediate alert
- Category > budget by 20%: flag in report
- Unrecognizable transaction: ask owner for categorization
- Failed processing after 2 retries: report failure, do not guess
```
### Example 3: Monitoring & Alerts (Continuous)
```markdown
## Program: System Monitoring
**Authority:** Check system health, restart services, send alerts
**Approval gate:** Restart services automatically. Escalate if restart fails twice.
**Trigger:** Every heartbeat cycle
### Checks
- Service health endpoints responding
- Disk space above threshold
- Pending tasks not stale (>24 hours)
- Delivery channels operational
### Response Matrix
| Condition | Action | Escalate? |
| ---------------- | ------------------------ | ------------------------ |
| Service down | Restart automatically | Only if restart fails 2x |
| Disk space < 10% | Alert owner | Yes |
| Stale task > 24h | Remind owner | No |
| Channel offline | Log and retry next cycle | If offline > 2 hours |
```
## The Execute-Verify-Report Pattern
Standing orders work best when combined with strict execution discipline. Every task in a standing order should follow this loop:
1. **Execute** — Do the actual work (don't just acknowledge the instruction)
2. **Verify** — Confirm the result is correct (file exists, message delivered, data parsed)
3. **Report** — Tell the owner what was done and what was verified
```markdown
### Execution Rules
- Every task follows Execute-Verify-Report. No exceptions.
- "I'll do that" is not execution. Do it, then report.
- "Done" without verification is not acceptable. Prove it.
- If execution fails: retry once with adjusted approach.
- If still fails: report failure with diagnosis. Never silently fail.
- Never retry indefinitely — 3 attempts max, then escalate.
```
This pattern prevents the most common agent failure mode: acknowledging a task without completing it.
## Multi-Program Architecture
For agents managing multiple concerns, organize standing orders as separate programs with clear boundaries:
```markdown
# Standing Orders
## Program 1: [Domain A] (Weekly)
...
## Program 2: [Domain B] (Monthly + On-Demand)
...
## Program 3: [Domain C] (As-Needed)
...
## Escalation Rules (All Programs)
- [Common escalation criteria]
- [Approval gates that apply across programs]
```
Each program should have:
- Its own **trigger cadence** (weekly, monthly, event-driven, continuous)
- Its own **approval gates** (some programs need more oversight than others)
- Clear **boundaries** (the agent should know where one program ends and another begins)
## Best Practices
### Do
- Start with narrow authority and expand as trust builds
- Define explicit approval gates for high-risk actions
- Include "What NOT to do" sections — boundaries matter as much as permissions
- Combine with cron jobs for reliable time-based execution
- Review agent logs weekly to verify standing orders are being followed
- Update standing orders as your needs evolve — they're living documents
### Avoid
- Grant broad authority on day one ("do whatever you think is best")
- Skip escalation rules — every program needs a "when to stop and ask" clause
- Assume the agent will remember verbal instructions — put everything in the file
- Mix concerns in a single program — separate programs for separate domains
- Forget to enforce with cron jobs — standing orders without triggers become suggestions
## Related
- [Automation & Tasks](/automation) — all automation mechanisms at a glance
- [Cron Jobs](/automation/cron-jobs) — schedule enforcement for standing orders
- [Hooks](/automation/hooks) — event-driven scripts for agent lifecycle events
- [Webhooks](/automation/cron-jobs#webhooks) — inbound HTTP event triggers
- [Agent Workspace](/concepts/agent-workspace) — where standing orders live, including the full list of auto-injected bootstrap files (AGENTS.md, SOUL.md, etc.)

View file

@ -0,0 +1,82 @@
---
summary: "Task Flow flow orchestration layer above background tasks"
read_when:
- You want to understand how Task Flow relates to background tasks
- You encounter Task Flow or openclaw tasks flow in release notes or docs
- You want to inspect or manage durable flow state
title: "Task Flow"
---
# Task Flow
Task Flow is the flow orchestration substrate that sits above [background tasks](/automation/tasks). It manages durable multi-step flows with their own state, revision tracking, and sync semantics while individual tasks remain the unit of detached work.
## When to use Task Flow
Use Task Flow when work spans multiple sequential or branching steps and you need durable progress tracking across gateway restarts. For single background operations, a plain [task](/automation/tasks) is sufficient.
| Scenario | Use |
| ------------------------------------- | -------------------- |
| Single background job | Plain task |
| Multi-step pipeline (A then B then C) | Task Flow (managed) |
| Observe externally created tasks | Task Flow (mirrored) |
| One-shot reminder | Cron job |
## Sync modes
### Managed mode
Task Flow owns the lifecycle end-to-end. It creates tasks as flow steps, drives them to completion, and advances the flow state automatically.
Example: a weekly report flow that (1) gathers data, (2) generates the report, and (3) delivers it. Task Flow creates each step as a background task, waits for completion, then moves to the next step.
```
Flow: weekly-report
Step 1: gather-data → task created → succeeded
Step 2: generate-report → task created → succeeded
Step 3: deliver → task created → running
```
### Mirrored mode
Task Flow observes externally created tasks and keeps flow state in sync without taking ownership of task creation. This is useful when tasks originate from cron jobs, CLI commands, or other sources and you want a unified view of their progress as a flow.
Example: three independent cron jobs that together form a "morning ops" routine. A mirrored flow tracks their collective progress without controlling when or how they run.
## Durable state and revision tracking
Each flow persists its own state and tracks revisions so progress survives gateway restarts. Revision tracking enables conflict detection when multiple sources attempt to advance the same flow concurrently.
## Cancel behavior
`openclaw tasks flow cancel` sets a sticky cancel intent on the flow. Active tasks within the flow are cancelled, and no new steps are started. The cancel intent persists across restarts, so a cancelled flow stays cancelled even if the gateway restarts before all child tasks have terminated.
## CLI commands
```bash
# List active and recent flows
openclaw tasks flow list
# Show details for a specific flow
openclaw tasks flow show <lookup>
# Cancel a running flow and its active tasks
openclaw tasks flow cancel <lookup>
```
| Command | Description |
| --------------------------------- | --------------------------------------------- |
| `openclaw tasks flow list` | Shows tracked flows with status and sync mode |
| `openclaw tasks flow show <id>` | Inspect one flow by flow id or lookup key |
| `openclaw tasks flow cancel <id>` | Cancel a running flow and its active tasks |
## How flows relate to tasks
Flows coordinate tasks, not replace them. A single flow may drive multiple background tasks over its lifetime. Use `openclaw tasks` to inspect individual task records and `openclaw tasks flow` to inspect the orchestrating flow.
## Related
- [Background Tasks](/automation/tasks) — the detached work ledger that flows coordinate
- [CLI: tasks](/cli/index#tasks) — CLI command reference for `openclaw tasks flow`
- [Automation Overview](/automation) — all automation mechanisms at a glance
- [Cron Jobs](/automation/cron-jobs) — scheduled jobs that may feed into flows

View file

@ -0,0 +1,328 @@
---
summary: "Background task tracking for ACP runs, subagents, isolated cron jobs, and CLI operations"
read_when:
- Inspecting background work in progress or recently completed
- Debugging delivery failures for detached agent runs
- Understanding how background runs relate to sessions, cron, and heartbeat
title: "Background Tasks"
---
# Background Tasks
> **Looking for scheduling?** See [Automation & Tasks](/automation) for choosing the right mechanism. This page covers **tracking** background work, not scheduling it.
Background tasks track work that runs **outside your main conversation session**:
ACP runs, subagent spawns, isolated cron job executions, and CLI-initiated operations.
Tasks do **not** replace sessions, cron jobs, or heartbeats — they are the **activity ledger** that records what detached work happened, when, and whether it succeeded.
<Note>
Not every agent run creates a task. Heartbeat turns and normal interactive chat do not. All cron executions, ACP spawns, subagent spawns, and CLI agent commands do.
</Note>
## TL;DR
- Tasks are **records**, not schedulers — cron and heartbeat decide _when_ work runs, tasks track _what happened_.
- ACP, subagents, all cron jobs, and CLI operations create tasks. Heartbeat turns do not.
- Each task moves through `queued → running → terminal` (succeeded, failed, timed_out, cancelled, or lost).
- Cron tasks stay live while the cron runtime still owns the job; chat-backed CLI tasks stay live only while their owning run context is still active.
- Completion is push-driven: detached work can notify directly or wake the
requester session/heartbeat when it finishes, so status polling loops are
usually the wrong shape.
- Isolated cron runs and subagent completions best-effort clean up tracked browser tabs/processes for their child session before final cleanup bookkeeping.
- Isolated cron delivery suppresses stale interim parent replies while
descendant subagent work is still draining, and it prefers final descendant
output when that arrives before delivery.
- Completion notifications are delivered directly to a channel or queued for the next heartbeat.
- `openclaw tasks list` shows all tasks; `openclaw tasks audit` surfaces issues.
- Terminal records are kept for 7 days, then automatically pruned.
## Quick start
```bash
# List all tasks (newest first)
openclaw tasks list
# Filter by runtime or status
openclaw tasks list --runtime acp
openclaw tasks list --status running
# Show details for a specific task (by ID, run ID, or session key)
openclaw tasks show <lookup>
# Cancel a running task (kills the child session)
openclaw tasks cancel <lookup>
# Change notification policy for a task
openclaw tasks notify <lookup> state_changes
# Run a health audit
openclaw tasks audit
# Preview or apply maintenance
openclaw tasks maintenance
openclaw tasks maintenance --apply
# Inspect TaskFlow state
openclaw tasks flow list
openclaw tasks flow show <lookup>
openclaw tasks flow cancel <lookup>
```
## What creates a task
| Source | Runtime type | When a task record is created | Default notify policy |
| ---------------------- | ------------ | ------------------------------------------------------ | --------------------- |
| ACP background runs | `acp` | Spawning a child ACP session | `done_only` |
| Subagent orchestration | `subagent` | Spawning a subagent via `sessions_spawn` | `done_only` |
| Cron jobs (all types) | `cron` | Every cron execution (main-session and isolated) | `silent` |
| CLI operations | `cli` | `openclaw agent` commands that run through the gateway | `silent` |
| Agent media jobs | `cli` | Session-backed `video_generate` runs | `silent` |
Main-session cron tasks use `silent` notify policy by default — they create records for tracking but do not generate notifications. Isolated cron tasks also default to `silent` but are more visible because they run in their own session.
Session-backed `video_generate` runs also use `silent` notify policy. They still create task records, but completion is handed back to the original agent session as an internal wake so the agent can write the follow-up message and attach the finished video itself. If you opt into `tools.media.asyncCompletion.directSend`, async `music_generate` and `video_generate` completions try direct channel delivery first before falling back to the requester-session wake path.
While a session-backed `video_generate` task is still active, the tool also acts as a guardrail: repeated `video_generate` calls in that same session return the active task status instead of starting a second concurrent generation. Use `action: "status"` when you want an explicit progress/status lookup from the agent side.
**What does not create tasks:**
- Heartbeat turns — main-session; see [Heartbeat](/gateway/heartbeat)
- Normal interactive chat turns
- Direct `/command` responses
## Task lifecycle
```mermaid
stateDiagram-v2
[*] --> queued
queued --> running : agent starts
running --> succeeded : completes ok
running --> failed : error
running --> timed_out : timeout exceeded
running --> cancelled : operator cancels
queued --> lost : session gone > 5 min
running --> lost : session gone > 5 min
```
| Status | What it means |
| ----------- | -------------------------------------------------------------------------- |
| `queued` | Created, waiting for the agent to start |
| `running` | Agent turn is actively executing |
| `succeeded` | Completed successfully |
| `failed` | Completed with an error |
| `timed_out` | Exceeded the configured timeout |
| `cancelled` | Stopped by the operator via `openclaw tasks cancel` |
| `lost` | The runtime lost authoritative backing state after a 5-minute grace period |
Transitions happen automatically — when the associated agent run ends, the task status updates to match.
`lost` is runtime-aware:
- ACP tasks: backing ACP child session metadata disappeared.
- Subagent tasks: backing child session disappeared from the target agent store.
- Cron tasks: the cron runtime no longer tracks the job as active.
- CLI tasks: isolated child-session tasks use the child session; chat-backed CLI tasks use the live run context instead, so lingering channel/group/direct session rows do not keep them alive.
## Delivery and notifications
When a task reaches a terminal state, OpenClaw notifies you. There are two delivery paths:
**Direct delivery** — if the task has a channel target (the `requesterOrigin`), the completion message goes straight to that channel (Telegram, Discord, Slack, etc.). For subagent completions, OpenClaw also preserves bound thread/topic routing when available and can fill a missing `to` / account from the requester session's stored route (`lastChannel` / `lastTo` / `lastAccountId`) before giving up on direct delivery.
**Session-queued delivery** — if direct delivery fails or no origin is set, the update is queued as a system event in the requester's session and surfaces on the next heartbeat.
<Tip>
Task completion triggers an immediate heartbeat wake so you see the result quickly — you do not have to wait for the next scheduled heartbeat tick.
</Tip>
That means the usual workflow is push-based: start detached work once, then let
the runtime wake or notify you on completion. Poll task state only when you
need debugging, intervention, or an explicit audit.
### Notification policies
Control how much you hear about each task:
| Policy | What is delivered |
| --------------------- | ----------------------------------------------------------------------- |
| `done_only` (default) | Only terminal state (succeeded, failed, etc.) — **this is the default** |
| `state_changes` | Every state transition and progress update |
| `silent` | Nothing at all |
Change the policy while a task is running:
```bash
openclaw tasks notify <lookup> state_changes
```
## CLI reference
### `tasks list`
```bash
openclaw tasks list [--runtime <acp|subagent|cron|cli>] [--status <status>] [--json]
```
Output columns: Task ID, Kind, Status, Delivery, Run ID, Child Session, Summary.
### `tasks show`
```bash
openclaw tasks show <lookup>
```
The lookup token accepts a task ID, run ID, or session key. Shows the full record including timing, delivery state, error, and terminal summary.
### `tasks cancel`
```bash
openclaw tasks cancel <lookup>
```
For ACP and subagent tasks, this kills the child session. For CLI-tracked tasks, cancellation is recorded in the task registry (there is no separate child runtime handle). Status transitions to `cancelled` and a delivery notification is sent when applicable.
### `tasks notify`
```bash
openclaw tasks notify <lookup> <done_only|state_changes|silent>
```
### `tasks audit`
```bash
openclaw tasks audit [--json]
```
Surfaces operational issues. Findings also appear in `openclaw status` when issues are detected.
| Finding | Severity | Trigger |
| ------------------------- | -------- | ----------------------------------------------------- |
| `stale_queued` | warn | Queued for more than 10 minutes |
| `stale_running` | error | Running for more than 30 minutes |
| `lost` | error | Runtime-backed task ownership disappeared |
| `delivery_failed` | warn | Delivery failed and notify policy is not `silent` |
| `missing_cleanup` | warn | Terminal task with no cleanup timestamp |
| `inconsistent_timestamps` | warn | Timeline violation (for example ended before started) |
### `tasks maintenance`
```bash
openclaw tasks maintenance [--json]
openclaw tasks maintenance --apply [--json]
```
Use this to preview or apply reconciliation, cleanup stamping, and pruning for
tasks and Task Flow state.
Reconciliation is runtime-aware:
- ACP/subagent tasks check their backing child session.
- Cron tasks check whether the cron runtime still owns the job.
- Chat-backed CLI tasks check the owning live run context, not just the chat session row.
Completion cleanup is also runtime-aware:
- Subagent completion best-effort closes tracked browser tabs/processes for the child session before announce cleanup continues.
- Isolated cron completion best-effort closes tracked browser tabs/processes for the cron session before the run fully tears down.
- Isolated cron delivery waits out descendant subagent follow-up when needed and
suppresses stale parent acknowledgement text instead of announcing it.
- Subagent completion delivery prefers the latest visible assistant text; if that is empty it falls back to sanitized latest tool/toolResult text, and timeout-only tool-call runs can collapse to a short partial-progress summary.
- Cleanup failures do not mask the real task outcome.
### `tasks flow list|show|cancel`
```bash
openclaw tasks flow list [--status <status>] [--json]
openclaw tasks flow show <lookup> [--json]
openclaw tasks flow cancel <lookup>
```
Use these when the orchestrating Task Flow is the thing you care about rather
than one individual background task record.
## Chat task board (`/tasks`)
Use `/tasks` in any chat session to see background tasks linked to that session. The board shows
active and recently completed tasks with runtime, status, timing, and progress or error detail.
When the current session has no visible linked tasks, `/tasks` falls back to agent-local task counts
so you still get an overview without leaking other-session details.
For the full operator ledger, use the CLI: `openclaw tasks list`.
## Status integration (task pressure)
`openclaw status` includes an at-a-glance task summary:
```
Tasks: 3 queued · 2 running · 1 issues
```
The summary reports:
- **active** — count of `queued` + `running`
- **failures** — count of `failed` + `timed_out` + `lost`
- **byRuntime** — breakdown by `acp`, `subagent`, `cron`, `cli`
Both `/status` and the `session_status` tool use a cleanup-aware task snapshot: active tasks are
preferred, stale completed rows are hidden, and recent failures only surface when no active work
remains. This keeps the status card focused on what matters right now.
## Storage and maintenance
### Where tasks live
Task records persist in SQLite at:
```
$OPENCLAW_STATE_DIR/tasks/runs.sqlite
```
The registry loads into memory at gateway start and syncs writes to SQLite for durability across restarts.
### Automatic maintenance
A sweeper runs every **60 seconds** and handles three things:
1. **Reconciliation** — checks whether active tasks still have authoritative runtime backing. ACP/subagent tasks use child-session state, cron tasks use active-job ownership, and chat-backed CLI tasks use the owning run context. If that backing state is gone for more than 5 minutes, the task is marked `lost`.
2. **Cleanup stamping** — sets a `cleanupAfter` timestamp on terminal tasks (endedAt + 7 days).
3. **Pruning** — deletes records past their `cleanupAfter` date.
**Retention**: terminal task records are kept for **7 days**, then automatically pruned. No configuration needed.
## How tasks relate to other systems
### Tasks and Task Flow
[Task Flow](/automation/taskflow) is the flow orchestration layer above background tasks. A single flow may coordinate multiple tasks over its lifetime using managed or mirrored sync modes. Use `openclaw tasks` to inspect individual task records and `openclaw tasks flow` to inspect the orchestrating flow.
See [Task Flow](/automation/taskflow) for details.
### Tasks and cron
A cron job **definition** lives in `~/.openclaw/cron/jobs.json`. **Every** cron execution creates a task record — both main-session and isolated. Main-session cron tasks default to `silent` notify policy so they track without generating notifications.
See [Cron Jobs](/automation/cron-jobs).
### Tasks and heartbeat
Heartbeat runs are main-session turns — they do not create task records. When a task completes, it can trigger a heartbeat wake so you see the result promptly.
See [Heartbeat](/gateway/heartbeat).
### Tasks and sessions
A task may reference a `childSessionKey` (where work runs) and a `requesterSessionKey` (who started it). Sessions are conversation context; tasks are activity tracking on top of that.
### Tasks and agent runs
A task's `runId` links to the agent run doing the work. Agent lifecycle events (start, end, error) automatically update the task status — you do not need to manage the lifecycle manually.
## Related
- [Automation & Tasks](/automation) — all automation mechanisms at a glance
- [Task Flow](/automation/taskflow) — flow orchestration above tasks
- [Scheduled Tasks](/automation/cron-jobs) — scheduling background work
- [Heartbeat](/gateway/heartbeat) — periodic main-session turns
- [CLI: Tasks](/cli/index#tasks) — CLI command reference

View file

@ -0,0 +1,8 @@
---
summary: "Redirect to /automation/cron-jobs"
title: "Automation Troubleshooting"
---
# Automation Troubleshooting
This page moved to [Scheduled Tasks](/automation/cron-jobs#troubleshooting). See [Scheduled Tasks](/automation/cron-jobs#troubleshooting) for troubleshooting documentation.

View file

@ -0,0 +1,8 @@
---
summary: "Redirect to /automation/cron-jobs"
title: "Webhooks"
---
# Webhooks
This page moved to [Scheduled Tasks](/automation/cron-jobs#webhooks). See [Scheduled Tasks](/automation/cron-jobs#webhooks) for webhook documentation.