CodeDocs Vault

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.

The CLI can operate in two modes:

2. Gateway (src/gateway/)

Responsibility: Control plane that orchestrates everything.

The gateway is a WebSocket + HTTP server that:

Key files:

Auth scopes control access:

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:

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:

  1. Direct peer match
  2. Thread parent fallback
  3. Guild + roles (Discord)
  4. Guild match
  5. Team match
  6. Account match
  7. Channel match
  8. 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:

  1. Discovery — Scan ~/.openclaw/plugins/ and extensions/ directories
  2. Manifest Load — Read manifest.json per plugin
  3. Module Load — Dynamic import via Jiti (handles ESM + CJS)
  4. API Creation — Factory creates a plugin-specific API object
  5. Plugin Init — Call the plugin's default export with the API
  6. 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.

8. Memory (src/memory/)

Responsibility: Conversation memory and context management.

9. Infrastructure (src/infra/)

Responsibility: Low-level utilities shared across all components.

10. Web UI (ui/)

Responsibility: Browser-based control panel.

Built with Lit web components. Communicates with the gateway via WebSocket. Provides:

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