docs/cli/agent.md
openclaw agentRun one agent turn through the Gateway. Falls back to the embedded agent if the Gateway request fails; pass --local to force embedded execution up front.
Pass at least one session selector: --to, --session-key, --session-id, or --agent.
Related: Agent send tool
-m, --message <text>: message body--message-file <path>: read the message body from a UTF-8 file-t, --to <dest>: recipient used to derive the session key--session-key <key>: explicit session key to use for routing--session-id <id>: explicit session id--agent <id>: agent id; overrides routing bindings--model <id>: model override for this run (provider/model or model id)--thinking <level>: agent thinking level (off, minimal, low, medium, high, plus provider-supported custom levels such as xhigh, adaptive, or max)--verbose <on|off>: persist verbose level for the session--channel <channel>: delivery channel; omit to use the main session channel--reply-to <target>: delivery target override--reply-channel <channel>: delivery channel override--reply-account <id>: delivery account override--local: run the embedded agent directly (after plugin registry preload)--deliver: send the reply back to the selected channel/target--timeout <seconds>: override agent timeout (default 600, or agents.defaults.timeoutSeconds); 0 disables the timeout--json: output JSONopenclaw agent --to +15555550123 --message "status update" --deliver
openclaw agent --agent ops --message "Summarize logs"
openclaw agent --agent ops --message-file ./task.md
openclaw agent --agent ops --model openai/gpt-5.4 --message "Summarize logs"
openclaw agent --session-key agent:ops:incident-42 --message "Summarize status"
openclaw agent --agent ops --session-key incident-42 --message "Summarize status"
openclaw agent --session-id 1234 --message "Summarize inbox" --thinking medium
openclaw agent --to +15555550123 --message "Trace logs" --verbose on --json
openclaw agent --agent ops --message "Generate report" --deliver --reply-channel slack --reply-to "#reports"
openclaw agent --agent ops --message "Run locally" --local
--message or --message-file. --message-file strips a leading UTF-8 BOM and preserves multiline content; it rejects files that are not valid UTF-8./compact) cannot run through --message. The CLI rejects them and points you at the first-class command instead (openclaw sessions compact <key> for compaction).--local and embedded fallback runs are one-shot: bundled MCP loopback resources and warm Claude stdio sessions opened for the run are retired after the reply, so scripted invocations do not leave local child processes running. Gateway-backed runs keep Gateway-owned MCP loopback resources under the running Gateway process instead.--agent, --channel and --to together, session routing follows the channel's canonical recipient and session.dmScope. Channels with a stable outbound-only recipient identity use a provider-owned session isolated from the agent's main session. --reply-channel and --reply-account affect delivery only.--session-key selects an explicit session key. Agent-prefixed keys must use agent:<agent-id>:<session-key>, and --agent must match the key's agent id when both are given. Bare non-sentinel keys scope to --agent when supplied, or to the configured default agent otherwise; for example --agent ops --session-key incident-42 routes to agent:ops:incident-42. The literal keys global and unknown stay unscoped only when no --agent is supplied.--json reserves stdout for the JSON response; Gateway, plugin, and embedded-fallback diagnostics go to stderr so scripts can parse stdout directly.meta.transport: "embedded" and meta.fallbackFrom: "gateway" so scripts can detect a fallback run.gateway-fallback-* session/run id and reports meta.fallbackReason: "gateway_timeout" plus the fallback session fields, instead of racing the Gateway-owned transcript or silently replacing the original session.SIGTERM/SIGINT interrupt a waiting Gateway-backed request; if the Gateway already accepted the run, the CLI also sends chat.abort for that run id before exiting. --local and embedded fallback runs receive the same signal but do not send chat.abort. If the internal run-dedup key already has an active run for this session, the response reports status: "in_flight" and the non-JSON CLI prints a stderr diagnostic instead of an empty reply. For external cron/systemd wrappers, keep a hard-kill backstop such as timeout -k 60 600 openclaw agent ... so the supervisor can reap the process if shutdown cannot drain.models.json regeneration, SecretRef-managed provider credentials are persisted as non-secret markers (for example env var names, secretref-env:ENV_VAR_NAME, or secretref-managed), never resolved secret plaintext. Marker writes come from the active source config snapshot, not from resolved runtime secret values.With --json --deliver, the CLI JSON response includes top-level deliveryStatus so scripts can distinguish delivered, suppressed, partial, and failed sends:
{
"payloads": [{ "text": "Report ready", "mediaUrl": null }],
"meta": { "durationMs": 1200 },
"deliveryStatus": {
"requested": true,
"attempted": true,
"status": "sent",
"succeeded": true,
"resultCount": 1
}
}
Gateway-backed CLI responses also preserve the raw Gateway result shape at result.deliveryStatus.
deliveryStatus.status is one of:
| Status | Meaning |
|---|---|
sent | Delivery completed. |
suppressed | Delivery was intentionally not sent (for example a message-sending hook cancelled it, or there was no visible result). Terminal, no retry. |
partial_failed | At least one payload sent before a later payload failed. |
failed | No durable send completed, or delivery preflight failed. |
Common fields:
requested: always true when the object is present.attempted: true once the durable send path ran; false for preflight failures or no visible payloads.succeeded: true, false, or "partial"; "partial" pairs with status: "partial_failed".reason: lowercase snake-case reason from durable delivery or preflight validation. Known values include cancelled_by_message_sending_hook, no_visible_payload, no_visible_result, channel_resolved_to_internal, unknown_channel, invalid_delivery_target, and no_delivery_target; failed durable sends may also report the failed stage. Treat unknown values as opaque since the set can expand.resultCount: number of channel send results, when available.sentBeforeError: true when a partial failure sent at least one payload before erroring.error: true for failed or partial-failed sends.errorMessage: present only when an underlying delivery error message was captured. Preflight failures carry error/reason but no errorMessage.payloadOutcomes: optional per-payload results with index, status, reason, resultCount, error, stage, sentBeforeError, or hook metadata when available.