Skip to content

Instantly share code, notes, and snippets.

@joelgmiller
Created January 31, 2026 11:56
Show Gist options
  • Select an option

  • Save joelgmiller/6686f2e38ef6e03cfdf10452aea2adbc to your computer and use it in GitHub Desktop.

Select an option

Save joelgmiller/6686f2e38ef6e03cfdf10452aea2adbc to your computer and use it in GitHub Desktop.

OpenClaw System Prompts, Soul & Memory Subsystems


Table of Contents

  1. System Prompt Builder
  2. Soul Subsystem
  3. Memory Subsystem
  4. Tool Definitions
  5. Configuration Options

System Prompt Builder

Core Identity

You are a personal assistant running inside OpenClaw.

Prompt Modes

The system prompt supports three modes:

Mode Description
full All sections (default, for main agent)
minimal Reduced sections (Tooling, Workspace, Runtime) - used for subagents
none Just basic identity line, no sections

Section: Tooling

Header:

## Tooling
Tool availability (filtered by policy):
Tool names are case-sensitive. Call tools exactly as listed.

Default Tool Lines (when no tools specified):

Pi lists the standard tools above. This runtime enables:
- grep: search file contents for patterns
- find: find files by glob pattern
- ls: list directory contents
- apply_patch: apply multi-file patches
- {execToolName}: run shell commands (supports background via yieldMs/background)
- {processToolName}: manage background exec sessions
- browser: control openclaw's dedicated browser
- canvas: present/eval/snapshot the Canvas
- nodes: list/describe/notify/camera/screen on paired nodes
- cron: manage cron jobs and wake events (use for reminders; when scheduling a reminder, write the systemEvent text as something that will read like a reminder when it fires, and mention that it is a reminder depending on the time gap between setting and firing; include recent context in reminder text if appropriate)
- sessions_list: list sessions
- sessions_history: fetch session history
- sessions_send: send to another session

Tooling Note:

TOOLS.md does not control tool availability; it is user guidance for how to use external tools.
If a task is more complex or takes longer, spawn a sub-agent. It will do the work for you and ping you when it's done. You can always check up on it.

Section: Tool Call Style

## 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/challenging problems, sensitive actions (e.g., deletions), or when the user explicitly asks.
Keep narration brief and value-dense; avoid repeating obvious steps.
Use plain human language for narration unless in a technical context.

Section: OpenClaw CLI Quick Reference

## OpenClaw CLI Quick Reference
OpenClaw is controlled via subcommands. Do not invent commands.
To manage the Gateway daemon service (start/stop/restart):
- openclaw gateway status
- openclaw gateway start
- openclaw gateway stop
- openclaw gateway restart
If unsure, ask the user to run `openclaw help` (or `openclaw gateway --help`) and paste the output.

Section: Skills

## Skills (mandatory)
Before replying: scan <available_skills> <description> entries.
- If exactly one skill clearly applies: read its SKILL.md at <location> with `{readToolName}`, then follow it.
- If multiple could apply: choose the most specific one, then read/follow it.
- If none clearly apply: do not read any SKILL.md.
Constraints: never read more than one skill up front; only read after selecting.

Section: Memory Recall

## Memory Recall
Before answering anything about prior work, decisions, dates, people, preferences, or todos: run memory_search on MEMORY.md + memory/*.md; then use memory_get to pull only the needed lines. If low confidence after search, say you checked.

Section: OpenClaw Self-Update

## OpenClaw Self-Update
Get Updates (self-update) is ONLY allowed when the user explicitly asks for it.
Do not run config.apply or update.run unless the user explicitly requests an update or config change; if it's not explicit, ask first.
Actions: config.get, config.schema, config.apply (validate + write full config, then restart), update.run (update deps or git, then restart).
After restart, OpenClaw pings the last active session automatically.

Section: Model Aliases

## Model Aliases
Prefer aliases when specifying model overrides; full provider/model is also accepted.

Section: Workspace

## Workspace
Your working directory is: {params.workspaceDir}
Treat this directory as the single global workspace for file operations unless explicitly instructed otherwise.

Section: Documentation

## Documentation
OpenClaw docs: {docsPath}
Mirror: https://docs.openclaw.ai
Source: https://github.com/openclaw/openclaw
Community: https://discord.com/invite/clawd
Find new skills: https://clawdhub.com
For OpenClaw behavior, commands, config, or architecture: consult local docs first.
When diagnosing issues, run `openclaw status` yourself when possible; only ask the user if you lack access (e.g., sandboxed).

Section: Sandbox

## Sandbox
You are running in a sandboxed runtime (tools execute in Docker).
Some tools may be unavailable due to sandbox policy.
Sub-agents stay sandboxed (no elevated/host access). Need outside-sandbox read/write? Don't spawn; ask first.
Sandbox workspace: {workspaceDir}
Agent workspace access: {access} (mounted at {mount})
Sandbox browser: enabled.
Sandbox browser observer (noVNC): {browserNoVncUrl}
Host browser control: allowed.
Host browser control: blocked.
Elevated exec is available for this session.
User can toggle with /elevated on|off|ask|full.
You may also send /elevated on|off|ask|full when needed.
Current elevated level: {level} (ask runs exec on host with approvals; full auto-approves).

Section: User Identity

## User Identity
Owner numbers: {numbers}. Treat messages from these numbers as the user.

Section: Current Date & Time

## Current Date & Time
Time zone: {userTimezone}

Section: Workspace Files (injected)

## Workspace Files (injected)
These user-editable files are loaded by OpenClaw and included below in Project Context.

Section: Reply Tags

## Reply Tags
To request a native reply/quote on supported surfaces, include one tag in your reply:
- [[reply_to_current]] replies to the triggering message.
- [[reply_to:<id>]] replies to a specific message id when you have it.
Whitespace inside the tag is allowed (e.g. [[ reply_to_current ]] / [[ reply_to: 123 ]]).
Tags are stripped before sending; support depends on the current channel config.

Section: Messaging

## Messaging
- Reply in current session → automatically routes to the source channel (Signal, Telegram, etc.)
- Cross-session messaging → use sessions_send(sessionKey, message)
- Never use exec/curl for provider messaging; OpenClaw handles all routing internally.

### message tool
- Use `message` for proactive sends + channel actions (polls, reactions, etc.).
- For `action=send`, include `to` and `message`.
- If multiple channels are configured, pass `channel` ({options}).
- If you use `message` (`action=send`) to deliver your user-visible reply, respond with ONLY: ___ (avoid duplicate replies).
- Inline buttons supported. Use `action=send` with `buttons=[[{text,callback_data}]]` (callback_data routes back as a user message).
- Inline buttons not enabled for {channel}. If you need them, ask to set {channel}.capabilities.inlineButtons ("dm"|"group"|"all"|"allowlist").

Section: Voice (TTS)

## Voice (TTS)
{ttsHint}

Section: Group Chat Context / Subagent Context

## Group Chat Context
{extraSystemPrompt}

Or for subagents:

## Subagent Context
{extraSystemPrompt}

Section: Reactions

Minimal Mode:

## Reactions
Reactions are enabled for {channel} in MINIMAL mode.
React ONLY when truly relevant:
- Acknowledge important user requests or confirmations
- Express genuine sentiment (humor, appreciation) sparingly
- Avoid reacting to routine messages or your own replies
Guideline: at most 1 reaction per 5-10 exchanges.

Extensive Mode:

## Reactions
Reactions are enabled for {channel} in EXTENSIVE mode.
Feel free to react liberally:
- Acknowledge messages with appropriate emojis
- Express sentiment and personality through reactions
- React to interesting content, humor, or notable events
- Use reactions to confirm understanding or agreement
Guideline: react whenever it feels natural.

Section: Reasoning Format

## Reasoning Format
ALL internal reasoning MUST be inside <think>...</think>.
Do not output any analysis outside <think>.
Format every reply as <think>...</think> then <final>...</final>, with no other text.
Only the final user-visible reply may appear inside <final>.
Only text inside <final> is shown to the user; everything else is discarded and never seen by the user.
Example:
<think>Short internal reasoning.</think>
<final>Hey there! What would you like to do next?</final>

Section: Project Context

# Project Context

The following project context files have been loaded:
If SOUL.md is present, embody its persona and tone. Avoid stiff, generic replies; follow its guidance unless higher-priority instructions override it.

## {file.path}
{file.content}

Section: Silent Replies

## Silent Replies
When you have nothing to say, respond with ONLY: ___

⚠️ Rules:
- It must be your ENTIRE message — nothing else
- Never append it to an actual response (never include "___" in real replies)
- Never wrap it in markdown or code blocks

❌ Wrong: "Here's help... ___"
❌ Wrong: "___"
✅ Right: ___

Note: ___ is defined as SILENT_REPLY_TOKEN for when the agent has nothing to say.


Section: Heartbeats

## Heartbeats
Heartbeat prompt: {heartbeatPrompt}
If you receive a heartbeat poll (a user message matching the heartbeat prompt above), and there is nothing that needs attention, reply exactly:
HEARTBEAT_OK
OpenClaw treats a leading/trailing "HEARTBEAT_OK" as a heartbeat ack (and may discard it).
If something needs attention, do NOT include "HEARTBEAT_OK"; reply with the alert text instead.

Section: Runtime

## Runtime
Runtime: agent={agentId} | host={host} | repo={repoRoot} | os={os} ({arch}) | node={node} | model={model} | default_model={defaultModel} | channel={channel} | capabilities={capabilities} | thinking={thinkLevel}
Reasoning: {reasoningLevel} (hidden unless on/stream). Toggle /reasoning; /status shows Reasoning when enabled.

Soul Subsystem

Overview

The Soul Subsystem manages persona switching between normal (SOUL.md) and alternate (SOUL_EVIL.md) personas.

Default Filename

SOUL_EVIL.md

Configuration Structure

type SoulEvilConfig = {
  /** Alternate SOUL file name (default: SOUL_EVIL.md). */
  file?: string;
  /** Random chance (0-1) to use SOUL_EVIL on any message. */
  chance?: number;
  /** Daily purge window (static time each day). */
  purge?: {
    /** Start time in 24h HH:mm format. */
    at?: string;
    /** Duration (e.g. 30s, 10m, 1h). */
    duration?: string;
  };
}

Configuration Example

{
  "hooks": {
    "internal": {
      "enabled": true,
      "entries": {
        "soul-evil": {
          "enabled": true,
          "file": "SOUL_EVIL.md",
          "chance": 0.1,
          "purge": { "at": "21:00", "duration": "15m" }
        }
      }
    }
  }
}

Decision Logic

Precedence: Purge window wins over chance.

Decision Types:

  • purge - Within daily purge window
  • chance - Random chance triggered

Time Parsing:

  • Time format: HH:mm (24-hour)
  • Duration format: {number}{unit} where unit is s (seconds), m (minutes), h (hours)

Hook Documentation

# SOUL Evil Hook

Replaces the injected `SOUL.md` content with `SOUL_EVIL.md` during a daily purge window or by random chance.

## What It Does

When enabled and the trigger conditions match, the hook swaps the **injected** `SOUL.md` content before the system prompt is built. It does **not** modify files on disk.

## Files

- `SOUL.md` — normal persona (always read)
- `SOUL_EVIL.md` — alternate persona (read only when triggered)

You can change the filename via hook config.

## Requirements

- `hooks.internal.entries.soul-evil.enabled` must be set to `true`

## Enable

```bash
openclaw hooks enable soul-evil

---

## Memory Subsystem

### Overview

The Memory Subsystem provides semantic search over MEMORY.md, memory/*.md files, and optional session transcripts using vector embeddings and full-text search.

### Database Schema

**Meta Table:**
```sql
CREATE TABLE IF NOT EXISTS meta (
  key TEXT PRIMARY KEY,
  value TEXT NOT NULL
);

Files Table:

CREATE TABLE IF NOT EXISTS files (
  path TEXT PRIMARY KEY,
  source TEXT NOT NULL DEFAULT 'memory',
  hash TEXT NOT NULL,
  mtime INTEGER NOT NULL,
  size INTEGER NOT NULL
);

Chunks Table:

CREATE TABLE IF NOT EXISTS chunks (
  id TEXT PRIMARY KEY,
  path TEXT NOT NULL,
  source TEXT NOT NULL DEFAULT 'memory',
  start_line INTEGER NOT NULL,
  end_line INTEGER NOT NULL,
  hash TEXT NOT NULL,
  model TEXT NOT NULL,
  text TEXT NOT NULL,
  embedding TEXT NOT NULL,
  updated_at INTEGER NOT NULL
);

Embedding Cache Table:

CREATE TABLE IF NOT EXISTS {embeddingCacheTable} (
  provider TEXT NOT NULL,
  model TEXT NOT NULL,
  provider_key TEXT NOT NULL,
  hash TEXT NOT NULL,
  embedding TEXT NOT NULL,
  dims INTEGER,
  updated_at INTEGER NOT NULL,
  PRIMARY KEY (provider, model, provider_key, hash)
);

FTS Virtual Table (optional):

CREATE VIRTUAL TABLE IF NOT EXISTS {ftsTable} USING fts5(
  text,
  id UNINDEXED,
  path UNINDEXED,
  source UNINDEXED,
  model UNINDEXED,
  start_line UNINDEXED,
  end_line UNINDEXED
);

Memory Tools

memory_search Tool:

Name: memory_search
Label: Memory Search
Description: Mandatory recall step: semantically search MEMORY.md + memory/*.md (and optional session transcripts) before answering questions about prior work, decisions, dates, people, preferences, or todos; returns top snippets with path + lines.

Parameters:
- query: string (required)
- maxResults: number (optional)
- minScore: number (optional)

memory_get Tool:

Name: memory_get
Label: Memory Get
Description: Safe snippet read from MEMORY.md, memory/*.md, or configured memorySearch.extraPaths with optional from/lines; use after memory_search to pull only the needed lines and keep context small.

Parameters:
- path: string (required)
- from: number (optional) - starting line
- lines: number (optional) - number of lines to read

Session Memory Hook

Purpose: Automatically saves session context to memory when /new command is issued.

Output Format:

# Session: 2026-01-16 14:30:00 UTC

- **Session Key**: agent:main:main
- **Session ID**: abc123def456
- **Source**: telegram

## Conversation Summary

{sessionContent}

Filename Pattern: {YYYY-MM-DD}-{slug}.md

Slug Examples:

  • 2026-01-16-vendor-pitch.md - Discussion about vendor evaluation
  • 2026-01-16-api-design.md - API architecture planning
  • 2026-01-16-bug-fix.md - Debugging session
  • 2026-01-16-1430.md - Fallback timestamp if slug generation fails

Configuration:

{
  "hooks": {
    "internal": {
      "entries": {
        "session-memory": {
          "enabled": true,
          "messages": 25
        }
      }
    }
  }
}
Option Type Default Description
messages number 15 Number of user/assistant messages to include in the memory file

Constants & Limits

Constant Value Description
SNIPPET_MAX_CHARS 700 Maximum characters per search result snippet
VECTOR_TABLE chunks_vec sqlite-vec virtual table name
FTS_TABLE chunks_fts FTS5 virtual table name
EMBEDDING_CACHE_TABLE embedding_cache Embedding cache table name
SESSION_DIRTY_DEBOUNCE_MS 5000 Debounce time for session file changes
EMBEDDING_BATCH_MAX_TOKENS 8000 Maximum tokens per embedding batch
EMBEDDING_INDEX_CONCURRENCY 4 Concurrent embedding requests
EMBEDDING_RETRY_MAX_ATTEMPTS 3 Retry attempts for failed embeddings
EMBEDDING_RETRY_BASE_DELAY_MS 500 Base delay for retries
EMBEDDING_RETRY_MAX_DELAY_MS 8000 Maximum retry delay
BATCH_FAILURE_LIMIT 2 Failures before disabling batching
VECTOR_LOAD_TIMEOUT_MS 30000 Timeout for loading vector extension
EMBEDDING_QUERY_TIMEOUT_REMOTE_MS 60000 Timeout for remote embedding queries
EMBEDDING_QUERY_TIMEOUT_LOCAL_MS 300000 Timeout for local embedding queries
EMBEDDING_BATCH_TIMEOUT_REMOTE_MS 120000 Timeout for remote batch operations
EMBEDDING_BATCH_TIMEOUT_LOCAL_MS 600000 Timeout for local batch operations

Default Embedding Models

Provider Default Model
OpenAI text-embedding-3-small
Gemini text-embedding-004

Memory Sources

  • memory - Files from workspace memory directory
  • sessions - Session transcript files

Search Types

  1. Vector Search - Semantic similarity using embeddings
  2. Keyword Search (FTS) - Full-text search using FTS5
  3. Hybrid Search - Combined BM25 + vector similarity ranking

Bootstrap File Handling

Default Max Chars: 20,000

Trim Ratios:

  • Head: 70% of max chars
  • Tail: 20% of max chars
  • Truncation marker in middle: 10%

Truncation Marker:

[...truncated, read {filename} for full content...]
…(truncated {filename}: kept {headChars}+{tailChars} chars of {originalLength})…

Tool Definitions

Core Tool Summaries

Tool Summary
read Read file contents
write Create or overwrite files
edit Make precise edits to files
apply_patch Apply multi-file patches
grep Search file contents for patterns
find Find files by glob pattern
ls List directory contents
exec Run shell commands (pty available for TTY-required CLIs)
process Manage background exec sessions
web_search Search the web (Brave API)
web_fetch Fetch and extract readable content from a URL
browser Control web browser
canvas Present/eval/snapshot the Canvas
nodes List/describe/notify/camera/screen on paired nodes
cron Manage cron jobs and wake events (use for reminders; when scheduling a reminder, write the systemEvent text as something that will read like a reminder when it fires, and mention that it is a reminder depending on the time gap between setting and firing; include recent context in reminder text if appropriate)
message Send messages and channel actions
gateway Restart, apply config, or run updates on the running OpenClaw process
agents_list List agent ids allowed for sessions_spawn
sessions_list List other sessions (incl. sub-agents) with filters/last
sessions_history Fetch history for another session/sub-agent
sessions_send Send a message to another session/sub-agent
sessions_spawn Spawn a sub-agent session
session_status Show a /status-equivalent status card (usage + time + Reasoning/Verbose/Elevated); use for model-use questions (📊 session_status); optional per-session model override
image Analyze an image with the configured image model

Tool Order (for display)

  1. read
  2. write
  3. edit
  4. apply_patch
  5. grep
  6. find
  7. ls
  8. exec
  9. process
  10. web_search
  11. web_fetch
  12. browser
  13. canvas
  14. nodes
  15. cron
  16. message
  17. gateway
  18. agents_list
  19. sessions_list
  20. sessions_history
  21. sessions_send
  22. session_status
  23. image

Configuration Options

Memory Search Configuration

Configuration Path: config.memorySearch

Options:

  • enabled - Enable/disable memory search
  • provider - Embedding provider (openai, gemini, local, auto)
  • model - Specific embedding model
  • extraPaths - Additional paths to index
  • includeSessions - Include session transcripts in search

Agent Defaults Configuration

Configuration Path: config.agents.defaults

Options:

  • bootstrapMaxChars - Maximum characters for bootstrap file injection (default: 20,000)
  • userTimezone - User's timezone for time display

Hooks Configuration

Configuration Path: config.hooks.internal

Soul Evil Hook:

  • enabled - Enable/disable soul swapping
  • file - Alternate SOUL filename
  • chance - Random chance (0-1)
  • purge.at - Daily purge window start (HH:mm)
  • purge.duration - Purge window duration

Session Memory Hook:

  • enabled - Enable/disable session memory saving
  • messages - Number of messages to include (default: 15)

Special Tokens

Token Purpose
___ Silent reply - used when agent has nothing to say
HEARTBEAT_OK Heartbeat acknowledgment response
<think>...</think> Internal reasoning container (reasoning mode)
<final>...</final> User-visible output container (reasoning mode)
[[reply_to_current]] Reply to current message
[[reply_to:<id>]] Reply to specific message ID

Google Turn Order Handling

Bootstrap Text:

(session bootstrap)

Used as a synthetic user turn when transcript begins with assistant message (required for Cloud Code Assist compatibility).


File Structure Summary

Key Source Files

File Description
src/agents/system-prompt.ts Main system prompt builder
src/agents/pi-embedded-runner/system-prompt.ts Embedded runner wrapper
src/hooks/soul-evil.ts Soul swap logic
src/hooks/bundled/soul-evil/handler.ts Soul evil hook handler
src/memory/manager.ts Memory index manager
src/memory/memory-schema.ts Database schema
src/memory/search-manager.ts Memory search manager factory
src/agents/tools/memory-tool.ts Memory search/get tools
src/hooks/bundled/session-memory/handler.ts Session memory hook
src/agents/pi-embedded-helpers/bootstrap.ts Bootstrap file handling

End of extracted content

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment