Agent Loop (OpenClaw)
Ein Agent Loop ist der vollständige Durchlauf eines Agents: Eingabe -> Context-Aufbau -> Model-Inferenz -> Tool-Ausführung -> Streaming-Antworten -> Persistenz. Das ist der maßgebliche Pfad, der eine Nachricht in Aktionen und eine finale Antwort verwandelt und dabei den Session-Zustand konsistent hält.
In OpenClaw ist ein Loop ein einzelner, serialisierter Durchlauf pro Session, der Lifecycle- und Stream-Events ausgibt, während das Model denkt, Tools aufruft und Output streamt. Dieses Dokument erklärt, wie dieser Loop von Anfang bis Ende funktioniert.
Einstiegspunkte
- Gateway RPC:
agentundagent.wait. - CLI:
agentBefehl.
So funktioniert es (Überblick)
agentRPC validiert Parameter, löst die Session auf (sessionKey/sessionId), speichert Session-Metadaten und gibt sofort{ runId, acceptedAt }zurück.agentCommandführt den Agent aus:- löst Model + Thinking/Verbose-Defaults auf
- lädt den Skills-Snapshot
- ruft
runEmbeddedPiAgentauf (pi-agent-core Runtime) - gibt lifecycle end/error aus, falls der eingebettete Loop keins ausgibt
runEmbeddedPiAgent:- serialisiert Durchläufe über per-Session + globale Queues
- löst Model + Auth-Profil auf und baut die pi-Session
- abonniert pi-Events und streamt Assistant/Tool-Deltas
- erzwingt Timeout -> bricht den Durchlauf ab, wenn überschritten
- gibt Payloads + Usage-Metadaten zurück
subscribeEmbeddedPiSessionverbindet pi-agent-core Events mit dem OpenClawagentStream:- Tool-Events =>
stream: "tool" - Assistant-Deltas =>
stream: "assistant" - Lifecycle-Events =>
stream: "lifecycle"(phase: "start" | "end" | "error")
- Tool-Events =>
agent.waitnutztwaitForAgentJob:- wartet auf lifecycle end/error für
runId - gibt
{ status: ok|error|timeout, startedAt, endedAt, error? }zurück
- wartet auf lifecycle end/error für
Queueing + Concurrency
- Durchläufe werden pro Session-Key (Session-Lane) und optional über eine globale Lane serialisiert.
- Das verhindert Tool/Session-Races und hält die Session-History konsistent.
- Messaging-Channels können Queue-Modi wählen (collect/steer/followup), die dieses Lane-System speisen. Siehe Command Queue.
Session + Workspace-Vorbereitung
- Der Workspace wird aufgelöst und erstellt; Sandbox-Durchläufe können zu einem Sandbox-Workspace-Root umgeleitet werden.
- Skills werden geladen (oder aus einem Snapshot wiederverwendet) und in Env und Prompt injiziert.
- Bootstrap/Context-Dateien werden aufgelöst und in den System-Prompt-Report injiziert.
- Ein Session-Write-Lock wird erworben;
SessionManagerwird geöffnet und vorbereitet, bevor das Streaming beginnt.
Prompt-Aufbau + System Prompt
- Der System Prompt wird aus OpenClaws Base-Prompt, Skills-Prompt, Bootstrap-Context und per-Run-Overrides zusammengebaut.
- Model-spezifische Limits und Compaction-Reserve-Tokens werden durchgesetzt.
- Siehe System Prompt für das, was das Model sieht.
Hook-Punkte (wo du eingreifen kannst)
OpenClaw hat zwei Hook-Systeme:
- Internal Hooks (Gateway Hooks): Event-gesteuerte Skripte für Commands und Lifecycle-Events.
- Plugin Hooks: Erweiterungspunkte innerhalb des Agent/Tool-Lebenszyklus und der Gateway-Pipeline.
Internal Hooks (Gateway Hooks)
agent:bootstrap: läuft während des Aufbaus der Bootstrap-Dateien, bevor der System Prompt finalisiert wird. Nutze das, um Bootstrap-Context-Dateien hinzuzufügen oder zu entfernen.- Command Hooks:
/new,/reset,/stopund andere Command-Events (siehe Hooks-Dokumentation).
Siehe Hooks für Setup und Beispiele.
Plugin Hooks (Agent + Gateway Lifecycle)
Diese laufen innerhalb des Agent Loop oder der Gateway-Pipeline:
before_agent_start: Context injizieren oder System Prompt überschreiben, bevor der Durchlauf startet.agent_end: die finale Nachrichtenliste und Run-Metadaten nach Abschluss inspizieren.before_compaction/after_compaction: Compaction-Zyklen beobachten oder annotieren.before_tool_call/after_tool_call: Tool-Parameter/Ergebnisse abfangen.tool_result_persist: Tool-Ergebnisse synchron transformieren, bevor sie ins Session-Transkript geschrieben werden.message_received/message_sending/message_sent: eingehende + ausgehende Nachrichten-Hooks.session_start/session_end: Session-Lifecycle-Grenzen.gateway_start/gateway_stop: Gateway-Lifecycle-Events.
Siehe Plugins für die Hook-API und Registrierungsdetails.
Streaming + partielle Antworten
- Assistant-Deltas werden von pi-agent-core gestreamt und als
assistantEvents ausgegeben. - Block-Streaming kann partielle Antworten entweder bei
text_endodermessage_endausgeben. - Reasoning-Streaming kann als separater Stream oder als Block-Antworten ausgegeben werden.
- Siehe Streaming für Chunking und Block-Reply-Verhalten.
Tool-Ausführung + Messaging-Tools
- Tool-Start/Update/End-Events werden auf dem
toolStream ausgegeben. - Tool-Ergebnisse werden für Größe und Image-Payloads bereinigt, bevor sie geloggt/ausgegeben werden.
- Messaging-Tool-Sends werden getrackt, um doppelte Assistant-Bestätigungen zu unterdrücken.
Antwort-Formung + Unterdrückung
- Finale Payloads werden zusammengestellt aus:
- Assistant-Text (und optionalem Reasoning)
- Inline-Tool-Summaries (wenn verbose + erlaubt)
- Assistant-Fehlertext, wenn das Model einen Fehler hat
NO_REPLYwird als stilles Token behandelt und aus ausgehenden Payloads gefiltert.- Messaging-Tool-Duplikate werden aus der finalen Payload-Liste entfernt.
- Wenn keine renderbaren Payloads übrig bleiben und ein Tool einen Fehler hatte, wird eine Fallback-Tool-Error-Antwort ausgegeben (es sei denn, ein Messaging-Tool hat bereits eine für den User sichtbare Antwort gesendet).
Compaction + Retries
- Auto-Compaction gibt
compactionStream-Events aus und kann einen Retry auslösen. - Bei einem Retry werden In-Memory-Buffer und Tool-Summaries zurückgesetzt, um doppelten Output zu vermeiden.
- Siehe Compaction für die Compaction-Pipeline.
Event Streams (aktuell)
lifecycle: ausgegeben vonsubscribeEmbeddedPiSession(und als Fallback vonagentCommand)assistant: gestreamte Deltas von pi-agent-coretool: gestreamte Tool-Events von pi-agent-core
Chat-Channel-Handling
- Assistant-Deltas werden in Chat-
delta-Nachrichten gepuffert. - Ein Chat-
finalwird bei lifecycle end/error ausgegeben.
Timeouts
agent.waitStandard: 30s (nur das Warten).timeoutMsParameter überschreibt das.- Agent Runtime:
agents.defaults.timeoutSecondsStandard 600s; durchgesetzt imrunEmbeddedPiAgentAbort-Timer.
Wo Dinge vorzeitig enden können
- Agent Timeout (Abbruch)
- AbortSignal (Abbruch)
- Gateway-Disconnect oder RPC-Timeout
agent.waitTimeout (nur Warten, stoppt den Agent nicht)