OpenClaw architecture: where the tokens actually go.

Updated 2026-07-16

OpenClaw looks like a chatbot from the outside and is an agent runtime on the inside: a gateway control plane, channel adapters, a per-turn agent loop, session transcripts on disk, and skills injected into the system prompt. Understanding which component triggers LLM calls, and with how much context, is what makes the runtime predictable and the bill explainable.

Quick answer: four layers, one of which spends money.

OpenClaw decomposes into four layers. The gateway is a long-running control plane, a WebSocket server bound to 127.0.0.1:18789 by default, that owns sessions, configuration, cron jobs, webhooks, and channel routing. Channel adapters log into WhatsApp, Telegram, Discord, and other platforms and normalize their messages into one internal shape. The agent runtime executes turns: OpenClaw embeds pi, a minimal agent runner, which drives the model-and-tools loop over RPC with streaming. And storage is refreshingly plain: every conversation is a JSONL transcript on disk under ~/.openclaw/agents/<agentId>/sessions/, which is why sessions survive restarts. Only the third layer talks to a model. The gateway routes, the adapters translate, the disk remembers; every token you pay for is emitted from inside the agent loop. That single fact organizes everything else on this page: to reason about cost, latency, or failure, find the loop, not the gateway.

The agent loop, step by step.

A message arriving from any channel becomes a run. The docs describe the sequence precisely: the agent RPC validates parameters, resolves the session, and immediately acknowledges with a run id; the command layer resolves which model will serve the turn and loads the skill snapshot; then the embedded runner takes over, serializing the run through a per-session queue, acquiring the session write lock, and preparing the transcript before anything streams. Inside the runner is the classic agentic loop. The model receives the assembled context, the system prompt plus conversation history, and responds with either tool calls or text. Tool calls are executed, their results are appended, and the context is resubmitted. The loop repeats until the model returns a text-only response, which ends the turn; assistant deltas and tool lifecycle events stream out to the channel as they happen. Two loop properties matter operationally. Runs serialize per session, so one conversation cannot race itself, and a slow turn queues the next message rather than dropping it. And the loop is bounded by watchdogs rather than optimism: the docs describe a default run timeout measured in hours plus model idle watchdogs, so a wedged upstream eventually surfaces as an error instead of a silent hang.

What actually enters the context window.

The compounding effect is the part newcomers miss: every loop iteration re-sends the accumulated context. A turn that chains four tool calls does not pay for its context once, it pays roughly five times as the transcript grows, which is why tool-heavy turns dominate token spend and why the model serving those turns is the main cost decision in the whole system.

  • The system prompt is assembled per run from OpenClaw's base prompt, the skills prompt, and bootstrap context files, plus any per-run overrides. It is rebuilt, not hand-written, so its size is a function of your config.
  • Skills are injected as a compact XML block listing each eligible skill's name and description, roughly two dozen tokens per skill plus fixed overhead. The full SKILL.md body is read on demand, not preloaded.
  • Conversation history rides along on every model request within the session scope you configured (per-peer, per-channel-peer, and so on), until compaction summarizes it.
  • Tool results are appended into context as the loop iterates; the runtime sanitizes oversized and binary payloads, but a chatty tool still bloats the turn.
  • Auto-compaction kicks in as context grows: earlier history gets summarized so the session can continue, an LLM operation in its own right that also spends tokens.

Sessions, scope, and the transcript on disk.

Each session is one JSONL file: user inputs, assistant output, tool calls, tool results, one line each, appended as they happen. This design carries three consequences. Durability is free, a gateway restart resumes exactly where the transcript left off. Debugging is transparent, you can read the actual context evolution of any conversation with less. And privacy is local, transcripts live on your machine, not a vendor's. Session scope is configuration, not convention: the session config decides whether each peer, channel, or account gets an isolated conversation, and reset policies (daily resets, idle expiry) bound how much history a session can accumulate. Those settings are quietly also cost settings, because history length times message frequency is the input-token bill. A shared main session across channels reads as magical continuity and pays for it on every turn.

Pay-as-you-go · transparent per-model pricing

Selected models are priced below official list prices. Exact input, output, cache, and per-request prices are shown for each model.

ModelOfficial PriceOur Price
Claude Opus 4.7$5.00 / $25.00 per M$4.00 / $20.00 per M
Claude Sonnet 4.6$3.00 / $15.00 per M$2.40 / $12.00 per M
Claude Haiku 4.5 20251001$1.00 / $5.00 per M$0.80 / $4.00 per M
GPT-5.5$5.00 / $30.00 per M$4.00 / $24.00 per M

Sizing models per component.

Because all model traffic funnels through the provider config, and refs are provider/model-id strings, sizing is a routing exercise. The components worth sizing separately: Interactive turns, the primary slot. This is the assistant's personality and competence; claude-sonnet-4-6 is the balanced pick, with claude-opus-4-7 as the premium option for installs whose turns are genuinely hard. The primary serves the tool-heavy loops too, so its per-token price multiplies across loop iterations, not just messages. Scheduled and background runs. Cron jobs, heartbeat-style check-ins, and monitoring tasks run without a human waiting, and their prompts are usually formulaic. claude-haiku-4-5-20251001 grade models serve these at a fraction of flagship cost; pointing a cron agent at the same Opus that serves your hardest interactive work is the most common silent overspend. Fallbacks. The fallbacks list is availability engineering: a different family behind the same gateway (gpt-5.5 backing a Claude primary, or the reverse) keeps the assistant answering through any one vendor's incident, and one key covers both. Escalations. Allowlist a flagship in agents.defaults.models so /model can pull it into a single session when a task earns it, then let the session revert. That gets flagship quality on demand without flagship rates as a default.

Where the architecture bites, and what to watch.

A useful weekly ritual: skim the per-model usage in your APIsRouter console against your mental model of the install. If the cron agent's model shows interactive-scale spend or the flagship shows daily-driver volume, the routing policy and reality have drifted, and the fix is two strings in openclaw.json.

  • Per-session serialization means one long tool loop delays everything queued behind it in that conversation; if a channel feels unresponsive, inspect the running turn before the gateway.
  • Skill sprawl inflates every turn: each eligible skill adds its description tokens to every run's system prompt. Gate skills per agent instead of loading the world.
  • Compaction is lossy by design: after a summarize, the model knows the summary, not the transcript. Durable facts belong in workspace files the agent re-reads, not in conversation history.
  • Tool results are billed context: a tool that returns a whole file when a line would do taxes every subsequent loop iteration of the turn.
  • The gateway is a 24/7 process on your hardware: channel sessions drop when the host sleeps, which looks like model failure but is one layer down.
  • Hot reload applies config safely but per-domain: model and provider edits hot-apply, gateway port and auth changes need a restart, and openclaw doctor arbitrates when validation rejects an edit.

Why a multi-model gateway fits this architecture.

OpenClaw's design assumes model plurality: refs are provider-qualified strings, primaries have fallback lists, sessions can switch models mid-conversation, and nothing in the loop cares which vendor answered. What it does not do is make acquiring five vendor accounts pleasant. A gateway collapses that: one provider block, one key, and every sizing decision above becomes a string choice inside a single catalog, Claude for turns, a budget id for cron, a GPT fallback, a flagship on the allowlist. The per-request usage log then gives the architecture its missing observability layer, per-model, per-key spend that maps one-to-one onto the components this page described. The custom model integration guide linked below has the exact config; the architecture is what makes that config worth tuning.

FAQ

Where does OpenClaw actually call the LLM?

Only inside the agent loop. The embedded pi runner assembles context (system prompt, skills block, history), sends it to the configured model, executes any tool calls, and resubmits until the model returns text only. The gateway, channel adapters, and session storage never touch a model.

What is the pi runner in OpenClaw?

The minimal coding-agent runtime OpenClaw embeds to execute turns. It runs in RPC mode with tool and block streaming: the gateway hands it a run, it drives the model-tools loop, streams deltas and tool events back, and the gateway routes them to the originating channel.

How does OpenClaw store conversations?

As JSONL transcripts on disk, one file per session under ~/.openclaw/agents/<agentId>/sessions/. Every user input, assistant reply, tool call, and tool result is a line. Sessions survive gateway restarts, and you can read a transcript directly to debug context evolution.

Why do tool-heavy OpenClaw turns cost so much more?

Each loop iteration re-sends the accumulated context: system prompt, skills block, history, and all prior tool results of the turn. A turn with four tool calls pays for its context roughly five times. That multiplication is why the primary model's per-token price matters more than message count.

Do skills make every request more expensive?

Modestly and linearly: each eligible skill injects a compact description, around two dozen tokens, into every run's system prompt, with full SKILL.md bodies read only on demand. Dozens of always-eligible skills add real overhead, which is why per-agent skill allowlists exist.

What is the best model setup for OpenClaw?

Split by component: a balanced primary like claude-sonnet-4-6 for interactive turns, a budget id for cron and background runs, a different-family fallback like gpt-5.5, and a flagship on the /model allowlist for escalations. Through one gateway key, that whole policy is config, and the console shows whether it holds.