OpenClawSkills
GitHub
Core Concepts β€’ TutorialHeader.readTime

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.

Tutorial.step

Entry Points

- Gateway RPC: ''agent'' and ''agent.wait''.

- CLI: ''agent'' command.

Tutorial.step

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? }''

Tutorial.step

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''.

Tutorial.step

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.

Tutorial.step

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.

Tutorial.step

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.

#

Tutorial.step

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.

#

Tutorial.step

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.

Tutorial.step

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.

Tutorial.step

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.

Tutorial.step

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).

Tutorial.step

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.

Tutorial.step

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

Tutorial.step

Chat Channel Handling

- Assistant deltas are buffered into chat ''delta'' messages.

- Chat ''final'' is emitted on ''lifecycle end/error''.

Tutorial.step

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.

Tutorial.step

Where things can end early

- Agent timeout (abort)

- AbortSignal (cancel)

- Gateway disconnect or RPC timeout

- ''agent.wait'' timeout (only waits, doesn't stop agent)