Architecture
High-Level Overview
OpenClaw is a multi-channel AI assistant platform. At its core, it receives messages from various channels (WhatsApp, Telegram, Discord, Slack, CLI, web, etc.), routes them to an AI agent, executes the agent's tool calls, and sends responses back through the originating channel.
┌─────────────────────────────────────────────────────────────────┐
│ Channels Layer │
│ WhatsApp │ Telegram │ Discord │ Slack │ Web │ CLI │ iMessage │
└─────────────────┬───────────────────────────────────────────────┘
│ inbound messages
▼
┌─────────────────────────────────────────────────────────────────┐
│ Gateway (Control Plane) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌───────────────┐ │
│ │ Routing │ │ Sessions │ │ Config │ │ Plugin │ │
│ │ Engine │ │ Manager │ │ Manager │ │ Registry │ │
│ └────┬─────┘ └────┬─────┘ └──────────┘ └───────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Agent Runner │ │
│ │ System Prompt │ Tool Registry │ LLM Provider │ Sandbox │ │
│ └───────────────────────┬──────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Pi Agent SDK (Inner Loop) │ │
│ │ LLM Call → Parse Response → Execute Tools → Feed Back │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Core Components
1. CLI Layer (src/cli/, src/commands/)
Responsibility: User-facing command-line interface.
src/entry.ts— Bootstrap: suppresses experimental warnings, respawns Node if needed, parses CLI profilessrc/cli/run-main.ts— Entry point after bootstrap; callsrunCli()src/cli/program.ts— Builds the Commander.js program with all subcommandssrc/commands/— 221 command implementations (agents, auth, channels, config, cron, etc.)
The CLI can operate in two modes:
- Interactive (default): Starts a TUI session for direct conversation
- Daemon: Runs as a background service (
openclaw daemon start)
2. Gateway (src/gateway/)
Responsibility: Control plane that orchestrates everything.
The gateway is a WebSocket + HTTP server that:
- Manages channel connections (start/stop/health)
- Routes inbound messages to the correct agent
- Dispatches RPC-style method calls (80+ methods)
- Handles config hot-reload
- Manages device pairing, cron jobs, and node discovery
Key files:
server.impl.ts— Server initialization and lifecycleserver-methods.ts— Method dispatch routerserver-methods/— 50+ method handler files grouped by domain (chat.*,config.*,agents.*, etc.)config-reload.ts— Hot-reload logic for config and plugin changes
Auth scopes control access:
operator.admin— Full accessoperator.write— Config/channel changesoperator.read— Status queriesoperator.approvals— Tool approval workflowsoperator.pairing— Device pairing
3. Channels (src/channels/)
Responsibility: Adapters between messaging platforms and the internal message format.
Two-tier architecture:
Channel Docks (dock.ts) — Lightweight metadata objects (never import heavy dependencies):
capabilities, commands, outbound limits, config adapters,
group policies, mentions, threading, agent prompts
Channel Plugins (plugins/types.plugin.ts) — Full implementations:
type ChannelPlugin = {
id: ChannelId;
meta: ChannelMeta;
capabilities: ChannelCapabilities;
config: ChannelConfigAdapter;
setup?: ChannelSetupAdapter;
security?: ChannelSecurityAdapter;
groups?: ChannelGroupAdapter;
outbound?: ChannelOutboundAdapter;
gateway?: ChannelGatewayAdapter;
messaging?: ChannelMessagingAdapter;
agentPrompt?: ChannelAgentPromptAdapter;
agentTools?: ChannelAgentToolFactory | ChannelAgentTool[];
// ...
}8 built-in channels + 20+ extension channels. Each channel plugin provides its own config schema, setup flow, security adapter, outbound message formatting, and optionally channel-specific tools for the agent.
4. Agent Runner (src/agents/)
Responsibility: Manages agent sessions, builds prompts, registers tools, and drives the agentic loop.
This is the largest component (~375 files). Key subsystems:
- Session management: Persistent session state, write locking, transcript repair
- System prompt construction: Modular prompt builder (
system-prompt.ts) - Tool creation:
pi-tools.ts/openclaw-tools.ts— creates and registers tools with runtime context - Model selection: Auth profiles, failover chains, provider routing
- Sandbox: Configurable execution sandbox for bash tools
- Skills: Load, install, and manage agent skills
The actual LLM interaction is delegated to the Pi agent SDK's session.prompt() method.
5. Routing (src/routing/)
Responsibility: Maps inbound messages to the correct agent and session.
resolveRoute() uses a multi-tier binding chain:
- Direct peer match
- Thread parent fallback
- Guild + roles (Discord)
- Guild match
- Team match
- Account match
- Channel match
- Default agent
Session keys encode the full routing context:
agent:{agentId}:{mainKey}:{channel}:{accountId}:{peerKind}:{peerId}:{dmScope}:{identityLink}
6. Plugin System (src/plugins/)
Responsibility: Extension framework for adding tools, hooks, channels, providers, and gateway methods.
Lifecycle:
- Discovery — Scan
~/.openclaw/plugins/andextensions/directories - Manifest Load — Read
manifest.jsonper plugin - Module Load — Dynamic import via Jiti (handles ESM + CJS)
- API Creation — Factory creates a plugin-specific API object
- Plugin Init — Call the plugin's default export with the API
- Registry Merge — Collect all registrations into a unified registry
Plugins can register: tools, hooks, channels, providers, gateway methods, config schemas.
7. Configuration (src/config/)
Responsibility: Config loading, validation, persistence, and session storage.
- YAML-based primary config file
- Per-agent config overrides
- Session store (JSON files)
- Config hot-reload with file watching
8. Memory (src/memory/)
Responsibility: Conversation memory and context management.
- Memory search via
memory_searchandmemory_gettools - Vector embeddings via SQLite-vec (through extensions)
- Memory files (MEMORY.md, memory/*.md) as persistent knowledge
9. Infrastructure (src/infra/)
Responsibility: Low-level utilities shared across all components.
- Network: TLS, port management, outbound proxying
- System: binary management, paths, runtime guards
- Data: migrations, serialization
- Process: child process management, PTY
10. Web UI (ui/)
Responsibility: Browser-based control panel.
Built with Lit web components. Communicates with the gateway via WebSocket. Provides:
- Chat interface
- Agent/channel management
- Config editing
- Session monitoring
Component Interaction Flow
User sends WhatsApp message
→ Baileys SDK receives message
→ WhatsApp channel plugin normalizes to internal format
→ Gateway receives inbound message event
→ Routing engine resolves: (channel=whatsapp, peer=+1234) → agent "main", session key "agent:main:..."
→ Session manager loads/creates session state
→ Agent runner builds system prompt (identity + skills + memory + channel hints + tools)
→ Agent runner creates tools (bash, read, write, message, web_search, etc.)
→ Pi SDK session.prompt(userMessage)
→ [Inner agentic loop — see 04-agentic-loop.md]
→ Agent produces final text response
→ Gateway dispatches response through WhatsApp outbound adapter
→ Baileys SDK sends message back to user
Data Flow
Inbound
Channel SDK → Channel Plugin → Gateway → Router → Session Manager → Agent Runner → Pi SDK
Outbound
Pi SDK (text/tool_use) → Event Handlers → Gateway → Channel Plugin → Channel SDK
Tool Execution
Pi SDK detects tool_use → Calls registered tool function → Tool executes (bash, file I/O, web, etc.) → Result fed back to Pi SDK → Pi SDK continues loop
Key Abstractions
| Abstraction | Purpose |
|---|---|
ChannelPlugin |
Standardized interface for any messaging platform |
ChannelDock |
Lightweight metadata for fast routing without heavy imports |
OpenClawPluginApi |
Scoped API object given to each plugin for registration |
PluginRegistry |
Unified collection of all registered tools, hooks, channels, providers |
SessionManager |
Persistent session state with write locking |
SystemPromptBuilder |
Modular, section-based prompt assembly |
EmbeddedRunAttempt |
Single agent execution attempt with full lifecycle |