Agent Loop
Agent loop lifecycle, flow, and wait semantics.
The agent loop is the agent's complete "true" run: ingestion β context assembly β model inference β
tool execution β streaming reply β persistence. This is the authoritative path for delivering messages
converted into actions and final answers while maintaining session state consistency.
In OpenClaw, the loop is a single serialized run per session that emits lifecycle and stream events
as the model thinks, calls tools, and streams output. This document explains how the real loop goes
end-to-end wire.
Entry Points
- Gateway RPC: ''agent'' and ''agent.wait''.
- CLI: ''agent'' command.
How it works (high-level)
1. ''agent'' RPC validates arguments, resolves session (sessionKey/sessionId), saves session metadata, returns immediately ''{ runId, acceptedAt }''.
2. ''agentCommand'' runs the agent:
- Resolves model+think/verbose defaults
- Loads skill snapshot
- Calls ''runEmbeddedPiAgent'' (pi-agent-core runtime)
- Emits lifecycle end/error if embedded loop didn't emit one
3.''runEmbeddedPiAgent'':
- Serializes runs per-session+global queue
- Resolves model+auth profiles and builds pi session
- Subscribes to pi events and streams assistant/tool deltas
- Enforces timeout β aborts run if exceeded
- Returns payload+usage metadata
4. ''subscribeEmbeddedPiSession'' bridges pi-agent-core events to OpenClaw ''agent'' stream:
- Tool events => ''stream: "tool"''
- Assistant deltas => ''stream: "assistant"''
- Lifecycle events => ''stream: "lifecycle"'' (''phase: "start" | "end" | "error"'')
5. ''agent.wait'' uses ''waitForAgentJob'':
- Waits for ''lifecycle end/error'' for ''runId''
- Returns ''{ status: ok|error|timeout, startedAt, endedAt, error? }''
Queue+Concurrency
- Runs are serialized per session key (session channel) and optionally via global channel.
- This prevents tool/session races and keeps session history consistent.
- Messaging channels can optionally queue mode for that channel system (collect/lead/follow).
See ''Command Queue''.
Session + Workspace Preparation
- Workspace is resolved and created; sandbox runs may redirect to sandbox workspace root.
- Skills are loaded (or reused from snapshot) and injected into environment and prompts.
- Bootstrap/context files are resolved and injected into system prompt report.
- Session write lock is acquired; ''SessionManager'' is opened and ready before streaming.
Prompt Assembly+System Prompt
- System prompt is built from OpenClaw's base prompt, skill prompts, bootstrap context, and per-run overrides.
- Model-specific limits and compaction reserve tokens are enforced.
- See ''System Prompt'' for what the model sees.
Hook Points (where you can intercept)
OpenClaw has two hook systems:
- Internal Hooks (gateway hooks): event-driven scripts for commands and lifecycle events.
- Plugin Hooks: extension points within agent/tool lifecycle and gateway pipeline.
#
Internal Hooks (Gateway Hooks)
- ''''agent:bootstrap'''': runs when building bootstrap files before system prompt finalization.
Use it to add/remove bootstrap context files.
- ''Command Hooks'': ''/new'', ''/reset'', ''/stop'' and other command events (see Hooks documentation).
See ''Hooks'' for setup and examples.
#
Plugin Hooks (Agent+Gateway Lifecycle)
They run within agent loop or gateway pipeline:
- ''''before_agent_start'''': inject context or override system prompt before run starts.
- ''''agent_end'''': inspect final message list and run metadata after completion.
- ''''before_compaction'''' / ''after_compaction'''': observe or annotate compaction loop.
- ''''before_tool_call'''' / ''after_tool_call'''': intercept tool arguments/results.
- ''''tool_result_persist'''': transform tool results synchronously before writing to session log.
- ''''message_received'''' / ''message_sending'''' / ''message_sent'''': inbound + outbound message hooks.
- ''''session_start'''' / ''session_end'''': session lifecycle boundaries.
- ''''gateway_start'''' / ''gateway_stop'''': gateway lifecycle events.
See ''Plugins'' for hook API and registration details.
Streaming + Partial Replies
- Assistant deltas are streamed from pi-agent-core and emitted as ''assistant'' events.
- Chunk streams can emit partial replies on ''text_end'' or ''message_end''.
- Reasoning streams can be emitted as separate stream or chunk reply.
- See ''Streaming'' for chunking and chunk reply behavior.
Tool Execution+Messaging Tools
- Tool start/update/end events are emitted on ''tool'' stream.
- Tool results are sanitized based on size and image payloads before logging/sending.
- Messaging tool sends are tracked to suppress duplicate assistant acknowledgments.
Reply Shaping+Suppression
- Final payload is assembled from:
- Assistant text (and optional reasoning)
- Inline tool summaries (when verbose+allowed)
- Assistant error text on model errors
- ''NO_REPLY'' is treated as silent token and filtered from outgoing payload.
- Messaging tool duplicates are removed from final payload list.
- If no renderable payload remains and tool errored, fallback tool error reply is emitted
(unless messaging tool already sent user-visible reply).
Compaction+Retry
- Auto-compaction emits ''compaction'' stream event and can trigger retry.
- On retry, memory buffer and tool summaries are reset to avoid duplicate output.
- See ''Compaction'' for compaction pipeline.
Event Stream (today)
- ''lifecycle'': emitted by ''subscribeEmbeddedPiSession'' (and as fallback for ''agentCommand'')
- ''assistant'': streaming deltas from pi-agent-core
- ''tool'': streaming tool events from pi-agent-core
Chat Channel Handling
- Assistant deltas are buffered into chat ''delta'' messages.
- Chat ''final'' is emitted on ''lifecycle end/error''.
Timeouts
- ''agent.wait'' default: 30 seconds (just wait). ''timeoutMs'' parameter overrides.
- Agent run time: ''agents.defaults.timeoutSeconds'' default 600 seconds; enforced in ''runEmbeddedPiAgent'' abort timer.
Where things can end early
- Agent timeout (abort)
- AbortSignal (cancel)
- Gateway disconnect or RPC timeout
- ''agent.wait'' timeout (only waits, doesn't stop agent)