Add visual Mermaid diagrams to supplement existing text descriptions throughout docs/. Diagrams cover architecture, message flows, agent lifecycle, routing, queue modes, security layers, plugin discovery, tool groups, session lifecycle, and onboarding flows. No existing content removed or altered. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
7.9 KiB
7.9 KiB
| summary | read_when | |
|---|---|---|
| Agent loop lifecycle, streams, and wait semantics |
|
Agent Loop (Moltbot)
An agentic loop is the full “real” run of an agent: intake → context assembly → model inference → tool execution → streaming replies → persistence. It’s the authoritative path that turns a message into actions and a final reply, while keeping session state consistent.
In Moltbot, a loop is a single, serialized run per session that emits lifecycle and stream events as the model thinks, calls tools, and streams output. This doc explains how that authentic loop is wired end-to-end.
stateDiagram-v2
[*] --> Intake: Inbound message / RPC
Intake --> ContextAssembly: Resolve session + workspace
ContextAssembly --> PromptBuild: Load skills, bootstrap files
PromptBuild --> ModelInference: System prompt + history
ModelInference --> ToolExecution: Tool calls returned
ToolExecution --> ModelInference: Tool results fed back
ModelInference --> Streaming: Assistant text deltas
Streaming --> Persistence: Final reply assembled
Persistence --> [*]: Session updated + reply delivered
ModelInference --> Compaction: Context limit hit
Compaction --> ModelInference: Retry with compacted context
Entry points
- Gateway RPC:
agentandagent.wait. - CLI:
agentcommand.
How it works (high-level)
agentRPC validates params, resolves session (sessionKey/sessionId), persists session metadata, returns{ runId, acceptedAt }immediately.agentCommandruns the agent:- resolves model + thinking/verbose defaults
- loads skills snapshot
- calls
runEmbeddedPiAgent(pi-agent-core runtime) - emits lifecycle end/error if the embedded loop does not emit one
runEmbeddedPiAgent:- serializes runs via per-session + global queues
- resolves model + auth profile and builds the pi session
- subscribes to pi events and streams assistant/tool deltas
- enforces timeout -> aborts run if exceeded
- returns payloads + usage metadata
subscribeEmbeddedPiSessionbridges pi-agent-core events to Moltbotagentstream:- tool events =>
stream: "tool" - assistant deltas =>
stream: "assistant" - lifecycle events =>
stream: "lifecycle"(phase: "start" | "end" | "error")
- tool events =>
agent.waituseswaitForAgentJob:- waits for lifecycle end/error for
runId - returns
{ status: ok|error|timeout, startedAt, endedAt, error? }
- waits for lifecycle end/error for
Queueing + concurrency
- Runs are serialized per session key (session lane) and optionally through a global lane.
- This prevents tool/session races and keeps session history consistent.
- Messaging channels can choose queue modes (collect/steer/followup) that feed this lane system. See Command Queue.
Session + workspace preparation
- Workspace is resolved and created; sandboxed runs may redirect to a sandbox workspace root.
- Skills are loaded (or reused from a snapshot) and injected into env and prompt.
- Bootstrap/context files are resolved and injected into the system prompt report.
- A session write lock is acquired;
SessionManageris opened and prepared before streaming.
Prompt assembly + system prompt
- System prompt is built from Moltbot’s base prompt, skills prompt, 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)
Moltbot has two hook systems:
- Internal hooks (Gateway hooks): event-driven scripts for commands and lifecycle events.
- Plugin hooks: extension points inside the agent/tool lifecycle and gateway pipeline.
Internal hooks (Gateway hooks)
agent:bootstrap: runs while building bootstrap files before the system prompt is finalized. Use this to add/remove bootstrap context files.- Command hooks:
/new,/reset,/stop, and other command events (see Hooks doc).
See Hooks for setup and examples.
Plugin hooks (agent + gateway lifecycle)
These run inside the agent loop or gateway pipeline:
before_agent_start: inject context or override system prompt before the run starts.agent_end: inspect the final message list and run metadata after completion.before_compaction/after_compaction: observe or annotate compaction cycles.before_tool_call/after_tool_call: intercept tool params/results.tool_result_persist: synchronously transform tool results before they are written to the session transcript.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 the hook API and registration details.
sequenceDiagram
participant GW as Gateway
participant HOOK as Plugin Hooks
participant AGENT as Agent Runtime
participant MODEL as Model API
participant TOOL as Tool Execution
GW->>HOOK: gateway_start
Note over GW: Gateway initializes
GW->>HOOK: message_received
GW->>HOOK: session_start
GW->>HOOK: before_agent_start
GW->>AGENT: Start agent run
AGENT->>MODEL: Send prompt + context
loop Tool Loop
MODEL->>AGENT: Tool call request
AGENT->>HOOK: before_tool_call
AGENT->>TOOL: Execute tool
TOOL->>AGENT: Tool result
AGENT->>HOOK: after_tool_call
AGENT->>HOOK: tool_result_persist
AGENT->>MODEL: Feed result back
end
MODEL->>AGENT: Final assistant reply
AGENT->>HOOK: agent_end
GW->>HOOK: message_sending
Note over GW: Deliver reply
GW->>HOOK: message_sent
GW->>HOOK: session_end
Streaming + partial replies
- Assistant deltas are streamed from pi-agent-core and emitted as
assistantevents. - Block streaming can emit partial replies either on
text_endormessage_end. - Reasoning streaming can be emitted as a separate stream or as block replies.
- See Streaming for chunking and block reply behavior.
Tool execution + messaging tools
- Tool start/update/end events are emitted on the
toolstream. - Tool results are sanitized for size and image payloads before logging/emitting.
- Messaging tool sends are tracked to suppress duplicate assistant confirmations.
Reply shaping + suppression
- Final payloads are assembled from:
- assistant text (and optional reasoning)
- inline tool summaries (when verbose + allowed)
- assistant error text when the model errors
NO_REPLYis treated as a silent token and filtered from outgoing payloads.- Messaging tool duplicates are removed from the final payload list.
- If no renderable payloads remain and a tool errored, a fallback tool error reply is emitted (unless a messaging tool already sent a user-visible reply).
Compaction + retries
- Auto-compaction emits
compactionstream events and can trigger a retry. - On retry, in-memory buffers and tool summaries are reset to avoid duplicate output.
- See Compaction for the compaction pipeline.
Event streams (today)
lifecycle: emitted bysubscribeEmbeddedPiSession(and as a fallback byagentCommand)assistant: streamed deltas from pi-agent-coretool: streamed tool events from pi-agent-core
Chat channel handling
- Assistant deltas are buffered into chat
deltamessages. - A chat
finalis emitted on lifecycle end/error.
Timeouts
agent.waitdefault: 30s (just the wait).timeoutMsparam overrides.- Agent runtime:
agents.defaults.timeoutSecondsdefault 600s; enforced inrunEmbeddedPiAgentabort timer.
Where things can end early
- Agent timeout (abort)
- AbortSignal (cancel)
- Gateway disconnect or RPC timeout
agent.waittimeout (wait-only, does not stop agent)