跳到正文
FunCoding

搜索

搜索文档、Skill 和 MCP

Automation payloads

Payload kinds, agent-turn flags, command and script payloads, and session execution styles

What a job runs and where it runs: the four payload kinds, their flags, and the four session execution styles. Part of the Automations guide.

Payloads

Every job carries exactly one payload kind, chosen by flag:

PayloadFlagRuns
System event--system-event <text>Enqueued into the main session, no model call by itself
Agent message--message <text>A model-backed agent turn
Command--command <shell> or --command-argv <json>A shell/process on the Gateway host, no model call
Script--script <file|->A headless code-mode script using the owning agent's tools

System-owned monitor jobs are gateway-converged and cannot be created or edited through the CLI or API. The heartbeat kind creates one heartbeat monitor job per heartbeat-enabled agent (see Heartbeat). Monitor jobs appear in openclaw cron list; use --all to include disabled rows.

The weekly Skill Workshop curator (declaration key skill-collection-review:<agentId>, and the older skillCollectionReview payload kind) is retired. The Gateway deletes those stored rows when it loads the cron store and creates no replacement; the declaration-key namespace stays reserved. Learned-skill cleanup now runs without a schedule; see Unused-skill cleanup.

Agent-turn options

Prompt text (required for isolated/current/custom-session jobs).

Model override; must resolve to an allowed model or the run fails with a validation error.

Per-job fallback model list, for example --fallbacks openai/gpt-6-astra,openrouter/meta-llama/llama-3.3-70b-instruct:free. Pass --fallbacks "" for a strict run with no fallbacks.

On automations edit, removes the per-job fallback override so the job follows configured fallback precedence. Cannot combine with --fallbacks.

On automations edit, removes the per-job model override so the job follows normal automation model precedence (stored automation-session override, else agent/default model). Cannot combine with --model.

Thinking level override (off|minimal|low|medium|high|xhigh|adaptive|max|ultra). Available levels still depend on the selected model and agent runtime.

On automations edit, removes the per-job thinking override. Cannot combine with --thinking.

Skip workspace bootstrap file injection.

Restrict which tools the job can use, for example --tools exec,read. Pass --tools "" for an empty allowlist that disables all agent tools, including tools used by a condition trigger.

New jobs that can run tools always store an explicit tool policy. A job created without --tools (or with *) stores *: each run uses the owner session's current tool policy, including its group, agent, sandbox, and runtime restrictions. An agent that requests a finite list is capped to the tools available to its creating turn and cannot widen the stored list. automations edit --clear-tools restores *. Existing jobs that predate an explicit tool policy retain their current behavior until their tool policy is explicitly edited or the job is recreated. Agent-created script payloads, condition triggers, and jobs whose creator captured Codex app authority store the creating turn's tools instead: scripts reach MCP only through servers their list names, and app authority is bound to that list.

Earlier releases saved a copy of the creating turn's tool list on agent-created agent turns. That copy could miss tools the creator had, such as the native shell. Those jobs now run with their owner conversation's tools, like a * job; the stored copy is left as it is. Jobs whose creator captured Codex app authority keep using their copy.

Changing an account-bound job to a payload that does not run tools and later back to an agent turn preserves its account restriction. A payload conversion does not reauthorize that job as an operator-created job.

Doctor checks scheduled tool authority only for agent turns, script payloads, and jobs with a condition script. A command payload without a condition script does not need agent-tool provenance; its retained account restriction stays unchanged.

Management edits cannot restore missing policy metadata as operator authority. For a legacy job that has lost its policy, an authenticated operator can explicitly reauthorize it, or an authenticated creator can recreate it with a fresh tool cap.

When the creator's exec capability is fixed to the Gateway, the automation also retains that target. With tools.exec.host: "auto", the saved target determines placement. A conflicting current explicit host setting or required sandbox isolation blocks the command instead of moving it to another host. Current tool and approval policies still apply.

With message in the tool cap, scheduled agent turns can read messages and channel information on supported channel plugins without an inbound chat. Operator-created jobs use the current operator read policy. Agent-created jobs retain their recorded creator origin and account, and the channel's delegated read restrictions still apply. Delivery settings do not grant read access.

Manual runs use the same scheduled execution context as timer-fired runs after the request passes admission. Ending the chat turn or tool call that started a run does not expire the job's tool access. The job still uses its stored authority and current tool restrictions; starting it manually does not grant the caller's extra permissions to the job.

Current global, agent, profile, and provider tool policy is checked when each new scheduled message invocation starts. Configuration changes apply to later invocations; an invocation already admitted retains its configuration. Disabling or removing a job, withdrawing its message capability, or revoking its caller or plugin authority stops further affected reads from that occurrence, including pending reads before another provider request or result delivery. Re-enabling the job does not restore an occurrence's revoked access.

A new account-bound job created by a verified local administrator retains that authenticated local source, allowing provider-permitted reads through its saved creator account. Editing its toolsAllow cap from the same local source explicitly reauthorizes an existing job. Description, display-label, and exact no-op edits preserve the recorded source. Changes to model-facing names, prompts, tools, schedules, or other executable behavior need fresh source authorization and clear the old source when none is present. Remote management alone cannot supply local-source authorization, and older jobs without a provable origin remain blocked until reauthorized or recreated from a fresh authorized source.

Scheduled turns can also edit, delete, pin, and unpin Discord messages. Agent-created jobs use their recorded creator account and Discord's delegated target restrictions. Operator-created jobs use Discord's operator target policy. Trusted operator jobs can additionally use channel-edit, including the existing channel and thread edit options; account-created jobs do not inherit operator administration.

For these writes, the job needs message in its tool policy, an enabled account and action, and the bot's required Discord permissions. Use an updated Discord plugin with scheduled write support.

Account-bound jobs can use Discord channel-edit when an authenticated Discord turn has authorized their current definition. OpenClaw privately retains that requester's Discord account and sender identity, and Discord's current channel or thread permissions must allow the edit. The original session creator and a configured OpenClaw owner are not substitutes for those native permissions.

Executable edits from the job's owning conversation and account bind the job to the current authorized editor. This includes the prompt, model, name, schedule, delivery, and tool policy. An executable edit without a matching authenticated Discord requester clears this permission and stops further native actions from the old occurrence. Description and display-label changes preserve it.

Older jobs, jobs edited by older writers, and jobs whose requester authorization was cleared need fresh authorization before channel-edit can run. From the original Discord conversation and account, ask the agent to edit the job with an explicit finite toolsAllow list including message, or recreate it there. If its execution authorization is also missing, recreate it from that conversation; management access alone does not restore the missing authorization. The editor must already have automation-management access. Other job behavior keeps its existing policy; a CLI edit cannot invent a Discord requester. These requester facts are omitted from public job results, and no new setting is needed.

Channel-name lookup and subsequent write requests retain the current job and plugin authority. Configuration changes apply to the next message invocation; disabling or narrowing the job itself stops later requests and retries in the current invocation. A confirmed write still returns its result if authority ends while the response is pending.

--model sets the job's primary model; it does not replace a session /model override, so configured fallback chains still apply on top of it. An unresolved or disallowed model fails the run with an explicit validation error rather than silently falling back to the default. If a job has --model but no explicit or configured fallback list, OpenClaw passes an empty fallback override instead of silently appending the agent primary as a hidden retry target.

A fallback after a provider timeout continues the same scheduled turn and reuses its saved user input. Failed attempts do not complete the turn or duplicate the scheduled prompt.

Pick the model for the job's difficulty, not the agent's default. Routine automation - summaries, triage, classification, status checks - runs well on a lighter model, which is cheaper and faster per run and adds up across a schedule. Keep your default model for jobs that need deep reasoning, and use --fallbacks when a light primary should escalate on failure.

Model-selection precedence for isolated jobs, highest first:

  1. Per-job payload model (explicit config; a disallowed model fails the run)
  2. Gmail hook model override (only when the run came from Gmail and that override is allowed)
  3. User-selected stored automation-session model override
  4. Agent/default model selection

Fast mode follows the resolved live selection. Isolated automation resolves it in this order: stored session fastMode, per-agent agents.entries.*.fastModeDefault, global agents.defaults.fastModeDefault, then selected-model params.fastMode. Auto mode uses the model's params.fastAutoOnSeconds cutoff, defaulting to 60 seconds.

When a runtime reports token usage without a cost, automation estimates use the selected agent's local models.json prices and the model metadata retained for that run.

If a run hits a live model-switch handoff, the scheduler retries with the switched provider/model and persists that selection (and any new auth profile) for the active run. Retries are bounded: after the initial attempt plus 2 switch retries, the scheduler aborts instead of looping.

Before an isolated run starts, OpenClaw checks reachable local endpoints for configured api: "ollama" and api: "openai-completions" providers whose baseUrl is loopback, private-network, or .local. This preflight walks the job's configured fallback chain and only marks the run skipped once every candidate is unreachable; --fallbacks "" keeps that walk strict to just the primary model. A down endpoint records the run as skipped with a clear error instead of starting a model call. The result is cached for 5 minutes per endpoint (not per job or model), so many due jobs sharing a dead local Ollama/vLLM/SGLang/LM Studio server cost one check instead of a request storm. Skipped preflight runs do not increment execution-error backoff; set failureAlert.includeSkipped to opt into repeated skip alerts.

Client-side preflight timeouts are not cached. The next scheduled run checks the endpoint again instead of inheriting a timeout from another run.

Command payloads

Command payloads run deterministic scripts inside the Gateway scheduler without starting a model-backed turn. They execute on the Gateway host, capture stdout/stderr, record the run in the job's run history, and reuse the same announce, webhook, and none delivery modes as agent-turn jobs.

When an agent-turn automation's exec needs approval, the card is delivered to connected approval surfaces and the run waits for the decision; answering Always allow mints a scoped standing grant so later occurrences run without prompting. See Standing grants for automations for lifetime, listing, and revocation.

Command payloads are an operator-admin Gateway automation surface, not an agent tools.exec call. Creating, updating, removing, or manually running automation jobs requires operator.admin; scheduled command runs later execute inside the Gateway process as that admin-authored automation. Agent exec policy (tools.exec.mode, approval prompts, per-agent tool allowlists) governs model-visible exec tools, not command payloads.

openclaw automations create "*/15 * * * *" \
  --name "Queue depth check" \
  --command "scripts/check-queue.sh" \
  --command-cwd "/srv/app" \
  --announce \
  --channel telegram \
  --to "-1001234567890"

--command <shell> stores argv: ["sh", "-lc", <shell>]. Use --command-argv '["node","scripts/report.mjs"]' for exact argv execution without shell parsing. Optional --command-env KEY=VALUE (repeatable), --command-input, --timeout-seconds (default 10 minutes), --no-output-timeout-seconds, and --output-max-bytes control the process environment, stdin, and output bounds.

Delivered text is derived from process output: non-empty stdout wins; if stdout is empty and stderr is non-empty, stderr is delivered; if both are present, the scheduler sends a small stdout: / stderr: block. Exit code 0 records the run ok; non-zero exit, signal, timeout, or no-output timeout records error and can trigger failure alerts. A command that prints only NO_REPLY uses the normal automation silent-token suppression and posts nothing back to chat.

When the run deadline stops a command, run history retains its captured output and command timeout reason after bounded process cleanup. Completion delivery does not start after that deadline.

Script payloads

Script payloads run headlessly in the same code-mode executor as trigger scripts, without starting a conversational agent turn. They are available by default; setting cron.triggers.enabled: false disables creation and execution of script payloads together with condition-trigger scripts and stream schedules. Script jobs support only main and isolated session targets.

openclaw automations create "0 * * * *" \
  --name "Hourly queue check" \
  --script ./automation/check-queue.js \
  --script-timeout-seconds 300 \
  --script-tool-budget 50 \
  --session isolated \
  --announce

Use --script <file|-> to read JavaScript from a file or stdin. The CLI preserves leading and trailing spaces in file paths; quote the path as one shell argument. The timeout defaults to 300 seconds and is capped at 900; the tool budget defaults to 50 calls and is capped at 200. These payload budgets are separate from the smaller trigger-gate evaluation budgets.

Script payloads can call configured MCP server tools as MCP.<server>.<tool>({ ...input }), like interactive Code Mode. MCP is opt-in per server: name each server in the job's toolsAllow (--tools) with an exact tool such as wispr-flow__search_meetings or a server-scoped glob such as wispr-flow__*. A wildcard *, a missing toolsAllow, a glob without a server prefix, or a script that never mentions MCP starts no server. Within a named server, the owning agent's tool policy still applies. Each run starts its own runtime for the named servers, counts connection time against the script timeout and each call against the tool budget, and retires the runtime when the run ends. A named server that fails to start is absent from MCP; if the script then fails, the run error ends with MCP server "<name>" is unavailable: <reason>. See Event triggers for the shared details.

The script may return an object with these optional fields:

  • notify: Text delivered through the job's announce, webhook, or none delivery mode. If omitted, nothing is delivered. For a main job, the text becomes a system event.
  • wake: "now" requests an immediate heartbeat after enqueueing notify (or a compact completion event); "next-heartbeat" enqueues the event for the next heartbeat.
  • state: JSON state, capped at 16 KB and persisted only after a successful run. The next run receives a frozen copy as trigger.state, matching trigger scripts. Because that namespace has one persisted owner, a script payload cannot be combined with a condition trigger on the same job.
  • nextCheck: A duration such as "15m". It is valid only for jobs with pacing enabled and uses the same pacing clamp as agent-turn proposals.

Throws, timeouts, exhausted tool budgets, invalid results, and nextCheck without pacing are normal automation run errors: they enter run history, backoff, and failure-alert handling without persisting returned state.

Plugin reloads invalidate cached script preparation. If a plugin retires during setup, OpenClaw refreshes the tools once before starting the script, within the original deadline. A failure after the script starts never triggers this setup retry. If the refresh fails, run history and failure alerts explain that automatic setup recovery failed and the script did not run.

Changing a running job's script payload or saved state protects that edit from the old script's returned state, including when completion is recovered after a Gateway restart. The completed run still retains its history.

Authoring recurring jobs

A recurring job re-runs the same instructions on every fire, so anything the model works out from scratch costs the same time and tokens each run. Keep the model for judgment and move the repeatable parts into code:

  • Put listing and diffing, dedupe, and checkpoints or watermarks in a workspace script that the payload runs in a single exec call.
  • Keep detailed instructions in a workspace file next to the script and have the message reference it (for example, "Follow scripts/<job>.md"), so most fixes need only workspace file edits, not a job update.
  • Have the message name the exact tool ids and argument shapes the run should use, instead of asking the model to discover them.
  • Cap toolsAllow to the tools the run actually needs.
  • When a script can decide there is nothing to do, use a condition trigger, a command payload, or a script payload so quiet fires skip the model. Scripts can call a configured MCP server only when toolsAllow names it (<server>__<tool> or <server>__*). Triggers and script payloads are unavailable when cron.triggers.enabled is false.
  • When a run fails, make it fail instead of posting the error yourself: throw from trigger or script payload JavaScript, or exit non-zero from a command payload. A script that returns an error field still succeeds. The scheduler owns failure accounting: only the failure alert waits for consecutive failed runs; the run's own output still follows the job's delivery setting.

Execution styles

Codex apps in scheduled automations

Codex-created automations can retain the app IDs and permission ceiling available to the authenticated creator thread. At execution, OpenClaw requires the same prepared Codex profile and account, then narrows the stored cap against current app policy. Revoked apps, account/runtime changes, and interactive approval requirements fail closed with a recovery message; they never fall back to broader or different credentials. Older jobs without a captured app envelope continue their ordinary non-app behavior; recreate or reauthorize one only when it needs Codex app access. See Native Codex plugins.

Style--session valueRuns inBest for
Main sessionmainOwning agent's main sessionReminders, system events
IsolatedisolatedDedicated cron:<jobId>Reports, background chores
Current sessioncurrentDetached; commits to the creation-bound conversationContext-aware recurring work
Custom sessionsession:custom-idPersistent named sessionWorkflows that build on history

Agent-turn jobs default to the creating conversation when the create request carries session context. Callers without a session key, including CLI and API callers that do not supply one, fall back to isolated. System events and heartbeats still default to main; command and script payloads still default to isolated.

An explicitly isolated agent-turn job created from a conversation keeps that conversation's identity for delivery. With default announce delivery and no explicit or remembered external route, its final result is committed into the creating conversation, including WebChat/Control UI. The run remains isolated and does not read the conversation's history. See Automation delivery for generation checks, duplicate prevention, and external-route behavior.

Main session vs current vs isolated vs custom

Main session jobs enqueue a system event into the owning agent's main session and optionally wake the heartbeat (--wake now or --wake next-heartbeat). The event is processed with that session's existing context and last delivery context. Internal automation turns do not extend daily or idle reset freshness; only visible user activity updates session freshness. Current-session jobs execute in a detached run session, read a bounded tail of the conversation captured when the job was created, and commit the final visible assistant result back to that exact conversation. 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.

current binds conversation context and result delivery, not the original agent execution or its worktree. The detached run has its own session identity and uses the scheduled agent's workspace and captured tool restrictions. It does not inherit the conversation's cloud worker placement. Messages sent to the job's cron session address its latest detached run, independently of the bound conversation. In-flight turns sent through that stable cron key are canceled if the key is reassigned. A task-specific checkout path in the prompt does not grant access to it. Before using a job to continue repository work, verify that its execution environment can access the required checkout and tools; otherwise keep the work with its existing execution owner. A result committed to the conversation does not itself resume the original agent.

Custom-session agent turns wait for active work in that session before preparing or resetting its context, so a scheduled tick cannot invalidate an in-progress compaction.

Custom-session agent turns use the existing session’s saved workspace and working directory, including its managed worktree. Requester-scoped jobs may use a saved workspace only for their owning conversation; trusted operator-scheduled jobs can target another conversation’s saved workspace. A missing, retired, or mismatched worktree stops the run instead of falling back to the agent’s default workspace. Filesystem containment and the job’s tool restrictions still apply; a path in the job prompt does not grant access. Persistent-session rollover keeps the saved workspace binding, permission mode, containment root, and inherited tool restrictions; detached runs do not inherit this workspace context. A new session:custom-id without an existing session starts in the configured agent workspace. Use delivery: { mode: "none" } without an external target for quiet named-session work that needs no runner fallback announcement.

Main-session automation events are self-contained system-event reminders. They do not automatically include the default heartbeat prompt or the heartbeat monitor scratch; say it explicitly in the automation event text if a reminder should consult that context.

Main-session jobs use the owning session's delivery context, not a separate chat announce target. Edits that enable announce delivery, or set a chat target without explicitly choosing no delivery, are rejected without changing the job. Use an isolated job with --message and --announce for chat delivery. Primary webhook delivery remains supported for main-session jobs.

What 'fresh session' means for isolated jobs

A new transcript/session id per run. OpenClaw carries safe preferences (thinking/fast/verbose settings, labels, explicit user-selected model/auth overrides), but does not inherit ambient conversation context from an older automation session row: channel/group routing, send or queue policy, elevation, origin, or ACP runtime binding. Use current or session:<id> when a recurring job should deliberately build on the same conversation context.

Unattended run contract

Isolated automation and hook agent turns are explicitly unattended: no one is present to clarify or approve. The final reply must be the deliverable rather than a plan, acknowledgement, or request for input. The agent returns NO_REPLY when nothing needs doing. When the task failed or is blocked, the reply starts with AUTOMATION_FAILED on its own line, followed by what failed and what it tried. The scheduler records that run as an error with the remaining text as its error, delivers that text instead of the token when the job announces, and applies the normal retry, failure-alert, and owner-repair policy. When the run hands its work to a subagent, the child's settled final answer is classified the same way. Only an exact first line counts; a reply that mentions the token elsewhere is ordinary output.

For trusted scheduled jobs, the job's own instructions win when they intentionally ask for a question or plan, and the agent may remove a job that is no longer needed. External hook turns receive only the common unattended contract; they do not receive that override or self-removal guidance across the external-content boundary.

Subagent and Discord delivery

When isolated automation runs orchestrate subagents, delivery prefers the final descendant output over stale parent interim text. If descendant tasks are still running or settling, OpenClaw suppresses that partial parent update instead of announcing it. This includes a yielded orchestrator waiting for its successor to start and completed descendants whose result delivery is still pending. The wait shares the existing run deadline and stops on cancellation. A delivery.mode: "none" run whose turn only handed work to a child waits for the child under the same deadline and records the child's final reply as the run output without sending it. A child that deliberately stays silent (NO_REPLY) leaves a quiet successful run; a child that times out or ends without a reply fails the run.

For text-only Discord announce targets, OpenClaw sends the canonical final assistant text once instead of replaying both streamed/intermediate text and the final answer. Media and structured Discord payloads are still delivered separately so attachments and components are not dropped.