OpenClaw System Prompt Assembly and Provider Customization

This page explains how OpenClaw generates its system prompt in three layers and how provider plugins can customize core sections. It is for developers integrating or debugging agent prompts.

Read this when

  • Editing system prompt text, tools list, or temporal sections
  • Changing workspace bootstrap or skills injection behavior

OpenClaw generates its own system prompt for each agent execution; no default prompt exists at runtime.

The assembly process is structured in three layers:

  • buildAgentSystemPrompt produces the prompt from explicit inputs. It functions purely as a renderer and never accesses global config directly.
  • resolveAgentSystemPromptConfig handles config-backed prompt settings (owner display, TTS hints, model aliases, memory citation mode, sub-agent delegation mode) for a given agent.
  • Runtime adapters (embedded, CLI, command/export previews, compaction) collect live facts (tools, sandbox state, channel capabilities, context files, provider prompt contributions) and invoke the configured prompt facade.

This approach keeps exported and debug prompt surfaces in sync with live runs without consolidating every runtime detail into a single monolithic builder.

Provider plugins can add cache-aware guidance without supplanting the OpenClaw-owned prompt. A provider runtime can:

  • swap out one of three named core sections: interaction_style, tool_call_style, execution_bias
  • place a stable prefix above the prompt cache boundary
  • place a dynamic suffix below the prompt cache boundary

Reserve provider-owned contributions for model-family-specific tuning. Keep the legacy before_prompt_build hook for compatibility or genuinely global prompt changes.

The built-in GPT-5-family prompt contribution (resolveGpt5SystemPromptContribution) leverages this mechanism: a stablePrefix behavior contract (execution policy, tool discipline, output contract, completion contract) plus an optional interaction_style override for a more approachable tone. For OpenAI-family routes, plugins.entries.openai.config.personality governs that style layer: "friendly" serves as the default, "on" points to "friendly", and "off" strips only the friendly override; the stable behavior contract stays intact.

Structure

The prompt remains concise with fixed sections:

  • Tooling: a reminder of the structured-tool source of truth plus runtime tool-use guidance. When progress_card is active (tools.updatePlan, enabled by default), its own description covers maintaining one durable plan and status note, keeping at most one step in_progress, and skipping routine updates that don't alter the situation.
  • Execution Bias: act on actionable requests within the turn, continue until finished or blocked, recover from weak tool results, verify mutable state live, and confirm before finalizing.
  • Promised Work: promising future, background, delegated, or continued work creates follow-through ownership: set up a push-based completion or watch path before ending the turn, proactively return with the result or a concrete blocker, and never treat progress (like running) as completion.
  • Safety: a brief guardrail reminder against power-seeking behavior or bypassing oversight.
  • Skills (when available): instructs the model on loading skill instructions on demand.
  • OpenClaw Control: favor the gateway tool for config/restart tasks; don't invent CLI commands.
  • OpenClaw Self-Update: inspect config safely with config.schema.lookup, patch with config.patch, replace the full config with config.apply, and run update.run only when the user explicitly asks. The agent-facing gateway tool refuses to rewrite tools.exec.mode.
  • Workspace: working directory (agents.defaults.workspace).
  • Documentation: local docs/source path and when to consult them.
  • Workspace Files (injected): notes that bootstrap files appear below.
  • Sandbox (when enabled): sandboxed runtime, sandbox paths, elevated-exec availability.
  • Temporal Context: local date and time zone below the cache boundary; exact time comes from session_status when available.
  • Assistant Output Directives: compact attachment, voice-note, and reply-tag syntax.
  • Collapsible Details (when supported): teaches the model to keep optional depth in <details> disclosures while keeping the primary answer and required actions visible.
  • Heartbeats: heartbeat prompt and ack behavior, when heartbeats are enabled for the default agent.
  • Runtime: host, OS, node, model, repo root (when detected), thinking level (one line).
  • Reasoning: current visibility level plus the /reasoning toggle hint.

Large stable content (including Project Context) sits above the internal prompt cache boundary. Volatile per-turn sections (Control UI embed guidance, Messaging, Collapsible Details, Voice, Group Chat Context, Reactions, Heartbeats, Runtime) are appended below that boundary so local backends with prefix caches can reuse the stable workspace prefix across channel turns. The boundary is internal transport metadata: every section remains system-prompt guidance for CLI backends. Tool descriptions should avoid embedding current channel names when the accepted schema already carries that runtime detail.

Tooling also carries long-running-work guidance:

  • use cron for future follow-up (check back later, reminders, recurring work) instead of exec sleep loops, yieldMs delay tricks, or repeated process polling
  • use exec / process only for commands that start now and continue in the background
  • when automatic completion wake is enabled, start the command once and rely on the push-based wake path
  • use process for logs, status, input, or intervention on a running command
  • for larger tasks, prefer sessions_spawn; sub-agent completion is push-based and auto-announces back to the requester
  • do not poll subagents list / sessions_list in a loop just to wait for completion

agents.defaults.subagents.delegationMode can reinforce this. With no explicit setting, OpenClaw uses "prefer" in each agent's main session and "suggest" elsewhere; an explicit default or per-agent override always wins. "prefer" adds a dedicated Delegation section telling the agent to stay responsive, use hidden sub-agents for internal legwork, and use visible sidebar sessions for work the user will follow or return to. This is prompt-only; tool policy still controls whether sessions_spawn is available.

At the ultra thinking level, a Proactive Sub-Agent Orchestration section is also added when sessions_spawn is available: it tells the model to parallelize independent investigation, implementation, and verification through sub-agents, keep simple or tightly coupled work local, give each sub-agent a bounded objective, and synthesize results before replying.

Safety guardrails in the system prompt are advisory, not enforcement. Use tool policy, exec approvals, sandboxing, and channel allowlists for hard enforcement; operators can disable prompt guardrails by design.

On channels with native approval cards/buttons, the prompt tells the agent to rely on that UI first, and to include a manual /approve command only when the tool result says chat approvals are unavailable or manual approval is the only path.

Prompt modes

OpenClaw renders smaller system prompts for sub-agents. The runtime sets a promptMode per run (not user-facing config):

  • full (default): all sections above.
  • minimal: used for sub-agents; omits the memory prompt section (bundled as Memory Recall), OpenClaw Self-Update, Model Aliases, User Identity, Assistant Output Directives, Messaging, Collapsible Details, Silent Replies, and Heartbeats. Tooling, Safety, Skills (when supplied), Workspace, Sandbox, Current Date & Time (when known), Runtime, and injected context stay available.
  • none: returns only the base identity line.

Under promptMode=minimal, extra injected prompts are labeled Subagent Context instead of Group Chat Context.

For channel auto-reply runs, OpenClaw omits the generic Silent Replies section when direct, group, or message-tool-only context already owns the visible-reply contract. Only legacy automatic group/channel mode shows NO_REPLY; direct chats and message-tool-only replies skip silent-token guidance.

Prompt snapshots

OpenClaw keeps committed prompt snapshots for the Codex runtime happy path under test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/. They render selected app-server thread/turn params plus a reconstructed model-bound prompt layer stack for Telegram direct, Discord group, and heartbeat turns: a pinned Codex gpt-5.5 model prompt fixture, the Codex happy-path permission developer text, OpenClaw developer instructions, turn-scoped collaboration-mode instructions when OpenClaw provides them, user turn input, and references to dynamic tool specs.

Refresh the pinned Codex model prompt fixture with pnpm prompt:snapshots:sync-codex-model. Its default lookup order is $CODEX_HOME/models_cache.json, then ~/.codex/models_cache.json, then the maintainer checkout convention ~/code/codex/codex-rs/models-manager/models.json; if none of those are present, the process exits without touching the committed fixture. To refresh from a specific models_cache.json or models.json file, pass --catalog <path>.

These snapshots are not a byte-for-byte capture of the raw OpenAI request. After OpenClaw sends thread and turn parameters, Codex may append runtime-owned workspace context (AGENTS.md, environment context, memories, app/plugin instructions, built-in Default collaboration-mode instructions).

Regenerate with pnpm prompt:snapshots:gen; check for drift with pnpm prompt:snapshots:check. CI runs the drift check together with the additional-boundary shards, so prompt changes and snapshot updates land in the same PR.

Workspace bootstrap injection

The configured agent workspace determines agent identity, instructions, and memory, which are then routed to the prompt surface that matches their lifetime. When a session runs from another folder or managed worktree, that folder stays the execution workspace. Its AGENTS.md is appended after the configured workspace files as project context; OpenClaw does not load SOUL.md, IDENTITY.md, USER.md, MEMORY.md, or BOOTSTRAP.md from the execution folder.

  • AGENTS.md
  • SOUL.md
  • IDENTITY.md
  • USER.md
  • BOOTSTRAP.md (only on brand-new workspaces)
  • MEMORY.md when present

On the native Codex harness, OpenClaw does not repeat stable workspace files in every user turn. Codex loads the execution folder's AGENTS.md, including its ## Tools section, through native project-doc discovery, so OpenClaw does not inject that file again. When execution uses another folder, OpenClaw adds the configured agent workspace's bounded AGENTS.md snapshot to the thread-level developer instructions so native Codex sub-agents inherit it. SOUL.md, IDENTITY.md, and USER.md remain turn-scoped collaboration developer instructions and intentionally do not flow to native sub-agents. MEMORY.md content is not pasted into every native Codex turn either: when memory tools are available for the agent workspace, Codex turns get a small workspace-memory note directing the model to memory_search or memory_get. If tools are disabled or memory search is unavailable, MEMORY.md falls back to the normal bounded turn-context path. BOOTSTRAP.md keeps the normal turn-context role.

Heartbeat monitor scratch is not a bootstrap file. The heartbeat runner appends it only to heartbeat turns; normal turns do not receive it. The default agent's system prompt automatically includes heartbeat guidance while its cadence is enabled, with no independent heartbeat setting to hide that section.

On non-Codex harnesses, the remaining bootstrap files compose into the OpenClaw prompt per their existing gates. Keep injected files concise, especially non-Codex MEMORY.md: it should stay a curated long-term summary, with detailed daily notes in memory/*.md retrievable on demand via memory_search / memory_get. Oversized non-Codex MEMORY.md files increase prompt usage and can be partially injected under the bootstrap file limits below.

Note

memory/*.md daily files are not part of the normal bootstrap Project Context. On ordinary turns they are accessed on demand via memory_search / memory_get, so they do not count against the context window unless the model explicitly reads them. Bare /new and /reset turns are the exception: the runtime can prepend recent daily memory as a one-shot startup-context block for that first turn.

Large files are truncated with a marker:

LimitConfig keyDefault
Per-file max charactersagents.defaults.bootstrapMaxChars20000
Total across all filesagents.defaults.bootstrapTotalMaxChars60000

When truncation happens, OpenClaw always injects a concise notice into the system prompt saying some bootstrap files were truncated and to read the affected files directly; this notice is built in and not configurable, and it deliberately omits per-file details. Missing files inject a short missing-file marker. File names and raw/injected counts stay in diagnostics such as /context, /status, doctor, and logs.

For memory files, truncation is not data loss: the file stays intact on disk. On native Codex, MEMORY.md is read on demand through memory tools when available, with bounded prompt fallback otherwise. On other harnesses, the model only sees the shortened injected copy until it reads or searches memory directly. If MEMORY.md is repeatedly truncated, distill it into a shorter durable summary, move detailed history into memory/*.md, or intentionally raise the bootstrap limits.

Sub-agent sessions only inject AGENTS.md (other bootstrap files are filtered out to keep sub-agent context small).

Internal hooks can intercept this step via the agent:bootstrap event to mutate or replace the injected bootstrap files (for example swapping SOUL.md for an alternate persona).

To sound less generic, start with SOUL.md Personality Guide.

To inspect how much each injected file contributes (raw vs injected, truncation, tool schema overhead), use /context list or /context detail. See Context.

Time handling

The Temporal Context section includes the user-local calendar date and time zone. It appears below the cache boundary, so day rollover or a timezone change does not invalidate the stable prefix.

Use session_status when the agent requires the precise current time and the tool is accessible; its status card displays a timestamp line. This same tool can also apply a per-session model override, which model=default removes.

Set it up with:

  • agents.defaults.userTimezone

For complete behavior details, see Timezones and Date & Time.

Skills

When qualifying skills exist, OpenClaw inserts a brief <available_skills> list (formatSkillsForPrompt) that includes the file path for each skill. The prompt directs the model to use read to fetch the SKILL.md from the specified location, whether workspace, managed, or bundled. If no skills qualify, the Skills section is omitted.

Native Codex turns receive this list as turn-scoped collaboration developer instructions rather than per-turn user input, except for lightweight cron turns that keep the exact scheduled prompt unchanged. Other harnesses retain the standard prompt section.

The location may reference a nested skill, like skills/personal/foo/SKILL.md. Nesting serves only organizational purposes; the prompt uses the flat skill name from SKILL.md frontmatter.

Qualification depends on skill metadata gates, runtime environment or configuration checks, and the effective agent skill allowlist when agents.defaults.skills or agents.entries.*.skills is set. Plugin-bundled skills qualify only if their owning plugin is enabled, allowing tool plugins to expose deeper operating guides without packing all that guidance into every tool description.

<available_skills>
  <skill>
    <name>...</name>
    <description>...</description>
    <location>...</location>
  </skill>
</available_skills>

This approach keeps the base prompt compact while still permitting targeted skill usage. The skills subsystem owns sizing, independent of generic runtime read and injection sizing:

ScopeSkills prompt budgetRuntime excerpt budget
Globalskills.limits.maxSkillsPromptCharsagents.defaults.contextLimits.*
Per-agentagents.entries.*.skillsLimits.maxSkillsPromptCharsagents.entries.*.contextLimits.*

The runtime excerpt budget applies to memory_get, live tool results, and post-compaction AGENTS.md refreshes.

Documentation

The Documentation section references local docs when they exist, such as docs/ in a Git checkout or the bundled npm package docs, and otherwise falls back to https://docs.openclaw.ai. It also notes the OpenClaw source location: Git checkouts show the local source root, while package installs receive the GitHub source URL with guidance to review source there when docs are incomplete or outdated.

The prompt frames docs as the authoritative source for OpenClaw self-knowledge before the model understands how OpenClaw operates, covering memory and daily notes, sessions, tools, Gateway, config, commands, and project context. It instructs the model to treat AGENTS.md, project context, workspace, profile, and memory notes, along with memory_search, as instruction context or user memory, not as OpenClaw design or implementation details. If docs are silent or stale, the model should flag that and examine the source. It also tells the model to run openclaw status directly when feasible, asking the user only when access is unavailable.

For configuration matters, it directs agents to the gateway tool action config.schema.lookup for precise field-level docs and constraints, then to docs/gateway/configuration.md and docs/gateway/configuration-reference.md for broader context.

2,437 words · updated Aug 24, 2026