pi-mono Agent Loop
pi-mono Agent Loop
The core execution engine in pi-mono. Drives LLM streaming, tool calls, and event emission. OpenClaw wraps it via runEmbeddedPiAgent.
Entry points
| Function | Use case |
|---|---|
agentLoop(prompts, ctx, cfg) |
New run — adds prompts to context, starts loop |
agentLoopContinue(ctx, cfg) |
Retry — continues from existing context; last message must be non-assistant |
Both return EventStream<AgentEvent, AgentMessage[]>.
Loop anatomy
agent_start
outer-loop:
inner-loop:
turn_start
[inject steering messages]
streamAssistantResponse → message_start / message_update* / message_end
if stopReason == error|aborted → turn_end + agent_end, return
executeToolCalls → tool_execution_start/update/end + message_start/end per result
turn_end
[check steering messages → continue inner]
[check getFollowUpMessages → continue outer]
agent_end
Message representation
AgentMessage[]used throughout internally (richer metadata, timestamps).Message[](LLM wire format) produced only at the LLM call boundary viaconfig.convertToLlm().- Optional
config.transformContext()runs beforeconvertToLlm— used by OpenClaw for compaction.
Steering vs follow-up messages
| Callback | When polled | Effect |
|---|---|---|
getSteeringMessages() |
Start of run + after each turn | Injects user messages between turns (mid-run interrupt) |
getFollowUpMessages() |
After agent would naturally stop | Re-enters the outer loop with new messages |
This is how OpenClaw's Command Queue modes (steer, followup) feed the loop.
Tool execution pipeline
tool.prepareArguments(rawArgs)
→ validateToolArguments(schema)
→ config.beforeToolCall({…}) → block?
→ tool.execute(id, args, signal, onPartial)
→ config.afterToolCall({…, result, isError}) → rewrite?
→ ToolResultMessage emitted
Execution mode: sequential or parallel (configurable). Parallel preparation fires all non-blocked execute calls concurrently, then awaits in order.
Per-turn API key resolution
config.getApiKey(provider) is called each turn — enables support for short-lived / expiring tokens without restarting the loop.
Related
- pi-mono — library entity
- Source - Agent Loop (pi-mono) — detailed source notes
- Agent Loop (OpenClaw) — OpenClaw's wrapper and hook layer on top
- Streaming — full event reference
- Command Queue — queue modes that feed steering/follow-up callbacks
- OpenClaw Hooks — how OpenClaw maps its hooks to pi-mono config callbacks