Skip to content

Master the OpenClaw Agent Loop: End-to-End Execution Guide

Ever felt like your AI agent is a black box? You send a message, wait, and hope it doesn’t get stuck or break something. Understanding the actual execution path—the “Agent Loop”—is the key to building reliable agentic workflows that you can actually trust in production.

An agentic loop is the full run of an agent: intake, context assembly, model inference, tool execution, streaming replies, and persistence. In OpenClaw, a loop is a single, serialized run per session that emits lifecycle and stream events as the model thinks and acts. This is how that loop is wired end-to-end.

You can start an agent loop through a few different doors. The Gateway RPC uses agent and agent.wait. If you are working in the terminal, you can use the CLI agent command.

The process follows a specific sequence to turn your input into a finished response:

  1. The agent RPC validates your parameters and resolves the session using a sessionKey or sessionId. It saves the session metadata and returns { runId, acceptedAt } immediately.
  2. The agentCommand runs the agent. It picks the model and thinking defaults, loads your skills snapshot, and calls runEmbeddedPiAgent. It also handles lifecycle end or error events if the core loop misses them.
  3. runEmbeddedPiAgent handles the heavy lifting. It serializes runs through session and global queues, builds the session, and subscribes to events. It also tracks usage and enforces timeouts.
  4. subscribeEmbeddedPiSession bridges internal events to the OpenClaw agent stream. It maps tool events to stream: "tool", assistant deltas to stream: "assistant", and lifecycle events to stream: "lifecycle".
  5. agent.wait uses waitForAgentJob to stay active until the runId hits a lifecycle end or error. It returns the final status and timing data.

To keep your session history consistent, runs are serialized per session key. This “session lane” prevents tool or session races. Messaging channels can choose different queue modes like collect, steer, or followup to feed this system. You can find more details in the Command Queue documentation.

Before the model starts thinking, the system prepares the environment. It resolves the workspace and might redirect sandboxed runs to a specific sandbox root. It loads skills from a snapshot and injects them into the environment. Finally, it acquires a session write lock and opens the SessionManager before any streaming begins.

The system prompt is a combination of several parts: the OpenClaw base prompt, skills prompts, bootstrap context, and any overrides for that specific run. The system also enforces model-specific limits and reserves tokens for compaction. You can see exactly what the model sees in the System prompt guide.

OpenClaw gives you two ways to jump into the loop and change how things work.

These are event-driven scripts for commands and lifecycle events.

  • agent:bootstrap: This runs while building bootstrap files. You can use it to add or remove context files before the system prompt is finished.
  • Command hooks: These handle events like /new, /reset, or /stop.

Check the Hooks doc for setup details.

These hooks run inside the agent loop or the gateway pipeline:

  • before_model_resolve: Runs before the session starts so you can override the provider or model.
  • before_prompt_build: Runs after the session loads. You can use prependContext for dynamic text or use system-context fields for stable guidance.
  • before_agent_start: A legacy hook for compatibility.
  • before_agent_reply: Runs after actions but before the LLM call. A plugin can use this to send a synthetic reply or silence the turn.
  • agent_end: Lets you inspect the final message list and metadata.
  • before_compaction / after_compaction: Used to observe compaction cycles.
  • before_tool_call / after_tool_call: Lets you intercept tool parameters or results.
  • before_install: Inspects built-in scan findings to block skill or plugin installs.
  • tool_result_persist: Transforms tool results before they are written to the transcript.
  • message_received / message_sending / message_sent: Hooks for inbound and outbound messages.
  • session_start / session_end: Marks session boundaries.
  • gateway_start / gateway_stop: Marks gateway lifecycle events.

If you are building guards, remember these rules:

  • In before_tool_call or before_install, setting { block: true } stops the process.
  • In message_sending, setting { cancel: true } stops the message.

Detailed API info is in the Plugin hooks documentation.

Assistant deltas stream from the core and show up as assistant events. The system can emit partial replies on text_end or message_end. Reasoning can also be sent as a separate stream or as part of the block replies. You can read more about chunking in the Streaming guide.

When a tool runs, you get start, update, and end events on the tool stream. The system cleans up tool results by checking size and image payloads before logging them. It also tracks messaging tools to make sure the assistant doesn’t send duplicate confirmations.

The final output is built from assistant text, reasoning, and tool summaries. If the model errors, the system includes that error text. The system filters out NO_REPLY tokens so they don’t reach the user. It also removes duplicate messaging tool payloads. If there is nothing to show but a tool failed, it sends a fallback error reply.

When a conversation gets too long, auto-compaction triggers. This emits a compaction event and can start a retry. During a retry, the system resets in-memory buffers and tool summaries to prevent double outputs. See the Compaction guide for the full pipeline.

The system currently supports these stream types:

  • lifecycle: Handles start, end, and error phases.
  • assistant: Sends streamed deltas from the model.
  • tool: Sends streamed tool events.
  • compaction: Notifies you of compaction cycles.

For chat interfaces, assistant deltas are gathered into delta messages. A final chat message is sent once the lifecycle hits an end or error state.

The agent.wait call has a default timeout of 30 seconds, which you can change with the timeoutMs parameter. The actual agent runtime is much longer, defaulting to 48 hours, and is managed by an abort timer in the core runtime.

A run can stop for a few reasons:

  • The agent hits its runtime timeout.
  • An AbortSignal cancels the run.
  • The gateway disconnects or the RPC times out.
  • The agent.wait call times out (though this doesn’t stop the agent itself).

AI Setup Assistant

OpenClaw

OpenClaw Expert

Still stuck?

If this page didn't answer your case, ask OpenClaw Expert for step-by-step guidance.