Automation payloads: job types, flags, and session execution styles
Explains the four payload types a job can hold, their flags, and the four ways a session can execute. Useful for operators configuring cron jobs and automation runs.
Read this when
- Choosing a system-event, agent-turn, command, or script payload
- Setting a per-job model, thinking level, or tool policy
- Deciding between main, current, isolated, and custom sessions
What each job executes, and where: four payload types with their flags, plus four ways a session can execute. This page belongs to the Automations guide.
Payloads
A job holds one payload type only, and the flag selects it:
| Payload | Flag | Runs |
|---|---|---|
| System event | --system-event <text> | A normal turn inside the main session of the agent that owns the job |
| Agent message | --message <text> | A turn run by a model-backed agent |
| Command | --command <shell> or --command-argv <json> | A shell process on the Gateway host, with no model call |
| Script | --script <file|-> | A headless code-mode script that uses the owning agent's tools |
Doctor turns former heartbeat monitors into ordinary agentTurn jobs that you can edit. On startup, the Gateway no longer reconciles a system-owned monitor from config. To inspect jobs whether enabled or disabled, use openclaw automations list --all. See Heartbeat migration.
The weekly Skill Workshop curator (declaration key skill-collection-review:<agentId>, plus the older skillCollectionReview payload kind) has been retired. When the Gateway loads the cron store it deletes those stored rows and puts nothing in their place; the declaration-key namespace remains reserved. Learned-skill cleanup is now unscheduled; see Unused-skill cleanup.
Agent-turn options
-
--message(string, required), The prompt text an agent-turn job uses, covering main, isolated, current, and custom sessions. -
--model(string), Overrides the model; it has to resolve to a permitted model, otherwise the run fails with a validation error. -
--fallbacks(string), A fallback model list for this job, for example--fallbacks openai/gpt-5.6-sol,openrouter/meta-llama/llama-3.3-70b-instruct:free. For a strict run with no fallbacks, pass--fallbacks "". -
--clear-fallbacks(boolean), When set toautomations edit, drops the job's fallback override so configured fallback precedence applies. Cannot be combined with--fallbacks. -
--clear-model(boolean), When set toautomations edit, drops the job's model override so the usual automation model precedence applies (the stored automation-session override, otherwise the agent/default model). Cannot be combined with--model. -
--thinking(string), Overrides the thinking level (off|minimal|low|medium|high|xhigh|adaptive|max|ultra). Which levels are available still depends on the chosen model and the agent runtime. -
--clear-thinking(boolean), When set toautomations edit, drops the job's thinking override. Cannot be combined with--thinking. -
--light-context(boolean), Skips injection of workspace bootstrap files. -
--skip-if-scratch-empty(boolean), Skips the agent turn when the stored scratch is explicitly empty. A missing scratch still runs. To disable this, use--no-skip-if-scratch-empty. -
--include-reasoning(boolean), Delivers the agent's reasoning together with a meaningful result. Reasoning on its own does not turn a quiet check into a notification. To keep it out of delivery, use--no-include-reasoning. This setting is separate from the model's thinking level. -
--tools(string), Limits the tools available to the job, for example--tools exec,read. An empty allowlist that disables every agent tool, including tools a condition trigger uses, is passed as--tools "".
Any new job that can run tools always stores an explicit tool policy. If a job is created without
--tools (or with *), it stores *: every run applies the owner session's current tool policy,
group, agent, sandbox, and runtime restrictions included. When an agent requests a
finite list, it is capped at the tools its creating turn had and cannot widen the
stored list. Should a requested name, group, or pattern match no captured tool, agent-created
jobs and agent tool-cap edits fail with that entry named in the error rather than saving a partial
list. Codex app tools the creator runtime cannot carry fall under this too. Either use a supported
tool name and runtime, or remove the unavailable entry explicitly.
automations edit --clear-tools restores *. Jobs that existed before an
explicit tool policy keep behaving as they do now until someone explicitly edits their tool policy
or the job is recreated. Agent-created script payloads, condition triggers, and jobs
whose creator captured Codex app authority instead store the creating turn's tools: scripts
reach MCP only through servers named in their list, and app authority is bound to that list.
Older releases saved a copy of the creating turn's tool list on agent-created agent turns.
That copy could lack tools the creator had, the native shell among them. Such jobs now run with
their owner conversation's tools, the same as a * job; the stored copy is left untouched. Jobs whose
creator captured Codex app authority continue to use their copy.
When an account-bound job is changed to a payload that runs no tools and then back to an agent turn, its account restriction survives. Converting the payload does not reauthorize that job as one an operator created.
Doctor verifies scheduled tool authority only for agent turns, script payloads, and jobs that have a condition script. A command payload with no condition script does not require agent-tool provenance; the account restriction it retains is left as is.
Edits made through management cannot restore missing policy metadata as operator authority. Where a legacy job has lost its policy, an authenticated operator may explicitly reauthorize it, or an authenticated creator may recreate it with a new tool cap.
If the creator's exec capability is fixed to the Gateway, the automation keeps that
target as well. Under tools.exec.host: "auto", placement is decided by the saved target.
A current explicit host setting that conflicts, or required sandbox
isolation, blocks the command rather than moving it to a different host. Current tool
and approval policies still apply.
When message is in the tool cap, scheduled agent turns may read messages and channel
information on supported channel plugins with no inbound chat. Jobs created by an operator
use the current operator read policy. Jobs created by an agent keep the creator origin and
account recorded at creation, and the channel's delegated read restrictions still
apply. Read access is not granted by delivery settings.
Scheduled agent turns can inspect their own job and remove it once finished,
even when no interactive sender exists. This self-scoped automations tool grants
no administrator access and no control over other jobs, and explicit tool-policy
denials still apply.
With sessionTarget: "session:<same session key>", an authenticated operator turn can schedule an agentTurn back into the exact
conversation it came from. New
jobs keep the original authenticated source privately, so the continuation can
complete authorized work, such as inspecting and merging that conversation's PR,
with no further message from the operator. On each occurrence the original operator scopes, role, device, access grant, model restrictions, and exact
session identity are revalidated under current policy. The original operator
scope ceiling is preserved; this is neither a new PR-only permission nor a blanket grant to automations.
The stored tool cap, sandbox, and current tool denials still apply. Scheduled
automation management stays self-scoped.
This source is not inferred for existing jobs, guests, isolated/current targets, scripts, or another conversation. An authenticated owner update can bind it again to the updated task. Executable edits made without that authentication discard it. Display-only edits, and disabling or re-enabling the job, preserve the stored source; names, schedules, and other executable inputs stay bound. A fresh owner capture applies only to the definition that was captured, even if another manager edits the job before the update commits. Disabling or removing a job still cancels its active occurrence; re-enabling it does not bring that cancelled occurrence back.
A continuation waits for its current conversation turn to finish before it reads the current job and checks its source at launch. Context supplied by a trigger does not alter that stored definition. Existing stored sources stay valid after an upgrade, including jobs the scheduler disabled. A rejected source is recorded as a terminal failure rather than retrying the same authority error over and over.
While an at agent-turn continuation in an explicitly named conversation waits
for a result, it can call automations with action: "next_check" and in: "3m"
to rearm that same job. No new job is created and its task, target,
and permissions are unchanged. Without a next-check proposal, ordinary one-shot completion and
deleteAfterRun behavior stay the same.
A manual run shares the same scheduled execution context as a timer-triggered run once the request has been admitted. Ending the chat turn or tool call that launched the run does not cause the job to lose its tool access. The job continues to operate under its stored authority and whatever tool restrictions currently apply; launching it by hand does not pass the caller's extra permissions on to the job.
The tool policy in force globally, per agent, per profile, and per provider is evaluated at the start of every new scheduled message invocation. Later invocations pick up configuration changes; an invocation that has already been admitted keeps the configuration it started with. If a job is disabled or removed, its message capability is withdrawn, or its caller or plugin authority is revoked, further affected reads from that occurrence stop, including pending reads that have not yet reached another provider request or result delivery. Turning the job back on does not bring back an occurrence's revoked access.
A new account-bound job created by a verified local administrator keeps that authenticated local source, so provider-permitted reads can go through its saved creator account. When its toolsAllow cap is edited from that same local source, an existing job is explicitly reauthorized. Edits to the description, the display label, or exact no-op changes leave the recorded source intact. Model-facing names, prompts, tools, schedules, and other executable behavior require fresh source authorization, and the old source is cleared when none is supplied. Remote management on its own cannot provide local-source authorization, and older jobs with no provable origin stay blocked until they are reauthorized or recreated from a fresh authorized source.
Scheduled turns are also able to edit, delete, pin, and unpin Discord messages. Jobs created by an agent rely on their recorded creator account and Discord's delegated target restrictions. Jobs created by an operator follow Discord's operator target policy. Trusted operator jobs may additionally use channel-edit, including the existing channel and thread edit options; jobs created by an account do not inherit operator administration.
For these writes, the job requires 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 may use Discord channel-edit when an authenticated Discord turn has authorized their current definition. OpenClaw privately stores that requester's Discord account and sender identity, and the edit must be permitted by Discord's current channel or thread permissions. Neither the original session creator nor a configured OpenClaw owner stands in for those native permissions.
Executable edits made from the job's owning conversation and account bind the job to the current authorized editor. This covers the prompt, model, name, schedule, delivery, and tool policy. An executable edit with no matching authenticated Discord requester clears this permission and halts further native actions from the old occurrence. Changes to the description and display label preserve it.
Older jobs, jobs edited by older writers, and jobs whose requester authorization was cleared all 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 that includes message, or recreate the job there. If its execution authorization is missing as well, recreate it from that conversation; management access alone will not restore the missing authorization. The editor must already hold automation-management access. Other job behavior keeps its existing policy; a CLI edit cannot invent a Discord requester. Public job results omit these requester facts, and no new setting is required.
Channel-name lookup and the write requests that follow retain the current job and plugin authority. Configuration changes take effect on the next message invocation; disabling or narrowing the job itself halts later requests and retries within the current invocation. If authority ends while the response is pending, a confirmed write still returns its result.
Inference account continuity
New isolated agent-turn jobs privately keep their selected stored inference account and a compatible authentication route. OAuth and API keys can stay enabled at the same time: changing interactive defaults, profile order, or the job's plain model selection does not switch the job's account or billing route. Automatic ownership is distinct from an explicit user profile pin. Token refresh within the same authorization is permitted; deleting, replacing, or revoking that authorization stops the job instead of falling back to another account. Model and route compatibility still apply.
At creation, account capture follows scheduled-model selection, including an allowed model@profile value in per-agent or global subagents.model. A disallowed scheduled model falls back without retaining that model's account.
To change an account on purpose, update the job with a model/profile selection, for example --model "openai/gpt-4.1@work". This captures a fresh authorization. For legacy jobs with no recorded inference owner, openclaw doctor --fix records the account the job's next unbound run would use: an explicit selection, or otherwise the first account in the run's normal account order, ignoring temporary rate-limit cooldowns. With auth.order set, that is the account every earlier run used; without it, runs rotated between accounts of the same type by last use, and Doctor records one of them. When several accounts are eligible, Doctor names the others along with the command to change the choice. Doctor uses normal automation model selection, preserves inherited defaults and fallback lists, leaves existing bindings unchanged, and backs up cron state before committing. Missing accounts, and personal accounts that need their owner's authorization, are left unchanged with job-specific adoption instructions.
Managed updates and the standard container entrypoint run repairing Doctor before activation. A manual source upgrade must include openclaw doctor --fix before the Gateway is started. Startup reports host-account jobs that may not be migrated before scheduling; it does not capture credentials or rewrite jobs.
Keys held in the environment or provider config have no stored account to record. A job on such a route stays unbound and runs on that key; once a stored account becomes eligible for its route, the job stops with the adoption instructions rather than switching to that account. Job creation follows the same rule. An account refusal ends the run; it never falls back to another model or provider. Credentialless models remain usable without an account. Native runtime-owned jobs keep their runtime's existing authorization checks, and a native connection cannot silently replace a job's recorded host-managed inference account. An explicit update from an authorized native creator can adopt its runtime authority. Moving a job to an agent with a different credential owner requires explicit account adoption. Tool and delivery accounts remain separate from the inference account.
--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.
Choose the model for the job's difficulty, not for the agent's default. Routine automation, such as summaries, triage, classification, and status checks, runs well on a lighter model, which is cheaper and faster per run and adds up over a schedule. Reserve 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:
- Per-job payload
model(explicit config; a disallowed model fails the run) - Gmail hook model override (only when the run came from Gmail and that override is allowed)
- User-selected stored automation-session model override
- Agent/default model selection
A stored session model picked by the user counts as an exact choice, per selection source policy: when it fails, the run reports that failure rather than falling back to configured defaults. This holds for an agent turn in a main or custom (session:<key>) session, and for a main-session system event, whenever the user chose that session's model. Per-job --fallbacks still apply.
Fast mode tracks whichever live selection gets resolved. For isolated automation the resolution order is: stored session fastMode, then per-agent agents.entries.*.fastModeDefault, then global agents.defaults.fastModeDefault, then selected-model params.fastMode. Auto mode relies on the model's params.fastAutoOnSeconds cutoff, which defaults to 60 seconds.
If a runtime reports token usage but no cost, automation estimates draw on the selected agent's local models.json pricing plus the model metadata kept for that run.
When a run encounters a live model-switch handoff, the scheduler retries against the switched provider/model and stores that model choice for the active run. A job that has a recorded inference account keeps that account and its compatible authentication route; a switch is not allowed to take on a different account. Retry counts are limited: once the initial attempt and 2 switch retries are used up, the scheduler aborts rather than looping.
Prior to an isolated run starting, OpenClaw probes reachable local endpoints for configured api: "ollama" and api: "openai-completions" providers whose baseUrl is loopback, private-network, or .local. This preflight follows the job's configured fallback chain, and the run is marked skipped only after every candidate proves unreachable; --fallbacks "" restricts that walk to the primary model alone, and a user-selected stored session model likewise restricts it to that one model. If an endpoint is down, the run is recorded as skipped with a clear error rather than a model call being started. Results are cached for 5 minutes per endpoint (not per job or model), so many due jobs that share a dead local Ollama/vLLM/SGLang/LM Studio server cost one check rather than a request storm. Runs skipped by preflight do not increment execution-error backoff. They follow the existing failure-alert policy without needing failureAlert.includeSkipped; recurring jobs stay enabled and recover on their own once a later preflight finds the provider reachable.
Timeouts from the client-side preflight are never cached. Rather than inheriting a timeout from another run, the next scheduled run checks the endpoint again.
The local check opens a TCP connection and closes it, sending no HTTP requests and no provider credentials, so authenticated local servers do not log spurious /models authorization failures. TLS, authentication, and model errors fall to inference. For endpoints routed through a managed proxy, connectivity checks are deferred to inference instead of testing a direct connection.
Job scratch and quiet results
Every job may hold private task context in scratch, stored in the shared state database and capped at 256 KiB. Any scratch that exists is injected into the job's bounded run context. It is left out of job lists, full job definitions, and run-history responses.
Warning
Never place API keys, tokens, or other secrets in scratch. Even though it is left out of job-list and history responses, it still becomes model prompt context.
openclaw automations scratch <job-id> --set "Check only for newly blocked work."
openclaw automations scratch <job-id> --json
Scratch updates rely on revision compare-and-swap. The CLI reads the current revision before it writes; --expected-revision <n> pins a known revision. Inside an automation turn, the automations tool offers self-scoped scratch_get, scratch_set, and record_result actions. Those actions give no access to another job's scratch or settings.
scratch_get returns both the content and the current revision. scratch_set swaps in completely new content, or wipes it via null, and needs expectedRevision from that read. If the prompt indicates scratch was shortened, reread the full content before replacing it. When a revision conflict occurs, read again and reconcile the content rather than overwriting someone else's edit.
For a visible result, use a normal final reply; for silence, use NO_REPLY. record_result takes a single outcome (no_change, progress, done, blocked, or needs_attention) plus a nonempty summary of at most 2000 characters. It logs the result but sends no notification on its own. Meaningful outcomes stay in ordinary run history and bounded session context, even when the final reply is silent; this is not a delivery retry queue. no_change keeps runner delivery silent while execution failures remain visible. On a paced job, adaptive scheduling still uses next_check. Scratch is context only, not a second scheduler: runtime neither parses tasks: blocks nor reads HEARTBEAT.md.
Under payload.skipIfScratchEmpty: true (--skip-if-scratch-empty), blank text, comments, headings, fence markers, and empty checklist stubs all count as an empty checklist. Deleting scratch with --unset works differently: a missing scratch does not suppress a run. If the job should stop no matter what, disable it.
Command payloads
Command payloads execute scripts inside the Gateway scheduler without launching a model-backed turn. They run 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 that agent-turn jobs use.
Note
When an agent-turn automation's exec needs approval, the card goes 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 belong to the operator-admin Gateway automation surface, not to an agent
tools.execcall. Creating, updating, removing, or manually running automation jobs requiresoperator.admin; scheduled command runs then 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> holds argv: ["sh", "-lc", <shell>]. For exact argv execution with no shell parsing, use --command-argv '["node","scripts/report.mjs"]'. The process environment, stdin, and output bounds are governed by the optional --command-env KEY=VALUE (which may be repeated), --command-input, --timeout-seconds (10 minutes by default), --no-output-timeout-seconds, and --output-max-bytes.
What gets delivered comes from the process output: non-empty stdout takes precedence; when stdout is empty but stderr is not, stderr is what gets delivered; and when both are present, a small stdout: / stderr: block is sent by the scheduler. The run ok is recorded by exit code 0; a non-zero exit, a signal, a timeout, or a no-output timeout records error and may fire failure alerts. If a command prints only NO_REPLY, the usual automation silent-token suppression applies and nothing is posted back to chat.
Should the run deadline halt a command, its captured output and command timeout reason are kept in run history once bounded process cleanup finishes. After that deadline, completion delivery does not begin.
Script payloads
Script payloads execute headlessly in the same code-mode executor used by trigger scripts, and no conversational agent turn is started. They are on by default; creation and execution of script payloads, along with condition-trigger scripts and stream schedules, are disabled when cron.triggers.enabled: false is set. Only main and isolated session targets are supported for script jobs.
The only automations actions a script receives are self-scoped ones (status, list, get, remove, runs, and next_check); add, update, run, and wake are not available. If you need to resume a conversation later, schedule an agentTurn instead.
openclaw automations create "0 * * * *" \
--name "Hourly queue check" \
--script ./automation/check-queue.js \
--script-timeout-seconds 300 \
--script-tool-budget 50 \
--session isolated \
--announce
Reading JavaScript from a file or stdin is done with --script <file|->. Leading and trailing spaces in file paths are preserved by the CLI, so quote the path as a single shell argument. Timeout defaults to 300 seconds, capped at 900; the tool budget defaults to 50 calls, capped at 200. These payload budgets are distinct from the smaller budgets used for trigger-gate evaluation.
As with interactive Code Mode, script payloads may call configured MCP server tools as MCP.<server>.<tool>({ ...input }). MCP is opt-in per server: each server must be named in the job's toolsAllow (--tools) using either an exact tool such as wispr-flow__search_meetings or a server-scoped glob such as wispr-flow__*. No server starts when you supply a wildcard *, omit toolsAllow, use a glob without a server prefix, or write a script that never mentions MCP. The owning agent's tool policy still applies inside a named server. Every run spins up its own runtime for the named servers, connection time counts against the script timeout and each call counts against the tool budget, and the runtime is retired when the run ends. A named server that fails to start is missing from MCP; should the script then fail, the run error closes with MCP server "<name>" is unavailable: <reason>. Shared details are in Event triggers.
The script may return an object with these optional fields:
notify: Text delivered through the job'sannounce,webhook, ornonedelivery mode. Nothing is delivered if it is omitted. For amainjob, the text becomes a system event.wake:"now"requests immediate session processing ofnotify(or a compact completion event). The legacy"next-heartbeat"value assigns the notice to an eligible scheduled automation; a missing target is reported.state: JSON state, capped at 16 KB and persisted only after a successful run. The next run receives a frozen copy astrigger.state, matching trigger scripts. Since 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". Valid only for jobs with pacing enabled, and it 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, and returned state is not persisted.
Cached script preparation is invalidated by plugin reloads. If a plugin retires during setup, OpenClaw refreshes the tools once before starting the script, within the original deadline. This setup retry is never triggered by a failure after the script starts. When the refresh fails, run history and failure alerts explain that automatic setup recovery failed and the script did not run.
If a running job's script payload or saved state is changed, that edit is protected 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
Every fire of a recurring job re-runs the same instructions, so whatever the model works out from scratch costs the same time and tokens each run. Reserve 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
execcall. - 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
toolsAllowto 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
toolsAllownames it (<server>__<tool>or<server>__*). Triggers and script payloads are unavailable whencron.triggers.enabledisfalse. - 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
Automations built by Codex may keep the app IDs and permission ceiling that the authenticated creator thread had. When the job runs, OpenClaw needs that same prepared Codex profile and account, then trims the stored cap to match current app policy. If apps were revoked, if the account or runtime changed, or if interactive approval is required, execution halts with a recovery message; it never falls back to wider or different credentials. Older jobs that never captured an app envelope keep their usual non-app behavior; recreate or reauthorize such a job only when it needs Codex app access. See Native Codex plugins.
| Style | --session value | Runs in | Best for |
|---|---|---|---|
| Main session | main | Owning agent's main session | Reminders, system events |
| Isolated | isolated | Dedicated cron:<jobId> | Reports, background chores |
| Current session | current | Detached; commits to the creation-bound conversation | Context-aware recurring work |
| Custom session | session:custom-id | Persistent named session | Workflows that build on history |
When the create request includes session context, agent-turn jobs default to the conversation that created them. Callers that pass no session key, such as CLI and API callers without one, use isolated instead. System events fall back to main; command and script payloads still fall back to isolated.
With announce, results from agent, command, and script jobs go to whichever chat or topic receives them. If a different delivery destination is set, that destination gets the result rather than the creating conversation; when no external route exists, the creating conversation receives it. An isolated run still does not read that conversation's history. See Automation delivery for generation checks and duplicate prevention.
Main session vs current vs isolated vs custom
Main session jobs push their system event or agent-turn payload through the owning agent’s normal session queue, carrying that session’s existing context and delivery context. The automation keeps running until the turn settles; being accepted into the queue alone is not success. Internal automation turns do not refresh daily or idle reset freshness; session freshness moves only on visible user activity. Current-session jobs execute in a detached run session, read a bounded tail of the conversation as captured at job creation, and deliver the final visible assistant result to the resolved destination (the creating conversation when no external route is configured). Isolated jobs run a dedicated agent turn with a fresh session. Custom sessions (session:xxx) keep context from one run to the next, which supports workflows like daily standups that build on earlier summaries.
current binds conversation context, not the original agent execution or its worktree; announce results belong to the resolved delivery destination. The detached run has its own session identity and captured tool restrictions. A current or isolated job linked to the conversation that created it works in that conversation's saved workspace and working directory while the conversation is current, at the workspace root rather than a subdirectory, and keeps the conversation's required sandbox. An unlinked job, or one whose conversation was reset, uses the scheduled agent's workspace. A job whose conversation was removed or archived, or whose bound worktree is gone, pauses instead of running. Resetting the conversation during a run ends the run: OpenClaw tools refuse further effects, and a CLI backend's process is stopped so its own file tools cannot keep writing to the workspace. 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 enter the session's ordinary turn queue and wait for active work before preparing context, so a scheduled tick cannot invalidate an in-progress compaction. The automation keeps running until that turn settles; queue acceptance alone does not count as success. Saved authenticated continuations retain their original source and its current permissions through execution and delivery.
To come back to this conversation later (for example, to recheck CI), add a one-shot at job with payload: { kind: "agentTurn", message: "Instructions for your next turn" } and sessionTarget: "session:<your session key from Runtime>". It runs inside the existing conversation with the same history and saved workspace/worktree.
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; other detached runs inherit it only from a current creating conversation, as described for current jobs above. 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 reminders. They include their own job scratch and notices assigned to that occurrence, not another monitor’s checklist or unrelated queued events. Put required instructions in the job payload or scratch.
Main-session agent-turn jobs support ordinary announce delivery, including an owner target. Main-session system-event and script jobs cannot use a separate chat announce target; edits that enable it are rejected without changing the job. 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 explains what failed and what it tried in ordinary prose.
A completed model run is not proof that the requested task succeeded. The scheduler does not classify assistant prose as an execution error: a blocker report remains ordinary output, including a subagent's settled final answer. It follows the job's delivery policy and does not itself trigger retries, error backoff, failure alerts, or owner-conversation repair. Runtime failures, such as provider errors or execution timeouts, still fail the run and use the normal scheduler failure policy. Required delivery failures are tracked separately; see Failure notifications.
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
Child completion does not resume an isolated automation turn. If the orchestrator must act on child results (for example, integrate or verify their work), it must spawn with collect: true and collect the results with agents_wait before ending its turn; fire-and-forget delegation is valid when the child output itself is the deliverable.
When isolated automation runs coordinate subagents, the final descendant output is preferred for delivery over interim text from a stale parent. Should descendant tasks still be running or settling, OpenClaw holds back that partial parent update rather than announcing it. This covers a yielded orchestrator that is waiting for its successor to start, as well as completed descendants whose result delivery is still pending. That wait uses the existing run deadline and ends on cancellation. If a delivery.mode: "none" run's turn only handed work off to a child, the run waits for that child under the same deadline and records the child's final reply as the run output without sending it. A meaningful result or a concrete blocker must come back from subagents, even when delivery is none. A child returning only NO_REPLY goes into missing-answer recovery; should it still yield no result or time out, the automation fails.
For Discord announce targets that are text-only, OpenClaw transmits the final assistant text a single time rather than replaying both the streamed/intermediate text and the final answer. Discord payloads that carry media or structured content are still delivered on their own, so attachments and components are not lost.