OpenClaw Code Deep Dive Part 1: The Architecture Behind 200K Stars
OpenClaw has 200K+ GitHub stars, a Wikipedia page, and a creator who just joined OpenAI. But strip away the narrative and you’re left with a question: what does the code actually do?
We cloned the repo and read the source. This 3-part series covers what we found in 209,000 lines of TypeScript.
- Part 1 (this post): Architecture — monorepo layout, agent runtime, gateway, routing
- Part 2: Skills, Memory & Tools
- Part 3: Security, Quality & Verdict
Repository at a Glance
OpenClaw is a pnpm monorepo targeting Node.js 22+ (ESM-only, TypeScript 5.9 strict mode).
| Directory | Purpose | Scale |
|---|---|---|
src/ |
Core runtime | ~50 dirs, ~800 files |
extensions/ |
Channel adapters, memory backends, auth | 37 plugins |
skills/ |
Bundled skill definitions (Markdown) | 52 skills |
apps/ |
macOS, iOS, Android companions | 3 apps |
packages/ |
Legacy name shims (Clawdbot, Moltbot) | 2 packages |
ui/ |
React-based web interface (A2UI) | 1 package |
Key dependencies: Express 5.2, Zod 4.3, Vitest 4.0, oxlint, sharp, grammy (Telegram), @slack/bolt, discord.js, @whiskeysockets/baileys (WhatsApp), playwright-core.
75+ direct dependencies. pnpm workspaces keep it organized.
The Biggest Finding: OpenClaw Doesn’t Implement Its Own Agent Loop
This is the most important architectural insight.
The core LLM interaction cycle — prompt construction, streaming, tool execution, error recovery — is entirely delegated to @mariozechner/pi-agent-core, a pre-1.0 package from a separate repository (github.com/badlogic/pi-mono by Mario Zechner).
OpenClaw uses four packages from pi-mono:
| Package | Version | Purpose |
|---|---|---|
pi-agent-core |
0.53.0 | Stateful agent loop, tool execution, event streaming |
pi-ai |
0.53.0 | Unified LLM API for 17+ providers |
pi-coding-agent |
0.53.0 | File operations, shell tools, grep/find |
pi-tui |
0.53.0 | Terminal UI |
The agent lifecycle flows through pi-agent-core:
agent_start → turn_start → message_start → message_update* → message_end
→ [tool_execution_start → tool_execution_update* → tool_execution_end]*
→ turn_end → agent_endFeatures like steer() (mid-run interruption), followUp() (queued work), abort(), thinking budgets, and tool error self-correction — all pi-agent-core.
So what does OpenClaw actually build? Everything around that loop: routing, channels, skills, memory, sandboxing, and the gateway.
The Gateway: 161 Files of Control Plane
Everything flows through a WebSocket + HTTP server. Default bind: ws://127.0.0.1:18789 (loopback only).
Authentication (4 modes)
src/gateway/auth.ts → authorizeGatewayConnect()| Mode | Use Case |
|---|---|
none |
Development only |
token |
Bearer token matching |
password |
Password-based auth |
trusted-proxy |
Proxy header validation |
All secret matching uses constant-time comparison (safeEqualSecret()). Rate limiting is per-IP with configurable scopes. Tailscale integration provides secure LAN access.
Chat Session Management
Three registries power the chat system:
- ChatRunRegistry — Maps session IDs to active chat runs (queue-based).
- ChatRunState — Aggregates buffers, delta timing, and abort tracking.
- ToolEventRecipientRegistry — Tracks WebSocket clients receiving tool events (TTL-based, 10min default).
Text deltas are throttled at 150ms minimum intervals. Heartbeat suppression prevents noisy UI updates during background operations. The dropIfSlow backpressure mechanism protects against slow consumers.
Boot Sequence
On startup, the gateway reads a BOOT.md file from the workspace and executes it as an agent prompt — enabling automated startup tasks like sending notifications or checking status. The boot creates an ephemeral session (boot-{timestamp}-{uuid}), runs the agent, then restores the original session mapping.
Routing: 8 Priority Levels
Messages from channels hit a tiered routing system in src/routing/resolve-route.ts:
| Priority | Match Type | Example |
|---|---|---|
| 1 | Direct Peer Binding | Thread/DM → specific agent |
| 2 | Parent Peer Inheritance | Reply in thread → parent’s agent |
| 3 | Guild + Roles | Discord guild + member role |
| 4 | Guild Only | Discord guild, any role |
| 5 | Team Binding | Slack workspace |
| 6 | Account Pattern | Account-level routing |
| 7 | Channel Default | Wildcard per channel |
| 8 | Global Default | Configured fallback |
Each route produces two session keys:
sessionKey— Full context (peer, account, channel)mainSessionKey— Simplified key for direct-chat collapsing
Sessions track model overrides, reasoning depth, send policy, and full transcript history. Persistence uses file-backed storage with atomic writes.
What This Means
OpenClaw’s architecture is a hub-and-spoke gateway pattern:
- Channels connect inbound (37 adapters via extensions).
- The gateway authenticates, rate-limits, and routes.
- The routing engine resolves which agent handles the message.
- The agent runtime (pi-agent-core) does the LLM work.
- Responses flow back through the gateway to the originating channel.
This is closer to Nginx for AI agents than a standalone AI framework. The gateway is well-engineered — authentication, session management, event broadcasting, and backpressure handling are all production-grade patterns.
But the most critical piece — the agent loop itself — lives in a pre-1.0 external dependency.
Next: Part 2 — Skills, Memory & Tools covers the SKILL.md system, hybrid memory search, 70 agent tools, and the plugin hook architecture.
Analysis based on OpenClaw v2026.2.18. Source: github.com/openclaw/openclaw.