OpenClaw agent runtime architecture is the ownership map behind every agent run. It answers a question that sounds boring until it breaks in production: which part of the system owns the model loop, which part owns provider transport, which part owns session state, and where can plugins safely attach?
That separation matters because an AI agent host is not just a wrapper around a model API. It has to admit work from channels, build context, pick a model, call tools, manage transcripts, compact long sessions, stream events, enforce policy, and return a final result. If all of that lives in one fuzzy “agent” box, debugging becomes guesswork.
OpenClaw’s docs take the more useful route. They split the runtime into named code areas with clear jobs. The built-in runtime lives under src/agents/. Model and provider transport live under src/llm/. Plugin-facing contracts are exposed through openclaw/plugin-sdk/* barrels. That tells maintainers where to work, and it tells plugin authors where not to reach.
What the OpenClaw agent runtime architecture actually owns
An agent runtime owns the prepared model loop. In OpenClaw terms, that means it receives the prompt, drives model output, handles native tool calls, and returns the finished turn to the host.
That is separate from four nearby layers that people often mix together:
- Provider: how OpenClaw authenticates, discovers models, and names model references, such as
openai,anthropic, orgithub-copilot. - Model: the model selected for the turn, such as an
openai/*oranthropic/*ref. - Agent runtime: the loop or backend that executes the prepared turn, such as
openclaw,codex,copilot, or a CLI backend. - Channel: where messages enter and leave, such as Slack, Telegram, Discord, iMessage, WhatsApp, cron, or a web UI.
Once you keep those layers apart, OpenClaw’s runtime design starts to make sense. A provider is not a runtime. A model prefix is not a runtime. A channel is not a runtime. The runtime is the execution owner for the prepared agent turn.
Runtime code is not provider code
The most practical line in the docs is also the easiest to miss: runtime code lives under src/agents/, while model/provider transport lives under src/llm/.
That split keeps two kinds of complexity from contaminating each other. Provider transport has to know about model registries, request formats, stream implementations, endpoint quirks, and auth. Runtime code has to know about attempts, tool calls, transcripts, sessions, compaction, and host policy. Those are related, but they are not the same job.
This is why “use OpenAI” and “use Codex runtime” are not interchangeable statements in OpenClaw. openai is a provider prefix. codex is a runtime id when the Codex adapter is selected. A normal openai/* model route can run through different runtime behavior depending on endpoint facts, auth, and runtime policy.
That may feel strict. Good. Strict naming is cheaper than a night spent wondering why a turn used the wrong tool loop.
The main directories, in plain English
The architecture page names the important runtime areas. Here is the working mental model.
embedded-agent-runner: the built-in attempt loop
src/agents/embedded-agent-runner/ owns the built-in attempt loop. It covers run.ts, model selection and provider normalization, per-provider request parameters, compaction, transcript wiring, and session wiring.
That is the heart of the built-in OpenClaw runtime. When the host needs to run an agent turn without handing execution to a plugin runtime, this is where the built-in path lives. It is also where many production-grade details gather: retries, normalized model behavior, transcript attachment, and context length pressure.
sessions: persistence, resources, prompts, and tools
src/agents/sessions/ owns session persistence and resource loading. The docs call out session-manager.ts, package-manager.ts, resource-loader.ts, in-session extensions, prompt templates, skills, themes, and TUI-backed tool renderers.
This is where OpenClaw’s runtime stops being an isolated API call. A run belongs to a session. That session can carry transcript history, loaded resources, selected prompts, skills, tool renderers, and package-provided extensions. For an operator, this is the difference between “the model answered” and “the agent continued the right conversation with the right tools.”
agent-core: reusable contracts
packages/agent-core/ is the reusable @openclaw/agent-core package. It contains the agent loop, runtime adapter types, messages, compaction helpers, prompt templates, skills, and session storage contracts.
The important word is contracts. This package is where runtime behavior becomes reusable without forcing every caller to import private app internals. It gives the runtime a common language for messages, adapters, prompts, compaction, and storage.
runtime, agent-tools, agent-hooks, and runtime selection
src/agents/runtime/ is the facade that wires @openclaw/agent-core to the plugin SDK LLM runtime. It also re-exports local proxy utilities. In plain English, it is the bridge between reusable core contracts and OpenClaw’s plugin-facing runtime surface.
src/agents/agent-tools*.ts owns OpenClaw tool definitions, parameter schemas, tool policy, before/after tool-call adapters, and host or sandbox edit tools. This is where tool calling becomes governed behavior, not an accidental list of functions.
src/agents/agent-hooks/ holds built-in runtime hooks such as compaction safeguards, compaction instructions, and context pruning. Hooks sit close to the runtime because they shape how a turn is prepared and protected.
src/agents/harness/ owns the runtime registry, selection policy, and lifecycle for the built-in runtime and plugin-registered runtimes. If a runtime can be selected, registered, or rejected, this layer is involved.
Why plugin boundaries matter
OpenClaw draws a hard line around plugin access. Core can call the built-in runtime through OpenClaw modules and SDK barrels. Plugins use documented openclaw/plugin-sdk/* entrypoints. They do not import src/** internals.
That rule is not bureaucracy. It is how a host keeps plugin support from turning into accidental coupling. If a plugin imports an internal file path, it is binding itself to private layout, private assumptions, and private churn. One refactor later, the plugin breaks or, worse, keeps working with stale behavior.
The SDK barrel gives plugin authors a supported contract. Internals can move. The contract has to stay honest. That is the bargain.
How runtime selection works
The built-in runtime id is openclaw. The legacy alias pi normalizes to openclaw. The legacy codex-app-server name normalizes to codex.
Runtime policy is configured through agentRuntime.id on provider or model entries. Model-level policy wins over provider-level policy. If the setting is missing or says default, OpenClaw resolves it to auto.
In auto mode, OpenClaw selects a registered plugin runtime only when it supports the effective provider route. If nothing claims the route, the built-in OpenClaw runtime runs it.
That last detail is worth spelling out: a provider or model prefix alone never selects an execution adapter. A string like openai/* names a model route. It does not automatically mean “run this through Codex.”
OpenAI has one special path. OpenClaw may select the codex runtime implicitly for exact official HTTPS Platform Responses or ChatGPT Responses routes with no authored request override. Completions adapters, custom endpoints, authored request behavior, and plaintext official HTTP endpoints do not get that implicit Codex path. Some stay on openclaw; plaintext official HTTP is rejected.
This is the kind of rule that seems fussy until you run mixed auth, custom endpoints, and plugin runtimes on the same host. Runtime selection has to be deterministic, or the operator cannot trust what happened.
Prepared runtime generations prevent stale state
OpenClaw also builds prepared model runtime generations. Gateway startup and config, plugin, or auth publication create one prepared generation per configured agent. That generation owns the discovered auth template, model registry, and projected model catalog as one atomic snapshot.
Agent runs then fork mutable auth and registry stores from that snapshot. Other surfaces, such as browse, status, cron, doctor, TUI, PDF, and image paths, read the published catalog instead of repeating filesystem discovery each time.
The practical value is consistency. A failed or stale generation is not served beside a newer partial generation. The lifecycle owner has to publish a complete replacement first. That is boring in the best way. It means an agent run should not see half-old auth, half-new model data, and a plugin registry that changed underneath it.
Resource manifests keep packages predictable
Resource packages can declare OpenClaw resources in package.json metadata. The supported entries include extensions, skills, prompts, and themes. Each entry is a file path or glob relative to the package root.
{
"openclaw": {
"extensions": ["extensions/index.ts"],
"skills": ["skills/*.md"],
"prompts": ["prompts/*.md"],
"themes": ["themes/*.json"]
}
}
If a resource type is not listed, OpenClaw falls back to conventional directories with the same names. That gives package authors a clear default path while still letting more structured packages be explicit.
For an agent runtime, this matters because resources are part of the run surface. Skills, prompts, themes, and extensions influence what the agent sees and how the session behaves. Runtime architecture has to make resource loading repeatable, not magical.
How OpenClaw compares with other agent runtime ideas
LangGraph presents itself as a low-level orchestration framework and runtime for long-running, stateful agents. It focuses on durable execution, streaming, persistence, human-in-the-loop work, and mixing deterministic steps with model-driven steps.
OpenAI’s Agents SDK takes a smaller-primitives approach: agents, tools, handoffs, guardrails, sessions, and tracing. It is useful when you want the SDK to manage turns, tool execution, guardrails, handoffs, and session behavior.
Anthropic’s agent guidance is more cautionary. Start with the simplest useful system, then add agentic complexity only when it earns its keep. Agents trade latency and cost for better task performance, so the architecture should stay understandable.
OpenClaw fits into that conversation from a different angle. It is not only asking, “How do I build an agent loop?” It is asking, “How does a self-hosted gateway decide which runtime owns this turn, which provider route supplies the model, which plugin boundary is legal, and which state snapshot the run can trust?”
That is a host-level problem. And for a self-hosted agent gateway, host-level problems are the product.
When this architecture helps most
The OpenClaw agent runtime architecture matters most when one installation has more than one model route, more than one channel, or more than one runtime option.
A simple single-agent toy can hide the distinction. The same code receives a message, calls a model, maybe calls a tool, and replies. But a real OpenClaw host may receive a Slack message, an iMessage reply, a cron event, and a browser or file task. It may have OpenAI, Anthropic, local models, Codex, plugin runtimes, and CLI backends in play.
At that point, runtime ownership cannot be vibes. You need stable rules:
- Provider transport stays under
src/llm/. - The built-in runtime stays under
src/agents/. - Reusable runtime contracts live in
@openclaw/agent-core. - Plugins use SDK barrels instead of private internals.
- Runtime selection follows provider/model-scoped policy and registered runtime support.
- Prepared runtime generations publish complete snapshots before runs use them.
Those rules make the system easier to reason about when something fails. Was it auth? Provider transport? Runtime selection? Harness support? Tool policy? Session resource loading? The architecture gives you places to look.
Common mistakes to avoid
The first mistake is treating provider and runtime as the same layer. They are not. openai is a provider prefix. codex is a runtime id. The route, endpoint, auth, authored request behavior, and runtime policy decide what actually runs.
The second mistake is letting plugins import private source paths. That works until it does not. Use the plugin SDK barrels. If the SDK does not expose what a plugin needs, that is a contract discussion, not a reason to grab an internal file.
The third mistake is ignoring runtime generations. Model and auth discovery are not harmless background details. If a run can see partial state, it can fail in ways that are miserable to reproduce. OpenClaw’s snapshot approach exists to keep those changes atomic.
FAQ
What is the built-in OpenClaw runtime id?
The built-in runtime id is openclaw. The old pi alias normalizes to openclaw.
Does an openai/* model automatically use Codex?
No. openai/* is a model route. Codex can be selected when a compatible registered runtime supports the effective route, or implicitly for the exact official HTTPS Responses paths described in the docs. A provider prefix by itself does not select an execution adapter.
Where do OpenClaw tools live?
OpenClaw-owned tool definitions, schemas, policy, before/after adapters, and host or sandbox edit tools live in src/agents/agent-tools*.ts.
Why does OpenClaw keep provider transport under src/llm/?
Provider transport is about model discovery, request formats, streams, and provider-specific behavior. Runtime code is about the agent loop, sessions, tools, compaction, transcripts, hooks, and execution adapters. Keeping those apart makes runtime selection and debugging clearer.
What are prepared runtime generations?
They are atomic snapshots built at gateway startup or when config, plugin, or auth state is published. Each generation owns the discovered auth template, model registry, and projected model catalog for a configured agent. Runs fork mutable stores from that snapshot.
Bottom line
OpenClaw agent runtime architecture is not just a folder map. It is a set of ownership boundaries. The built-in loop, provider transport, reusable core contracts, plugin entrypoints, runtime selection, and prepared snapshots each have a job.
That is exactly what a self-hosted agent gateway needs. Models can change. Providers can change. Plugins can arrive. Channels can multiply. The runtime still needs to know who owns the turn.
If you are running OpenClaw in production, read the architecture this way: not as trivia about directories, but as the operating manual for debugging agent runs without guessing.

