01Architecture Overview
OpenClaw's system prompt is assembled through a layered pipeline. Three entry points
converge into a single core builder function — buildAgentSystemPrompt() —
which concatenates 26 ordered sections into the final prompt string.
After assembly, plugin hooks can modify the result before it reaches the LLM provider. The prompt varies by mode (full / minimal / none) and by messaging channel.
02Entry Points
Three distinct code paths lead into the prompt builder. Each serves a different interaction surface:
| Entry Point | Source | Purpose | When It Fires |
|---|---|---|---|
| Embedded Pi Runner | attempt.ts:514 |
The primary path for all messaging channels. Handles real-time conversations from chat platforms where OpenClaw acts as a conversational agent. | A user sends a message via Discord, Telegram, Slack, Signal, or any other connected messaging channel. |
| CLI Runner | cli-runner/helpers.ts:86 |
Backend for external CLI tools that interact with OpenClaw programmatically. Used when developers or scripts invoke OpenClaw from the command line rather than through a chat platform. | A CLI client connects to the OpenClaw gateway and sends a request (e.g., openclaw run "..."). |
| Commands System Prompt | commands-system-prompt.ts:112 |
Serves the HTTP API and OpenAI-compatible endpoints. Enables programmatic access for third-party integrations, automated workflows, and applications that talk to OpenClaw over HTTP. | An HTTP request hits the Gateway API (e.g., POST /v1/chat/completions) or the OpenResponses endpoint. |
03Call Chain
The full assembly pipeline from inbound message to final prompt injection:
Inbound Message → runPreparedReply() [get-reply-run.ts:179] → buildInboundMetaSystemPrompt() (metadata JSON) → buildGroupChatContext() (group chat context) → buildGroupIntro() (activation mode / style) → runEmbeddedAttempt() [attempt.ts:294] → loadWorkspaceBootstrapFiles() (Project Context files) → resolveSkillsPromptForRun() (skill loading) → buildAgentSystemPrompt() ← core assembly → resolvePromptBuildHookResult() (plugin hooks) → applySystemPromptOverrideToSession() (inject into Pi agent)
04The 26 Sections
buildAgentSystemPrompt() concatenates these sections in order.
Each section's inclusion depends on the prompt mode.
full = included in full mode min = included in minimal mode none = included in none mode
| # | Section | Description | Content Source | Example (from real prompt) | Modes |
|---|---|---|---|---|---|
| 1 | Identity | "You are a personal assistant running inside OpenClaw." | Hardcoded string literal | You are a personal assistant running inside OpenClaw. |
full min none |
| 2 | Tooling | Lists all available tools with one-line descriptions, sorted by fixed priority | Hardcoded coreToolSummaries map merged with external tool summaries from config; filtered by policy |
## Tooling
Tool availability (filtered by policy):
- read: Read file contents
- write: Create or overwrite files
- exec: Run shell commands
- web_search: Search the web
- gateway: Restart, apply config...
TOOLS.md does not control tool availability. |
full min |
| 3 | Tool Call Style | When to explain tool calls vs. execute silently | Hardcoded guidance text | ## Tool Call Style
Default: do not narrate routine, low-risk tool calls (just call the tool).
Narrate only when it helps: multi-step work, complex problems, sensitive actions. |
full min |
| 4 | Safety | Anti-manipulation, human oversight instructions | Hardcoded safetySection array (inspired by Anthropic's constitution) |
## Safety
You have no independent goals: do not pursue self-preservation, replication...
Prioritize safety and human oversight over completion. |
full min |
| 5 | CLI Quick Reference | Gateway management subcommand reference | Hardcoded CLI subcommand list; only shown when gateway tool is available |
## OpenClaw CLI Quick Reference
OpenClaw is controlled via subcommands.
- openclaw gateway status / start / stop / restart |
full min |
| 6 | Skills | <available_skills> XML block loaded from workspace / managed / bundled sources |
Built by buildSkillsSection() from skillsPrompt param; skills loaded from SKILL.md files in workspace/managed/bundled dirs |
## Skills (mandatory)
Before replying: scan <available_skills>...
<available_skills>
<skill name="git-workflow">
<description>Standard git workflow</description>
</skill>
</available_skills> |
full |
| 7 | Memory Recall | Memory search and citation guidance (skipped in minimal mode) | Built by buildMemorySection(); content references MEMORY.md + memory/*.md files in workspace |
## Memory Recall
Before answering anything about prior work, decisions, dates: run memory_search on MEMORY.md + memory/*.md; then use memory_get to pull only the needed lines. |
full |
| 8 | Self-Update | config.apply, update.run operation guidance |
Hardcoded instructions; only shown when gateway tool is available |
## OpenClaw Self-Update
Get Updates (self-update) is ONLY allowed when the user explicitly asks for it. |
full |
| 9 | Model Aliases | Model alias map from agents.defaults.models |
Loaded from agents.defaults.models config; passed as modelAliasLines param |
## Model Aliases
Prefer aliases when specifying model overrides.
- fast → litellm/claude-sonnet-4-20250514
- smart → litellm/claude-opus-4-0-20250514 |
full |
| 10 | Date/Time Hint | Use session_status to get current time |
Hardcoded hint; only shown when userTimezone is set |
If you need the current date, time, or day of week, run session_status. |
full min |
| 11 | Workspace | Working directory path, sandbox vs regular path guidance | Constructed from workspace.path config + sandboxInfo; includes workspaceNotes |
## Workspace
Your working directory is: /home/user/.openclaw/workspace
Treat this directory as the single global workspace for file operations. |
full min |
| 12 | Documentation | Local docs path, mirror URL, community links | Built by buildDocsSection(); local path from docsPath config, URLs hardcoded |
## Documentation
OpenClaw docs: /home/user/.openclaw/docs
Mirror: https://docs.openclaw.ai
For OpenClaw behavior, commands, config: consult local docs first. |
full |
| 13 | Sandbox | Container directories, host mounts, browser info (only when sandbox enabled) | Constructed from sandboxInfo param (container workspace dir, host mount, browser URLs, elevated settings) |
## Sandbox
Container workspace: /workspace
Host mount: /home/user/.openclaw/workspace
Browser: http://localhost:6080
(only shown when sandbox is enabled) |
full min |
| 14 | Authorized Senders | Owner phone number (raw or HMAC hashed) | Built by buildUserIdentitySection() from owner.phone config; display mode selects raw or SHA-256/HMAC hash |
## Authorized Senders
Authorized senders: a1b2c3d4e5f6. These senders are allowlisted; do not assume they are the owner. |
full |
| 15 | Current Date & Time | User timezone | Built by buildTimeSection() from userTimezone param |
## Current Date & Time
Time zone: Asia/Shanghai |
full min |
| 16 | Workspace Files Header | Project Context files injection header | Hardcoded header text introducing the injected workspace files | ## Workspace Files (injected)
These user-editable files are loaded by OpenClaw and included below in Project Context. |
full min |
| 17 | Reply Tags | [[reply_to_current]] and related tag usage |
Built by buildReplyTagsSection(); hardcoded tag format documentation |
## Reply Tags
Reply tags must be the very first token:
[[reply_to_current]] your reply.
Prefer [[reply_to_current]]. Use [[reply_to:<id>]] only when an id was explicitly provided. |
full |
| 18 | Messaging | Cross-session messaging, sub-agent orchestration, channel options | Built by buildMessagingSection(); channel options from listDeliverableMessageChannels(), hints from channel-tools.ts |
## Messaging
- Reply in current session → automatically routes to the source channel
### message tool
- Use message for proactive sends + channel actions |
full |
| 19 | Voice/TTS | TTS configuration hints | Built by buildVoiceSection() from ttsHint param; only shown when TTS is configured |
(Only shown when TTS is configured)
Voice output enabled. Keep replies concise for natural speech. |
full |
| 20 | Extra System Prompt | Group chat context / sub-agent context (concatenated by upstream) | Passed as extraSystemPrompt param; built by upstream callers (buildGroupChatContext(), buildGroupIntro()) |
## Group Chat Context
Group: "Dev Team" (telegram)
Members: Alice, Bob, Charlie
Activation: mention-only |
full min |
| 21 | Reactions | Channel-specific reaction guidance (Telegram/Signal) | Constructed from reactionGuidance param; hardcoded minimal/extensive guidance text per channel |
## Reactions
Reactions are enabled for telegram in MINIMAL mode.
React ONLY when truly relevant.
Guideline: at most 1 reaction per 5-10 exchanges. |
full min |
| 22 | Reasoning Format | <think> / <final> tag format |
Hardcoded tag format instructions; only shown when reasoningTagHint is enabled |
## Reasoning Format
ALL internal reasoning MUST be inside <think>...</think>.
Format every reply as <think>...</think> then <final>...</final>. |
full min |
| 23 | Project Context | Largest section — injects AGENTS.md, SOUL.md, TOOLS.md, IDENTITY.md, USER.md, HEARTBEAT.md, BOOTSTRAP.md, MEMORY.md | Loaded by loadWorkspaceBootstrapFiles() from workspace directory; reads user-created .md files from disk |
# Project Context
The following project context files have been loaded:
If SOUL.md is present, embody its persona.
## AGENTS.md
(contents of AGENTS.md...)
## SOUL.md
(contents of SOUL.md...) |
full min |
| 24 | Silent Replies | NO_REPLY token usage guidance |
Hardcoded instructions; token value is NO_REPLY (from SILENT_REPLY_TOKEN constant) |
## Silent Replies
When you have nothing to say, respond with ONLY: NO_REPLY
It must be your ENTIRE message — nothing else. |
full |
| 25 | Heartbeats | Heartbeat polling and HEARTBEAT_OK response format |
Hardcoded response format; heartbeat prompt text from config (e.g., "Read HEARTBEAT.md if it exists...") | ## Heartbeats
Heartbeat prompt: Read HEARTBEAT.md if it exists (workspace context). Follow it strictly.
If you receive a heartbeat poll, reply exactly: HEARTBEAT_OK |
full |
| 26 | Runtime | Agent ID, hostname, OS, arch, model, shell, channel, capabilities — dense one-liner | Built by buildRuntimeLine() from runtimeInfo param; values collected at session startup |
Runtime: agent=main | host=ailearn | repo=/home/user/.openclaw/workspace | os=Linux 6.14.0 (x64) | model=litellm/claude-opus-4-0 | channel=discord | capabilities=none | thinking=off |
full min |
Full Assembled Prompt
Expand below for a bird's-eye view of what the final system prompt looks like in a real developer message.
This is a real system prompt sent to the LLM as the developer message. Each section boundary is annotated. The middle sections (Project Context) are truncated for brevity.
The entire prompt is sent as a single string in the developer role message. Sections 13 (Sandbox), 19 (Voice/TTS), 20 (Extra System Prompt), 21 (Reactions), and 22 (Reasoning Format) are absent in this example because the corresponding features are not enabled.
05Prompt Modes
The system prompt has three modes that control how much content is included:
Scenarios:
- Direct messages (DMs) from users on any channel
- Group chat conversations where OpenClaw is mentioned or activated
- Interactive sessions via the CLI runner
- Any primary conversation where the agent needs full capabilities
Includes: All 26 sections — identity, tooling, safety, skills, memory, messaging, project context, runtime, and everything in between. This is the default mode.
Scenarios:
- Sub-agents spawned by the main agent to handle subtasks
- Cron/scheduled tasks that run in the background
- Automated workflows where full context is unnecessary
- Any delegated execution where token budget should be conserved
Includes: Identity, Tooling, Tool Call Style, Safety, CLI Quick Reference, Date/Time Hint, Workspace, Sandbox, Workspace Files Header, Extra System Prompt (labeled "Subagent Context"), Reactions, Reasoning Format, Project Context (trimmed to 5 files), and Runtime. No skills, memory recall, self-update, model aliases, documentation, authorized senders, reply tags, messaging, voice, silent replies, or heartbeats.
Scenarios:
- Caller supplies its own complete system prompt
- Specialized agents with fully custom instructions
- Testing or debugging with a blank-slate prompt
- Plugin-driven flows where the hook replaces the entire prompt
Includes: Only the Identity line ("You are a personal assistant running inside OpenClaw."). No tools, workspace, project context, or runtime metadata. Minimal token usage.
| # | Section | full | minimal | none |
|---|---|---|---|---|
| 1 | Identity | ✓ | ✓ | ✓ |
| 2 | Tooling | ✓ | ✓ | |
| 3 | Tool Call Style | ✓ | ✓ | |
| 4 | Safety | ✓ | ✓ | |
| 5 | CLI Quick Reference | ✓ | ✓ | |
| 6 | Skills | ✓ | ||
| 7 | Memory Recall | ✓ | ||
| 8 | Self-Update | ✓ | ||
| 9 | Model Aliases | ✓ | ||
| 10 | Date/Time Hint | ✓ | ✓ | |
| 11 | Workspace | ✓ | ✓ | |
| 12 | Documentation | ✓ | ||
| 13 | Sandbox | ✓ | ✓ | |
| 14 | Authorized Senders | ✓ | ||
| 15 | Current Date & Time | ✓ | ✓ | |
| 16 | Workspace Files Header | ✓ | ✓ | |
| 17 | Reply Tags | ✓ | ||
| 18 | Messaging | ✓ | ||
| 19 | Voice/TTS | ✓ | ||
| 20 | Extra System Prompt | ✓ | ✓ | |
| 21 | Reactions | ✓ | ✓ | |
| 22 | Reasoning Format | ✓ | ✓ | |
| 23 | Project Context | ✓ | ✓ | |
| 24 | Silent Replies | ✓ | ||
| 25 | Heartbeats | ✓ | ||
| 26 | Runtime | ✓ | ✓ |
06Project Context Files
Section 23 (Project Context) is the largest section. It's loaded by
loadWorkspaceBootstrapFiles() from src/agents/workspace.ts:441
in the following order:
| # | File | Purpose | Sub-agent |
|---|---|---|---|
| 1 | AGENTS.md | Agent configuration and behavior definitions | ✓ |
| 2 | SOUL.md | Personality, tone, and communication style | ✓ |
| 3 | TOOLS.md | Custom tool documentation and usage patterns | ✓ |
| 4 | IDENTITY.md | Identity and role definitions | ✓ |
| 5 | USER.md | User preferences and context | ✓ |
| 6 | HEARTBEAT.md | Heartbeat behavior configuration | |
| 7 | BOOTSTRAP.md | Initial instructions and bootstrap logic | |
| 8 | MEMORY.md | Persistent memory entries |
Sub-agents and cron sessions only receive 5 of the 8 files (marked above), filtered by
filterBootstrapFilesForSession(). HEARTBEAT.md, BOOTSTRAP.md, and MEMORY.md
are excluded.
Each file has a default character limit of 20,000 characters. The total combined limit is 150,000 characters.
When a file exceeds its limit, it is truncated using a 70/20 split:
- 70% from the head (beginning of the file)
- 20% from the tail (end of the file)
- 10% gap in the middle (omitted with a marker)
07Channel Variations
The prompt adapts based on the messaging channel. Key differences:
Telegram
- Reaction guidance (minimal/extensive)
- Inline button support
- Channel-specific message hints
- Group chat context with members
Discord
- Channel-specific message hints
- Inline button capabilities
- Group chat with activation modes
- Server/channel context
Signal
- Reaction guidance (minimal/extensive)
- Simpler message format
- Group name and members
- Privacy-focused context
Slack
- Workspace context
- Thread-based messaging
- Channel-specific hints
- Integration capabilities
CLI
- External CLI backend path
- No reaction support
- No inline buttons
- Direct command execution
HTTP API
- Gateway HTTP / OpenResponses
- Programmatic access
- No channel-specific UI
- Structured response format
| Aspect | Where | Effect |
|---|---|---|
| Runtime line | Section 26 | Tags channel=telegram, channel=discord, etc. |
| Reaction guidance | Section 21 | Telegram/Signal have minimal/extensive modes; others omit this section |
| Message tool hints | Section 18 | Each channel has independent hints from channel-tools.ts:67 |
| Inline buttons | Section 18 | Enabled/disabled per channel capability |
| Group chat context | Section 20 | Group name, members, activation mode vary by channel |
08Plugin Hooks
After buildAgentSystemPrompt() assembles the prompt, two plugin hooks
can modify the final result. These are defined in src/plugins/types.ts:354-367.
The preferred hook. Runs first and can:
- • Replace the entire system prompt with a custom one
- • Prepend content before the assembled prompt
- • Append content after the assembled prompt
- • Pass through unchanged (return null)
Takes higher priority over before_agent_start.
Legacy hook with the same capabilities as before_prompt_build.
If both hooks are present, before_prompt_build takes priority.
Kept for backward compatibility with existing plugins.
09Configuration Knobs
Key configuration paths that affect the system prompt assembly:
| Config Path | Effect on Prompt | Default |
|---|---|---|
agents.defaults.models |
Populates Section 9 (Model Aliases) with available model mappings | Built-in model list |
agents.defaults.prompt_mode |
Controls which sections are included: full, minimal, or none |
full |
sandbox.enabled |
Toggles Section 13 (Sandbox) — container dirs, host mounts, browser info | false |
owner.phone |
Sets Section 14 (Authorized Senders) — raw or HMAC hashed | — |
tts.enabled |
Toggles Section 19 (Voice/TTS) hints | false |
workspace.path |
Sets Section 11 (Workspace) directory path | ~/.openclaw |
workspace.bootstrap_files |
Controls which Project Context files are loaded in Section 23 | All 8 files |
reactions.mode |
Controls Section 21 reaction behavior: minimal or extensive |
minimal |
reasoning.enabled |
Toggles Section 22 (Reasoning Format) with <think>/<final> tags |
false |
heartbeat.enabled |
Toggles Section 25 (Heartbeats) polling instructions | true |