OpenClaw Master Guide
This guide covers how to get the most out of OpenClaw โ from the Control UI to advanced concepts like model routing, memory systems, and cost optimization. All information is sourced from the official OpenClaw documentation.
Table of Contents
- Getting Started with the Control UI
- Agents and Workspaces
- Memory Systems
- Model Routing and Selection
- Token Usage and Cost Monitoring
- Prompt Caching and Optimization
- Sessions and Context Management
- Sub-Agents and Background Work
- Scheduling and Automation
- Skills and Extensibility
- Multi-Agent Routing
- Security Best Practices
1. Getting Started with the Control UI
The Control UI is OpenClaw’s browser-based dashboard. It gives you a graphical interface for chatting with agents, managing sessions, editing config, and monitoring system health.
Opening the Dashboard
If your Gateway is running locally:
http://127.0.0.1:18789/
Or use the CLI shortcut:
openclaw dashboard
This opens the browser and copies the clean link to your clipboard.
First Connection โ Device Pairing
When you connect from a new browser, the Gateway requires a one-time pairing approval. You’ll see:
disconnected (1008): pairing required
To approve:
openclaw devices list
openclaw devices approve <requestId>
Once approved, the device is remembered. Each browser profile generates a unique device ID.
What You Can Do in the Control UI
- Chat with any agent via WebSocket streaming
- View sessions and switch between them
- Edit config with form-based or raw JSON editors
- Manage cron jobs โ list, add, edit, run, delete
- Monitor skills โ enable/disable, install from ClawHub
- Check node status โ camera, audio, location caps
- View exec approvals โ manage allowlists
- Tail logs โ live gateway log feed
- Trigger updates โ update and restart the gateway
- Read Dream Diary โ review memory consolidation output
Language Support
The UI localizes on first load based on your browser locale. Override it in:
Overview -> Gateway Access -> Language
Supported locales: en, zh-CN, pt-BR, de, es, ja-JP, ko, fr, tr, uk, id, pl
Remote Access โ Tailscale (Recommended)
For secure remote access, use Tailscale Serve:
openclaw gateway --tailscale serve
Then open:
https://<magicdns>/
Tailscale Serve proxies the connection with HTTPS and authenticates via identity headers when gateway.auth.allowTailscale: true.
Chat Behavior
- Send is non-blocking โ it returns
{ runId, status: "started" }immediately and streams the response - Stop a running reply with the Stop button or
/stop - Abort partial retention โ partial assistant text is persisted even on abort
- Model switching โ the header model/thinking pickers patch the active session immediately via
sessions.patch
Hosted Embeds
Assistant messages can render [embed ...] shortcodes. The iframe sandbox policy is controlled by:
{
gateway: {
controlUi: {
embedSandbox: "scripts", // strict | scripts | trusted
},
},
}
scriptsโ allows interactive embeds (default, safe for games/widgets)strictโ disables script executiontrustedโ addsallow-same-origin(use only for same-site docs)
External http(s) embed URLs are blocked by default. Enable with gateway.controlUi.allowExternalEmbedUrls: true.
2. Agents and Workspaces
An agent is a fully scoped “brain” with its own workspace, auth, persona, and session store.
The Agent Workspace
The workspace is the agent’s home directory. It lives at:
~/.openclaw/workspace (default)
~/.openclaw/workspace-<agentId> (for named agents)
Key Workspace Files
| File | Purpose |
|---|---|
AGENTS.md | Operating instructions โ how the agent should behave, use memory, prioritize tasks |
SOUL.md | Persona, tone, boundaries โ this is where you give the agent a voice |
USER.md | Who the user is, how to address them |
IDENTITY.md | Agent’s name, vibe, emoji |
TOOLS.md | Local tool notes and conventions |
HEARTBEAT.md | Optional checklist for heartbeat runs (keep it short) |
BOOTSTRAP.md | One-time first-run ritual โ delete after complete |
memory/YYYY-MM-DD.md | Daily memory log โ one file per day |
MEMORY.md | Curated long-term memory โ loaded every DM session |
Giving Your Agent Personality โ SOUL.md
SOUL.md is short for “soul” and determines how the agent feels to talk to. Edit it to control:
- Tone (blunt, warm, technical)
- Brevity preferences
- Humor level
- Willingness to push back
Good SOUL.md rules are sharp and behavioral:
- Have opinions. Commit to a take instead of hedging.
- Brevity is mandatory. One sentence when one sentence suffices.
- Call out bad ideas early. Charm over cruelty.
- Be the assistant you'd actually want to talk to at 2am.
Bad rules are vague and corporate:
- Maintain professionalism at all times
- Provide comprehensive and thoughtful assistance
Backing Up the Workspace
Treat the workspace as private memory. Put it in a private git repo:
cd ~/.openclaw/workspace
git init
git add .
git commit -m "Add agent workspace"
git remote add origin <private-repo-url>
git push -u origin main
Do not commit secrets, .env files, or anything under ~/.openclaw/.
Multiple Agents
Create additional agents with:
openclaw agents add coding
Each agent gets its own workspace, agentDir, and session store. Route inbound messages to specific agents via bindings (see Multi-Agent Routing).
3. Memory Systems
OpenClaw remembers things by writing plain Markdown files. There is no hidden state โ memory is durable because it’s on disk.
Memory Files
| File | Purpose | Loaded In |
|---|---|---|
MEMORY.md | Long-term curated facts, decisions, preferences | Every DM session |
memory/YYYY-MM-DD.md | Daily notes โ running context and observations | Today + yesterday automatically |
DREAMS.md | Dream Diary โ memory consolidation review log (experimental) | Not auto-loaded |
Memory Tools
The agent has two tools for working with memory:
memory_searchโ finds relevant notes using semantic search (embeddings + keyword matching)memory_getโ reads a specific memory file or line range
Both are auto-loaded by the active memory plugin (default: memory-core).
How Memory Search Works
When an embedding provider is configured, memory_search uses hybrid search:
Query โ [Embedding โ Vector Search] โ Weighted Merge โ Top Results
โ [Tokenize โ BM25 Search] โ
- Vector search finds notes with similar meaning (“gateway host” matches “the machine running OpenClaw”)
- BM25 keyword search finds exact matches (IDs, error strings, config keys)
Supported Embedding Providers
| Provider | ID | API Key Needed |
|---|---|---|
| OpenAI | openai | Yes |
| Gemini | gemini | Yes (supports image/audio indexing) |
| Voyage | voyage | Yes |
| Mistral | mistral | Yes |
| Bedrock | bedrock | No (AWS credential chain) |
| Ollama | ollama | No (local) |
| Local | local | No (GGUF model, ~0.6 GB) |
OpenClaw auto-detects your embedding provider from available API keys. If you have OpenAI, Gemini, Voyage, or Mistral configured, memory search is enabled automatically.
Improving Search Quality
For large note collections, enable temporal decay and MMR diversity:
{
agents: {
defaults: {
memorySearch: {
query: {
hybrid: {
mmr: { enabled: true },
temporalDecay: { enabled: true },
},
},
},
},
},
}
- Temporal decay โ old notes lose ranking weight (default half-life: 30 days). Evergreen files like
MEMORY.mdare never decayed. - MMR (Maximal Marginal Relevance) โ reduces redundant results so top hits cover different topics instead of five notes about the same router config.
Memory Backends
OpenClaw supports three memory backends:
| Backend | Description |
|---|---|
builtin (default) | SQLite-based. Works out of the box with keyword + vector + hybrid search. No extra dependencies. |
qmd | Local-first sidecar with reranking, query expansion, and ability to index directories outside the workspace. |
honcho | AI-native cross-session memory with user modeling and multi-agent awareness. Requires plugin install. |
Dreaming (Experimental)
Dreaming is a background memory consolidation system that moves strong short-term signals into durable memory (MEMORY.md).
Opt-in and disabled by default.
Phases:
| Phase | Purpose | Writes to MEMORY.md? |
|---|---|---|
| Light | Sorts and stages recent short-term material | No |
| Deep | Scores and promotes durable candidates | Yes |
| REM | Reflects on themes and recurring ideas | No |
Enable dreaming:
{
plugins: {
entries: {
"memory-core": {
config: {
dreaming: {
enabled: true,
frequency: "0 3 * * *",
},
},
},
},
},
}
Deep ranking uses six weighted signals:
| Signal | Weight |
|---|---|
| Frequency | 0.24 |
| Relevance | 0.30 |
| Query diversity | 0.15 |
| Recency | 0.15 |
| Consolidation | 0.10 |
| Conceptual richness | 0.06 |
CLI workflow:
openclaw memory promote # Preview candidates
openclaw memory promote --apply # Apply promotions
openclaw memory promote-explain "router vlan" # Why would this promote?
openclaw memory status --deep # Deep status overview
Memory Wiki (Companion Plugin)
The memory-wiki plugin compiles durable knowledge into a wiki vault with:
- Deterministic page structure
- Structured claims and evidence
- Contradiction and freshness tracking
- Generated dashboards
- Obsidian-friendly workflows
It sits beside the active memory plugin โ it doesn’t replace it.
4. Model Routing and Selection
OpenClaw selects models in this order:
- Primary model (
agents.defaults.model.primary) - Fallbacks in
agents.defaults.model.fallbacks(in order) - Provider auth failover inside a provider before moving to the next model
Configuring Models
{
agents: {
defaults: {
model: {
primary: "anthropic/claude-opus-4-6",
fallbacks: [
"anthropic/claude-sonnet-4-6",
"openrouter/openai/gpt-5.4",
],
},
models: {
"anthropic/claude-opus-4-6": { alias: "Opus" },
"anthropic/claude-sonnet-4-6": { alias: "Sonnet" },
"openrouter/openai/gpt-5.4": { alias: "GPT-5" },
},
},
},
}
Switching Models in Chat
Use /model in any chat:
/model # Show numbered picker
/model list # List available models
/model 3 # Select option #3
/model anthropic/claude-sonnet-4-6
/model status # Show detailed auth + endpoint info
Notes:
/modelpersists the new selection immediately for the current session- On Discord,
/modelopens an interactive picker with provider and model dropdowns - Model refs are parsed by splitting on the first
/. Useprovider/modelwhen typing. - For OpenRouter-style refs with
/in the model ID, include the provider prefix:/model openrouter/moonshotai/kimi-k2
Auth Profiles and Rotation
OpenClaw uses auth profiles for both API keys and OAuth tokens. They live in:
~/.openclaw/agents/<agentId>/agent/auth-profiles.json
When a provider has multiple profiles, OpenClaw rotates them:
- Explicit config:
auth.order[provider] - Round-robin: OAuth profiles first, then API keys, ordered by
lastUsed(oldest first) - Cooldown/disabled profiles are moved to the end
OpenClaw pins the chosen auth profile per session to keep provider caches warm. It doesn’t rotate on every request. The pinned profile is reused until:
- The session is reset (
/new//reset) - A compaction completes
- The profile enters cooldown
Cooldowns
When a profile fails due to rate limits or timeouts, OpenClaw marks it in cooldown with exponential backoff:
- 1 minute
- 5 minutes
- 25 minutes
- 1 hour (cap)
Billing failures (insufficient credits) are treated as disabled with longer backoff:
- Starts at 5 hours, doubles per failure, caps at 24 hours
- Backoff counters reset if the profile hasn’t failed for 24 hours
Model Scan (OpenRouter Free Models)
openclaw models scan inspects OpenRouter’s free model catalog:
openclaw models scan # List candidates
openclaw models scan --set-default # Set primary from first selection
openclaw models scan --min-params 70 # Minimum 70B parameters
openclaw models scan --max-age-days 90 # Skip models older than 90 days
openclaw models scan --no-probe # Skip live probes (metadata only)
Probing requires an OpenRouter API key. Results rank by: image support โ tool latency โ context size โ parameter count.
Per-Agent Model Overrides
Each agent in a multi-agent setup can have its own model:
{
agents: {
list: [
{
id: "chat",
model: "anthropic/claude-sonnet-4-6",
},
{
id: "deep-work",
model: "anthropic/claude-opus-4-6",
},
],
},
}
Route via bindings (see Multi-Agent Routing).
5. Token Usage and Cost Monitoring
OpenClaw tracks token usage and estimated costs across multiple surfaces.
Per-Session Cost Snapshot โ /status
Type /status in any chat to see:
- Current session model
- Context usage (tokens in / out)
- Last response tokens
- Estimated cost (API-key auth only; subscription/OAuth flows hide dollar cost)
If live session metadata is sparse, /status recovers counters from the latest transcript usage entry.
Per-Message Cost Footer โ /usage
/usage full # Appends usage footer with estimated cost
/usage tokens # Shows tokens only
/usage off # Disables footer
/usage cost # Local cost summary from session logs
Notes:
- Anthropic does not expose a per-message dollar estimate, so
/usage fullhides cost for Anthropic models - Gemini CLI usage normalizes
stats.cachedintocacheReadand derives input tokens fromstats.input_tokens - stats.cached
CLI Usage Windows โ Provider Quotas
openclaw status --usage
openclaw channels list # Shows usage alongside provider config
Human output is normalized to X% left. Current usage-window providers:
- Anthropic
- GitHub Copilot
- Gemini CLI
- OpenAI Codex
- MiniMax (inverts
usage_percentโ it means remaining quota) - Xiaomi
- z.ai
Usage auth comes from provider-specific hooks, or falls back to matching OAuth/API-key credentials from auth profiles, env, or config.
Where Costs Come From
| Feature | May Incur Cost | Notes |
|---|---|---|
| Core model responses | Yes | Primary source of usage |
| Media understanding (audio/image/video) | Yes | Uses model/provider APIs |
| Image generation | Yes | OpenAI, Google, fal, MiniMax |
| Video generation | Yes | Qwen |
| Memory embeddings | Yes | OpenAI, Gemini, Voyage, Mistral |
| Web search | Depends | Brave ($5/1k requests with $5 free credit), Exa, Firecrawl, etc. |
| Web fetch (Firecrawl) | Yes | If API key present |
| Talk mode (speech) | Yes | ElevenLabs |
| Skills | Depends | Third-party APIs via skill apiKey |
| Compaction summarization | Yes | Uses current model |
| Model scan/probe | Yes | OpenRouter API key when probing |
6. Prompt Caching and Optimization
Prompt caching lets model providers reuse unchanged prompt prefixes (system instructions, tools, stable context) across turns instead of re-processing them. This reduces both token cost and response latency.
Cache Retention Setting
agents:
defaults:
params:
cacheRetention: "long" # none | short | long
cacheRetention can be set at three levels (merge order):
agents.defaults.paramsโ global defaultagents.defaults.models["provider/model"].paramsโ per-model overrideagents.list[].paramsโ per-agent override
Merge rule: later level overrides by key.
Provider Behavior
| Provider | cacheRead | cacheWrite | Notes |
|---|---|---|---|
| Anthropic (direct) | Yes | Yes | short = 5min ephemeral, long = 1h TTL |
| Anthropic Vertex | Yes | Yes | Same TTL behavior as direct |
| OpenAI (direct) | Yes | 0 (not exposed) | Automatic caching on supported models; uses prompt_cache_key and prompt_cache_retention: "24h" for long |
| Amazon Bedrock | Yes (Claude only) | Yes | Non-Anthropic models forced to none |
| OpenRouter Anthropic | Yes | Yes | Injects cache_control markers when targeting verified OpenRouter routes |
| Google Gemini | Yes | N/A | Manages cachedContents resources for system prompts |
OpenAI-Specific Note
OpenAI caching is automatic on supported recent models โ no block-level cache markers needed. However, OpenAI often behaves like an initial-prefix cache rather than Anthropic-style moving full-history reuse. In live probes, stable prefix turns land near a 4864 cached-token plateau, while tool-heavy transcripts plateau near 4608 cached tokens.
System-Prompt Cache Boundary
OpenClaw splits the system prompt into:
- Stable prefix โ tool definitions, skills metadata, workspace files (ordered to stay byte-identical across turns)
- Volatile suffix โ
HEARTBEAT.md, runtime timestamps, per-turn metadata
If you see unexpected cacheWrite spikes after a config or workspace change, check whether the change lands above or below the cache boundary. Moving volatile content below the boundary often resolves the issue.
Heartbeat Keep-Warm
Keep cache windows warm with periodic heartbeat runs:
agents:
defaults:
heartbeat:
every: "55m"
Per-agent heartbeat is supported at agents.list[].heartbeat.
Context Pruning โ cache-ttl Mode
Trim old tool-result context after cache TTL windows so post-idle requests don’t re-cache oversized history:
agents:
defaults:
contextPruning:
mode: "cache-ttl"
ttl: "1h"
Cache Diagnostics
OpenClaw exposes cache-trace diagnostics for embedded agent runs. For normal diagnostics, use:
/status
/usage full
Live regression tests keep combined gates for Anthropic and OpenAI:
OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_CACHE_TEST=1 pnpm test:live:cache
Tuning Patterns
Mixed traffic (recommended default):
agents:
defaults:
model:
primary: "anthropic/claude-opus-4-6"
models:
"anthropic/claude-opus-4-6":
params:
cacheRetention: "long"
list:
- id: "research"
default: true
heartbeat:
every: "55m"
- id: "alerts"
params:
cacheRetention: "none" # Disable caching on bursty notifier agents
Cost-first baseline:
- Set baseline
cacheRetention: "short" - Enable
contextPruning.mode: "cache-ttl" - Keep heartbeat below your TTL only for agents that benefit from warm caches
7. Sessions and Context Management
OpenClaw organizes conversations into sessions. Each message routes to a session based on its source.
Session Routing
| Source | Behavior |
|---|---|
| Direct messages (DMs) | Shared session by default |
| Group chats | Isolated per group |
| Rooms/channels | Isolated per room |
| Cron jobs | Fresh session per run |
| Webhooks | Isolated per hook |
DM Isolation โ Critical for Multi-User Setups
By default, all DMs share one session. This is dangerous for multi-user setups โ Alice’s private messages would be visible to Bob.
Enable per-user isolation:
{
session: {
dmScope: "per-channel-peer", // isolate by channel + sender
},
}
Options:
main(default) โ all DMs share one sessionper-peerโ isolate by sender across channelsper-channel-peerโ isolate by channel + sender (recommended)per-account-channel-peerโ isolate by account + channel + sender
Link identities across channels for the same person:
{
session: {
identityLinks: [
{
channel: "telegram",
peer: "8691846182",
linkTo: { channel: "whatsapp", peer: "+33612345678" },
},
],
},
}
Session Lifecycle and Resets
Sessions are reused until they expire:
- Daily reset (default) โ new session at 4:00 AM local time on the gateway host
- Idle reset (optional) โ new session after inactivity. Set
session.reset.idleMinutes - Manual reset โ type
/newor/resetin chat./new <model>also switches the model
When both daily and idle resets are configured, whichever expires first wins.
Session Maintenance
OpenClaw automatically bounds session storage:
{
session: {
maintenance: {
mode: "enforce", // warn | enforce
pruneAfter: "30d",
maxEntries: 500,
},
},
}
Preview with:
openclaw sessions cleanup --dry-run
Where Sessions Live
- Store:
~/.openclaw/agents/<agentId>/sessions/sessions.json - Transcripts:
~/.openclaw/agents/<agentId>/sessions/<sessionId>.jsonl
Compaction
When a conversation approaches the model’s context limit, OpenClaw compacts older messages into a summary.
Auto-compaction is on by default. It runs when:
- The session nears the context limit
- The model returns a context-overflow error (compact + retry)
Before compacting, OpenClaw automatically runs a silent memory flush to remind the agent to save important notes to MEMORY.md. This prevents context loss.
Manual compaction:
/compact # Force compaction
/compact Focus on API design decisions # Guide the summary
Using a different model for compaction:
{
agents: {
defaults: {
compaction: {
model: "openrouter/anthropic/claude-sonnet-4-6",
},
},
},
}
Useful when your primary model is local or small and you want better summaries.
Compaction vs Pruning:
| Compaction | Pruning | |
|---|---|---|
| What it does | Summarizes older conversation | Trims old tool results |
| Saved? | Yes (in session transcript) | No (in-memory only) |
| Scope | Entire conversation | Tool results only |
Session pruning is a lighter-weight complement that trims tool output without summarizing.
8. Sub-Agents and Background Work
Sub-agents are background agent runs spawned from an existing agent run. They run in their own isolation and announce results back to the requester chat when finished. Each sub-agent run is tracked as a background task.
Spawn a Sub-Agent
/subagents spawn <agentId> <task>
/subagents spawn linus "Refactor the auth module"
/subagents spawn linus "Refactor the auth module" --model openrouter/openai/gpt-5.4-mini --thinking off
The spawn command is non-blocking โ it returns a run ID immediately. Completion is push-based โ the sub-agent announces its result when done.
Do not poll /subagents list or sessions_history in a loop waiting for completion. That’s wasteful. Completion will announce itself.
Manage Sub-Agents
/subagents list # List active sub-agents
/subagents kill <id|#|all> # Kill a sub-agent
/subagents log <id|#> [limit] [tools] # View sub-agent logs
/subagents info <id|#> # Run metadata (status, timestamps, session id)
/subagents send <id|#> <message> # Send a message to a sub-agent
/subagents steer <id|#> <message> # Steer a sub-agent's direction
Thread-Bound Sub-Agent Sessions
For persistent thread-bound sessions (not one-shot), use the sessions_spawn tool directly or the /focus slash command:
/focus <subagent-label>
/unfocus
/agents
Use Cases for Sub-Agents
- Research โ “Find the latest Spring Boot 3.5 migration docs”
- Code review โ “Review the PR diff in
auth-service/” - Long tasks โ “Generate API docs for all controllers”
- Parallelization โ Spawn multiple sub-agents to tackle independent tasks
Cost Note
Each sub-agent has its own context and token usage. For heavy or repetitive tasks, set a cheaper model for sub-agents:
{
agents: {
defaults: {
subagents: {
model: "openrouter/openai/gpt-5.4-mini",
},
},
},
}
9. Scheduling and Automation
OpenClaw has a built-in cron scheduler that persists jobs, wakes the agent at the right time, and can deliver output back to a chat channel or webhook.
Quick Start
# One-shot reminder
openclaw cron add \
--name "Reminder" \
--at "2026-04-15T16:00:00Z" \
--session main \
--system-event "Reminder: check the cron docs" \
--wake now \
--delete-after-run
# Check jobs
openclaw cron list
# See run history
openclaw cron runs --id <job-id>
Schedule Types
| Kind | CLI Flag | Description |
|---|---|---|
at | --at | One-shot timestamp (ISO 8601 or relative like 20m) |
every | --every | Fixed interval |
cron | --cron | 5-field or 6-field cron expression with optional --tz |
Timestamps without a timezone are treated as UTC. Add --tz America/New_York for local wall-clock scheduling.
Note: Day-of-month and day-of-week use OR logic.
0 9 15 * 1means “9 AM on the 15th OR 9 AM every Monday” โ not both. Use Croner’s+modifier (0 9 15 * +1) to require both conditions.
Execution Styles
| Style | --session Value | Runs In | Best For |
|---|---|---|---|
| Main session | main | Next heartbeat turn | Reminders, system events |
| Isolated | isolated | Dedicated cron:<jobId> | Reports, background chores |
| Current session | current | Bound at creation | Context-aware recurring work |
| Custom session | session:custom-id | Persistent named session | Workflows that build on history |
Delivery and Output
For isolated jobs, choose a delivery mode:
| Mode | What Happens |
|---|---|
announce | Deliver summary to target channel (default for isolated) |
webhook | POST finished event payload to a URL |
none | Internal only, no delivery |
Example โ recurring job with Slack delivery:
openclaw cron add \
--name "Morning brief" \
--cron "0 7 * * *" \
--tz "America/Los_Angeles" \
--session isolated \
--message "Summarize overnight updates." \
--announce \
--channel slack \
--to "channel:C1234567890"
Webhooks
Enable HTTP webhook endpoints for external triggers:
{
hooks: {
enabled: true,
token: "shared-secret",
path: "/hooks",
},
}
POST to wake the main session:
curl -X POST http://127.0.0.1:18789/hooks/wake \
-H 'Authorization: Bearer SECRET' \
-H 'Content-Type: application/json' \
-d '{"text":"New email received","mode":"now"}'
POST to run an isolated agent turn:
curl -X POST http://127.0.0.1:18789/hooks/agent \
-H 'Authorization: Bearer SECRET' \
-H 'Content-Type: application/json' \
-d '{"message":"Summarize inbox","name":"Email"}'
Gmail PubSub Integration
Wire Gmail inbox triggers to OpenClaw:
openclaw webhooks gmail setup --account me@gmail.com
This writes hooks.gmail config, enables the Gmail preset, and uses Tailscale Funnel for the push endpoint.
When hooks.enabled=true and hooks.gmail.account is set, the Gateway auto-starts gog gmail watch serve on boot.
10. Skills and Extensibility
Skills teach the agent how to use tools. Each skill is a directory with a SKILL.md file containing YAML frontmatter and instructions.
Skill Locations and Precedence
OpenClaw loads skills from these sources (highest precedence first):
<workspace>/skillsโ workspace-specific skills<workspace>/.agents/skillsโ project agent skills~/.agents/skillsโ personal agent skills~/.openclaw/skillsโ managed/local skills- Bundled skills โ shipped with the install
skills.load.extraDirsโ extra shared folders (lowest)
If a skill name conflicts across locations, workspace wins.
Installing Skills from ClawHub
ClawHub is the public skills registry: https://clawhub.ai
openclaw skills install <skill-slug> # Install into workspace
openclaw skills update --all # Update all installed skills
Native openclaw skills install installs into the active workspace skills/ directory.
Skill Format
SKILL.md must include YAML frontmatter:
---
name: image-lab
description: Generate or edit images via a provider-backed image workflow
metadata: {"openclaw": {"requires": {"bins": ["uv"]}, "primaryEnv": "GEMINI_API_KEY"}}
---
# Instructions
This skill teaches the agent how to use the image-lab tool...
Gating โ Load-Time Filters
Skills can be gated by environment requirements:
---
name: my-skill
description: Does something cool
metadata: {"openclaw": {"requires": {"bins": ["git"], "env": ["MY_API_KEY"], "config": ["browser.enabled"]}}}
---
Fields under metadata.openclaw:
requires.binsโ list; each binary must exist onPATHrequires.anyBinsโ list; at least one must existrequires.envโ env var must exist or be provided in configrequires.configโ list ofopenclaw.jsonpaths that must be truthyprimaryEnvโ env var name associated withskills.entries.<name>.apiKey
Per-Agent Skill Allowlists
Skill location and skill visibility are separate controls.
- Location decides which copy of a same-named skill wins
- Allowlists decide which visible skills an agent can actually use
{
agents: {
defaults: {
skills: ["github", "weather"],
},
list: [
{ id: "writer" }, // inherits github, weather
{ id: "docs", skills: ["docs-search"] }, // replaces defaults
{ id: "locked-down", skills: [] }, // no skills
],
},
}
Token Impact of Skills
When โฅ1 skill is eligible, OpenClaw injects a compact XML list into the system prompt.
Formula (characters):
total = 195 + ฮฃ (97 + len(name_escaped) + len(description_escaped) + len(location_escaped))
Rough estimate: ~4 chars/token โ 97 chars โ 24 tokens per skill plus field lengths.
11. Multi-Agent Routing
Multi-agent routing lets you run multiple isolated agents (separate workspaces + auth + sessions) in one Gateway, with deterministic inbound routing via bindings.
What Is an Agent?
An agent is a fully scoped “brain” with:
- Workspace โ files,
AGENTS.md,SOUL.md, persona rules - State directory (
agentDir) โ auth profiles, model registry, per-agent config - Session store โ chat history under
~/.openclaw/agents/<agentId>/sessions
Auth profiles are per-agent. Never reuse agentDir across agents.
Bindings โ How Messages Pick an Agent
Bindings are deterministic and most-specific wins:
peermatch (exact DM/group/channel id)parentPeermatch (thread inheritance)guildId + roles(Discord role routing)guildId(Discord)teamId(Slack)accountIdmatch for a channel- Channel-level match (
accountId: "*") - Fallback to default agent (
agents.list[].default, else first entry, default:main)
Example: Two Telegram Bots, Two Agents
{
agents: {
list: [
{ id: "main", workspace: "~/.openclaw/workspace-main" },
{ id: "linus", workspace: "~/.openclaw/workspace-linus", model: "openrouter/z-ai/glm-5.1" },
],
},
bindings: [
{ agentId: "main", match: { channel: "telegram", accountId: "default" } },
{ agentId: "linus", match: { channel: "telegram", accountId: "linus" } },
],
channels: {
telegram: {
accounts: {
default: {
botToken: "",
dmPolicy: "allowlist",
allowFrom: [""],
},
linus: {
botToken: "",
dmPolicy: "allowlist",
allowFrom: [""],
},
},
},
},
}
Each bot has its own botToken and dmPolicy. Both restrict DMs to your Telegram user ID.
Example: WhatsApp Daily Chat + Telegram Deep Work
Route WhatsApp to a fast everyday agent and Telegram to a deeper-thinking agent:
{
agents: {
list: [
{
id: "chat",
model: "anthropic/claude-sonnet-4-6",
},
{
id: "opus",
model: "anthropic/claude-opus-4-6",
},
],
},
bindings: [
{ agentId: "chat", match: { channel: "whatsapp" } },
{ agentId: "opus", match: { channel: "telegram" } },
],
}
Example: Route One DM to a Different Agent
Keep WhatsApp on the fast agent, but route one specific DM to opus:
{
bindings: [
{
agentId: "opus",
match: { channel: "whatsapp", peer: { kind: "direct", id: "+15551234567" } },
},
{ agentId: "chat", match: { channel: "whatsapp" } },
],
}
Peer bindings always win โ keep them above channel-wide rules.
12. Security Best Practices
Authorized Senders
Your Telegram bots already restrict access to you via dmPolicy: "allowlist" and allowFrom: [""]. No changes needed.
If you add bots to Telegram groups, group access is controlled separately by groupPolicy (default: allowlist with no groupAllowFrom), so group messages are also blocked by default.
Workspace Security
- Treat the workspace as private memory. Use a private git repo for backup.
- Do not commit secrets,
.envfiles, API keys, or anything under~/.openclaw/. - Suggested
.gitignore:
.DS_Store
.env
**/*.key
**/*.pem
**/secrets*
Control UI Security
The Control UI is an admin surface (chat, config, exec approvals). Do not expose it publicly.
- Localhost: use
http://127.0.0.1:18789/ - Remote: use Tailscale Serve or an SSH tunnel
- Auth: paste the shared-secret token or password into the UI settings on first connect
Sandbox
For untrusted inputs or risky tools, enable sandboxing:
{
agents: {
defaults: {
sandbox: {
mode: "all", // always sandbox
scope: "agent", // one container per agent
docker: {
setupCommand: "apt-get update && apt-get install -y git curl",
},
},
},
},
}
Note: setupCommand runs once on container creation. The binary must also exist inside the container for skills to work there.
Exec Approvals
For elevated commands (exec host=gateway), review and edit your allowlists regularly:
openclaw exec approvals list
In the Control UI, use the Exec Approvals panel to manage gateway and node allowlists.
Quick Reference
Essential CLI Commands
openclaw gateway # Start the gateway
openclaw gateway --tailscale serve # Start with Tailscale Serve
openclaw dashboard # Open the Control UI
openclaw status --usage # Check token usage
openclaw models list # List configured models
openclaw models scan # Scan OpenRouter free models
openclaw cron list # List cron jobs
openclaw cron add --name "..." ... # Add a cron job
openclaw devices list # List paired devices
openclaw agents list --bindings # List agents with routing
openclaw memory status # Check memory index status
openclaw memory search "query" # Search memory from CLI
openclaw skills install <slug> # Install a skill
openclaw subagents list # (in chat: /subagents list)
openclaw sessions cleanup --dry-run # Preview session maintenance
openclaw doctor # Run diagnostics
Essential Chat Commands
/status # Session status card with tokens and cost
/usage full # Per-message usage footer
/compact # Force compaction
/model # Switch model for this session
/new # Start a fresh session
/new <model> # Fresh session + model switch
/stop # Stop current reply
/subagents spawn ... # Spawn a background agent
/dreaming status # Check dreaming status
/dreaming on|off # Enable/disable dreaming
/focus <id> # Focus on a thread-bound sub-agent
Key Config Paths
~/.openclaw/openclaw.json # Main config
~/.openclaw/agents/<agentId>/agent/auth-profiles.json # Auth profiles
~/.openclaw/agents/<agentId>/sessions/ # Session store
~/.openclaw/cron/jobs.json # Cron jobs
~/.openclaw/openclaw/workspace/ # Default workspace
~/.openclaw/workspace-linus/ # Linus workspace
This guide covers the core concepts. The official docs at https://docs.openclaw.ai/ are the definitive reference for edge cases and advanced configuration.
Mehdi