Background Exec and Process Management in OpenClaw

Learn how OpenClaw executes shell commands with the exec tool and manages long-running background sessions using the process tool. Essential for developers automating complex workflows.

Read this when

  • Adding or modifying background exec behavior
  • Debugging long-running exec tasks

OpenClaw executes shell commands via the exec tool, with long-running operations retained in memory. Oversight of those background sessions falls to the process tool.

exec tool

Parameters:

ParameterDescription
commandMandatory. The shell command to execute.
workdirDirectory for execution; when omitted, the default cwd applies.
envSupplemental environment variables passed to the command.
yieldMsDelay in milliseconds before the process is backgrounded, with 10000 as the default.
backgroundForces immediate background execution.
timeoutSecondsTimeout measured in seconds, defaulting to tools.exec.timeoutSeconds; upon expiry the process is terminated. Passing timeoutSeconds: 0 turns off the exec process timeout for that invocation.
ptyUses a pseudo-terminal when one is available, which suits TTY-dependent CLIs and coding agents.
elevatedExecutes beyond the sandbox when elevated mode is permitted, with gateway as the default, or node when the exec target is node.
hostDesignates the exec target among auto, sandbox, gateway, or node.
nodeNode identifier or name, applied together with host: "node".

Behavior:

  • Directly returned output accompanies foreground runs, and notification occurs when earlier output surpassed the combined cap.
  • Once backgrounded, whether explicitly or through the yieldMs timeout, the tool responds with status: "running" plus sessionId along with a brief output excerpt.
  • Runs that are backgrounded or use yieldMs pick up tools.exec.timeoutSeconds unless an explicit timeoutSeconds is supplied in the call.
  • Until the session is polled or cleared, output remains in memory, bounded by the per-session aggregate cap.
  • Finished sessions lapse once their configured TTL passes. The registry keeps at most 50 completed sessions and 2,000,000 characters of retained output in total, with the oldest entries removed first. Even when the newest finished session alone exceeds the global limit, its capped per-session aggregate is preserved.
  • When the process tool is blocked, exec runs in sync mode and disregards yieldMs and background.
  • For context-aware shell and profile rules, spawned exec commands are given OPENCLAW_SHELL=exec.
  • For work that should begin immediately and run long: launch it once, and if enabled, automatic completion wake handles the finish once the command produces output or errors out.
  • When automatic completion wake is not an option, or a quiet-success confirmation is needed for a command that ends cleanly without output, use process for polling.
  • Avoid using sleep loops or repeated polling to mimic reminders or postponed follow-ups; cron is the right tool for future work.

Env overrides

VariableEffect
OPENCLAW_BASH_YIELD_MSDefault pre-background delay in milliseconds. Defaults to 10000, with a clamp range of 10 to 120000.
OPENCLAW_BASH_MAX_OUTPUT_CHARSIn-memory aggregate cap measured in characters. Defaults to 200000, clamped between 1000 and 200000.
OPENCLAW_BASH_PENDING_MAX_OUTPUT_CHARSCap on pending stdout/stderr per stream. Defaults to 30000, clamped to 1000-200000 and constrained by the aggregate cap.
OPENCLAW_BASH_JOB_TTL_MSTTL for completed sessions in milliseconds, limited to a 1 minute to 3 hour span.
OPENCLAW_PROCESS_INPUT_WAIT_IDLE_MSIdle-output threshold that flags writable background sessions as likely awaiting input. Defaults to 15000.

Config (preferred over env overrides)

KeyDefaultEffect
tools.exec.backgroundMs10000Equivalent to OPENCLAW_BASH_YIELD_MS.
tools.exec.timeoutSeconds1800Timeout applied per call by default.
tools.exec.cleanupMs1800000Matches OPENCLAW_BASH_JOB_TTL_MS.
tools.exec.notifyOnExittrueQueues a system event and requests a heartbeat when a backgrounded exec terminates.
tools.exec.notifyOnExitEmptySuccessfalseAlso queues completion events for successful backgrounded runs that produce no output.

Child process bridging

For long-running child processes launched outside the exec/process tools, such as CLI respawns or gateway helpers, attach the child-process bridge helper so termination signals propagate and listeners detach on exit or close. This prevents orphaned processes under systemd and keeps shutdown behavior uniform across platforms.

process tool

Actions:

ActionEffect
listSessions that are running or have completed.
pollPull fresh output for a session, including its exit code.
logFetch combined output along with input-recovery guidance. Works with offset and limit.
writeProvide stdin (data, with eof being optional).
send-keysDeliver explicit key tokens or raw bytes to a session backed by a PTY.
submitSubmit Enter or a carriage return to a PTY-backed session.
pasteSend plain text, optionally using bracketed paste mode.
killStop a background session.
clearDrop a completed session from memory.
removeStop it if active, otherwise wipe it if done.

Notes:

  • Only sessions launched in the background are tracked and retained, and that retention is memory-only, never disk-based. Any process restart wipes them.
  • Resetting or deleting a session affects solely its own finished background processes; other sessions, explicit shared scopes, and active processes stay untouched.
  • While a background session is alive, cooperative host suspension and a safe Gateway restart are blocked until the process owner confirms the process has truly exited.
  • process remove can hide a running session right after a termination request; suspension and restart stay blocked until exit confirmation arrives.
  • Session logs appear in chat history only when you invoke process poll/log and the tool result gets stored.
  • process is agent-scoped, so it sees only sessions that same agent initiated.
  • For status, logs, or completion confirmation when automatic completion wake is unavailable, turn to poll/log.
  • Before restoring an interactive CLI, run log so the current transcript, stdin state, and input-wait hint appear together.
  • When input or intervention is needed, rely on write/send-keys/submit/paste/kill.
  • process list provides a derived name (command verb plus target) to make quick scans easier.
  • process list, poll, and log surface waitingForInput only when the session still has writable stdin and has sat idle beyond the input-wait threshold (15000 ms by default, OPENCLAW_PROCESS_INPUT_WAIT_IDLE_MS).
  • process log relies on line-based offset/limit. If neither is given, it returns the last 200 lines with a paging hint. When offset is present but limit is absent, it returns from offset to the end, with no 200-line cap.
  • process poll and process log tell apart output dropped at the aggregate retention cap from output merely skipped by the pending buffer or retained tail. Dropped output is unrecoverable; paged logs can only examine the retained portion.
  • poll's timeout waits up to that many milliseconds before responding; anything above 30000 gets clamped to 30000.
  • Polling is meant for on-demand status checks, not as a wait-loop scheduler. For deferred work, use cron.

Examples

Run a lengthy task, then check on it later:

{ "tool": "exec", "command": "sleep 5 && echo done", "yieldMs": 1000 }
{ "tool": "process", "action": "poll", "sessionId": "<id>" }

Look at an interactive session before sending anything:

{ "tool": "process", "action": "log", "sessionId": "<id>" }

Launch directly in the background:

{ "tool": "exec", "command": "npm run build", "background": true }

Feed stdin:

{ "tool": "process", "action": "write", "sessionId": "<id>", "data": "y\n" }

Send PTY keys:

{ "tool": "process", "action": "send-keys", "sessionId": "<id>", "keys": ["C-c"] }

Submit the current line:

{ "tool": "process", "action": "submit", "sessionId": "<id>" }

Paste literal text:

{ "tool": "process", "action": "paste", "sessionId": "<id>", "text": "line1\nline2\n" }
1,288 words · updated Aug 24, 2026