Get started
Swarms — Agent-Fan-out und Orchestrierung im Code-Modus
Swarms — Agent-Fan-out und Orchestrierung im Code-Modus
Status: Ausgeliefert — ersetzt durch docs/tools/swarm.md. Dieses Dokument bleibt als
Entwurfsprotokoll der Implementierung erhalten.
1. Was und warum
Ein Swarm besteht aus vielen Subagenten, die deterministisch von einem Skript im
Code-Modus orchestriert werden: N Leser per Fan-out starten, Erkenntnisse adversarial überprüfen,
durch einen zustandsbehafteten Priorisierer synthetisieren und Entscheidungsschranken in Schleifen
durchlaufen. Der Kontrollfluss (Promise.all,
while, if) ist die Orchestrierung — bewusst gibt es keine Graph-DSL,
keinen neuen Modus und keine neue Top-Level-Tool-Oberfläche.
Der OpenClaw-Code-Modus (QuickJS-WASI, Snapshot/Fortsetzung, Bridge-Anfragen) bildet die Grundlage. Ein geparkter Bridge-Aufruf übersteht einen VM-Snapshot und einen Gateway-Neustart und wird exakt an der Stelle fortgesetzt, an der er angehalten wurde — stärker als Designs mit Journal-Wiedergabe und ohne Determinismusanforderungen an Skripte.
Benennung: Der Name in Produkt und Dokumentation lautet Swarm. Code-Bezeichner bleiben unverändert:
agents.*-Gast-API, tools.swarm-Konfiguration, swarm-Gruppenspalten.
2. Entscheidungen (Maintainer, 2026-07-17)
- Kosten: erzwungene Konfigurationsobergrenzen; Token-Budget pro Swarm optional. Kein verpflichtendes Budget.
- Genehmigungen: Unterprozesse werden geschlossen fehlschlagend / nicht interaktiv ausgeführt. Aktionen, die eine Genehmigung erfordern, werden abgelehnt; die Ablehnung wird im Ergebnis des Unterprozesses gemeldet; das Skript entscheidet. Keine Flut von Bedienerabfragen durch Fan-out.
- v1 umfasst ausschließlich vom Modell geschriebene Ad-hoc-Skripte. Gespeicherte/benannte Workflows sowie CLI-/Cron-Einstieg: später (der Headless-Code-Modus ist für Cron bereits vorhanden).
- Identität des Unterprozesses: standardmäßig ein dedizierter Worker-Agent über die
tools.swarm.defaultAgentId-Konfiguration (gegen die vorhandene Zulassungsliste für Subagent-Ziele validiert);agentId-Überschreibung pro Spawn. Der Core liefert keine gebündelte Agent-ID aus; die Dokumentation empfiehlt eine schlankeworker-Agent-Konfiguration. - Keine Änderungen am Codex-Quellcode. Das Codex-Harness verwendet das Spawn-/Wait-Muster (§8).
3. Architekturübersicht
Skript im Code-Modus (QuickJS-VM, Gateway) Codex-V8-Skript (Codex-Prozess) agents.run(...) ── geparkter Bridge-Aufruf tools.sessions_spawn / tools.agents_wait │ │ Item-/Tool-/Aufruf-RPC (jeweils ≤600s) ▼ ▼ CORE (Harness-unabhängig, dieses Repository) sessions_spawn {collect:true, outputSchema, fastMode, groupId} agents_wait {ids, timeoutSeconds} │ Subagent-Registry (SQLite): Collector-Abschlussdatensätze, Swarm-Gruppen-ID │ Unterprozesse = gewöhnliche Subagent-Sitzungen (Lane-begrenzt, Genehmigungen geschlossen fehlschlagend) │ sessions.changed SSE ──► Punkte in Control UI / Seitenleiste / KanalstatusmeldungEin kanonischer Eigentümer der Spawn-/Abschluss-/Erledigungssemantik (Core-Tools + Registry).
Zwei Await-Transporte: QuickJS parkt einen Bridge-Aufruf unbegrenzt (Snapshot);
Codex fragt agents_wait über begrenzte RPCs ab.
4. Konfigurationsschranke (v1)
Neu: tools.swarm (global + Überschreibung pro Agent, dasselbe Zusammenführungsmuster wie
tools.codeMode):
"tools": { "swarm": { "enabled": false, // Hauptschranke, standardmäßig AUS "maxConcurrent": 8, // gleichzeitig ausgeführte Unterprozesse (Swarm-Lane-Obergrenze) "maxChildrenPerGroup": 50, // aktive Unterprozesse pro Swarm-Gruppe "maxTotalPerGroup": 200, // lebenslange Spawn-Anzahl pro Gruppe (Sicherung gegen unkontrollierte Ausführung) "waitTimeoutSecondsMax": 600, "defaultAgentId": "" // optional; Agent-ID des Unterprozesses, wenn agentId beim Spawn fehlt }}- Zod: Union
boolean | strict objectwieCodeModeSchema(src/config/zod-schema.agent-runtime.ts);swarm: true→{enabled: true}. - Typen in
src/config/types.tools.ts(sowohl pro Agent als auch Top-Leveltools), Bezeichnungen inschema.labels.ts, Hilfe inschema.help.runtime.ts. - Auflösungshelfer
resolveSwarmConfig(cfg, agentId)analog zuresolveCodeModeConfig(src/agents/code-mode.ts:215), der alle Zahlen begrenzt. - Auswirkungen bei deaktivierter Schranke: Das Tool
agents_waitfehlt in Katalogen; die Parametercollect/outputSchema/fastMode/groupIdfürsessions_spawnwerden mit einem eindeutigen Fehler abgelehnt, der den Konfigurationsschlüssel nennt. Keine weitere Verhaltensänderung. defaultAgentIdwird überresolveSubagentAllowedTargetIds(src/agents/subagent-target-policy.ts) validiert; unbekannte ID → Spawn-Fehler, kein Fallback.
5. Core: Spawn im Collector-Modus + agents_wait (v1)
5.1 Ergänzungen für sessions_spawn (alle an aktivierten Swarm gekoppelt)
collect: boolean— wenn wahr, wird die Ausführung des Unterprozesses mitexpectsCompletionMessage: falseund einem Collector-Abschlussdatensatz statt mit Ankündigungs-/Steuerungszustellung registriert. Das Tool gibt{ runId, sessionKey }sofort zurück. Keine Kanal-/Thread-Bindung.outputSchema: object— JSON Schema. Dem Unterprozess wird ein synthetischesstructured_output-Tool zu seiner Tool-Oberfläche hinzugefügt; ein Zusatz zum System-Prompt weist ihn an, es genau einmal mit seinem Endergebnis aufzurufen. Bei einem Validierungsfehler erhält der Unterprozess einen einmaligen erneuten Hinweis; danach enthält der Abschlussdatensatzstructured: undefinedzusammen mit dem Rohtext und einemschemaError.fastMode: true | "auto" | false— wird neben Modell/Denken überresolveSubagentModelAndThinkingPlan(src/agents/subagent-spawn-plan.ts) in den Sitzungs-Patch des Unterprozesses übernommen, wobei die vorhandeneFastMode-Achse (src/shared/fast-mode.ts) verwendet wird. Ausgelassen = erben.groupId: string— Stempel der Swarm-Gruppe. Standardwert:swarm:<requesterSessionKey>:<runId-of-requesting-run>. Wird im Registry-Datensatz und in der Sitzungszeile des Unterprozesses persistiert. Wird für Obergrenzen, Auflistung, Batch-Archivierung und die Punkte verwendet.label: stringist bereits vorhanden — wird in den Punkten und insubagents listangezeigt.- Agent-ID des Unterprozesses:
params.agentId→ andernfallstools.swarm.defaultAgentId→ andernfalls anfordernder Agent (vorhandenes Verhalten).
5.2 Genehmigungen schlagen geschlossen fehl
Collector-Unterprozesse werden mit einem nicht interaktiven Genehmigungskontext ausgeführt: Jeder
Tool-Aufruf, der eine Genehmigung durch den Bediener erfordern würde, wird als strukturierte Ablehnung
(approval_required) aufgelöst, die für den Unterprozess sichtbar ist; von diesem wird erwartet, dass er
die Blockierung in seinem Ergebnis meldet. Implementierung: Die vorhandene Genehmigungsrichtlinien-
Infrastruktur für Exec/Tools wird mit einem erzwungenen deny-Resolver für Unterprozessausführungen
im Collector-Modus wiederverwendet. Von Collector-Unterprozessen werden keine Genehmigungsereignisse
an Bedieneroberflächen ausgegeben.
5.3 Tool agents_wait (neu, an Schranke gekoppelt)
agents_wait({ ids: string[], timeoutSeconds?: number })→ { completed: [{ runId, status: "done"|"failed"|"killed"|"timeout", result: string, structured?: unknown, schemaError?: string, sessionKey, label?, usage?: {inputTokens, outputTokens} }], pending: string[] }- Kehrt zurück, sobald mindestens eine ID abgeschlossen ist (Erstabschluss-/Race-
Semantik, ermöglicht Pipelines), oder bei Zeitüberschreitung mit
completed: []. timeoutSecondsstandardmäßig 30, begrenzt aufwaitTimeoutSecondsMax.- Idempotent: Bereits abgeschlossene IDs geben ihre Datensätze erneut zurück (Datensätze bleiben bis zur Gruppenarchivierung erhalten). Unbekannte ID → Fehlereintrag pro ID, kein Throw.
- Eigentümerschaft: Nur die Sitzung, die eine Ausführung erzeugt hat (oder ihre Elternkette), darf
darauf warten — dieselbe Eigentümerschaftsregel wie für
waitim Code-Modus (code-mode.ts:1684). - Registry: Abschlussdatensätze befinden sich im vorhandenen SQLite-Speicher der
Subagent-Registry (
subagent-registry.store.sqlite.ts) — neue Felder, kein neuer Speicher, keine Erhöhung der Schemaversion (nur additive Spalten; siehe Einschränkung in §9).
5.4 Durchsetzung der Obergrenzen
maxConcurrent: Collector-Unterprozesse laufen auf der vorhandenen Subagent-Lane, werden jedoch pro Swarm-Gruppe gezählt; Spawns über der Obergrenze werden nach FIFO eingereiht (hostseitig im Spawn-Pfad — runId sofort zurückgeben, Ausführung beginnt, sobald ein Platz frei wird).maxChildrenPerGroup/maxTotalPerGroup: Spawn wird nach Überschreitung mit einem typisierten Fehler abgelehnt; der Fehlertext nennt den Konfigurationsschlüssel.- Tiefe: Collector-Unterprozesse behalten die
DEFAULT_SUBAGENT_MAX_SPAWN_DEPTH-Semantik bei (Unterprozesse sind Blätter, sofern Verschachtelung nicht ausdrücklich konfiguriert ist).
6. Testvertrag (v1, Lane A)
- Unit: Konfigurationsauflösung/-begrenzung; Ablehnungen durch die Schranke bei Deaktivierung; Standardbelegung von groupId; Durchsetzung der Obergrenzen (Einreihung + Ablehnung); Wait-Race-Semantik; Wait-Idempotenz; Ablehnung wegen Eigentümerschaft; Validierung strukturierter Ausgabe + erneuter Hinweis + schemaError-Pfad; Weitergabe von fastMode in den Sitzungs-Patch; Validierung von defaultAgentId.
- Integration (Vitest, simulierte Modelllaufzeit): 3 Collector-Unterprozesse erzeugen, in einer Schleife warten, Erstabschlussreihenfolge und abschließende Leerung prüfen; Simulation eines Gateway-Neustarts: Registry neu laden → Wait wird aus persistiertem Abschluss aufgelöst.
- Alle Tests zusammen mit
*.test.ts; keine Live-Modellaufrufe.
7. QuickJS-Gastoberfläche (Lane B, nach dem Core)
- Gast-Globals werden in
CONTROLLER_SOURCE(src/agents/code-mode.worker.ts:190-374) installiert, reservierte Namen werden incode-mode-namespaces.tsergänzt:agents.run(prompt, opts) → Promise<result|structured>— Komfortfunktion: Collector-Spawn + geparktes Await auf einer dedizierten Bridge-Methode (agentWait), die der Host beim Abschluss erledigt (kein Polling; Snapshot-sicher).agents.session(system, opts) → Promise<handle>;handle.send(input, opts) → Promise<...>;handle.close(). (v1.1 — wird nach run() ausgeliefert; verwendetmode:"session"+ Collector-Datensätze pro Turn.)phase(title),log(message)— Bridge-Benachrichtigungen ohne Rückmeldung → Swarm-Fortschrittsereignisse.
- Zu
CodeModeBridgeMethod(code-mode.ts:91) hinzugefügte Bridge-Methoden:agentSpawn,agentWait,swarmNote.agentSpawn/agentWaitsind konstruktionsbedingt wiedergabesicher: Der Idempotenzschlüssel(codeModeRunId, bridgeId)wird im Registry-Datensatz gespeichert; ein Neustart erledigt erneut aus persistierten Abschlüssen und erzeugt niemals doppelte Spawns. - Ausstehende
agentWait-Bridge-Aufrufe verlängern die Snapshot-TTL der Ausführung (die Menge ausstehender Agenten ist das Signal; kein Flag). - Die virtuelle Datei
API.read("agents.d.ts")dokumentiert die typisierte Oberfläche sowie die Fan-out-/Schranken-/Zyklusmuster (createCodeModeApiVirtualFiles,code-mode-namespaces.ts:876).
8. Projektion des Codex-Harness (spätere Lane)
sessions_spawn(mit neuen Parametern) undagents_waitdurchlaufen die vorhandene Bridge für dynamische Tools; innerhalb von Codex-Skripten im Code-Modus erscheinen sie automatisch alstools.*(verifiziert:codex-rs/code-mode/src/runtime/globals.rs:14-65,codex-rs/core/src/tools/spec_plan.rs:448-507).agents_waiterhält die lange Zeitüberschreitungsklasse für dynamische Tools (Obergrenze 600s;extensions/codex/src/app-server/dynamic-tool-execution.ts:37-39) und wird als zeitüberschreitungs-/wiedergabesicher gekennzeichnet.- Gruppenschlüssel für Codex-Eltern:
swarm:<parentSessionKey>:<turnId>. - Codex-native
spawn_agent-Subagenten bestehen parallel; ihre Task-Spiegelzeilen speisen dieselbe Fortschrittsoberfläche.
9. Persistenz und Aufbewahrung
- Keine neuen Speicher. Registry-Datensätze erweitern die vorhandenen SQLite-Tabellen der
Subagent-Registry; Unterprozesse sind gewöhnliche
sessions-Zeilen. Nur additive Spalten — jede Änderung, die eine Erhöhung der SQLite-Schemaversion erfordert, benötigt zuerst die ausdrückliche Zustimmung eines Maintainers (Repository-Richtlinie). - Swarm-Gruppen-ID im Registry-Datensatz + Sitzungsmetadaten des Unterprozesses.
- Aufbewahrung: Abgeschlossene Collector-Datensätze bleiben bis zur Gruppenarchivierung erhalten:
Wenn die übergeordnete Ausführung endet (oder die TTL abläuft), werden die Unterprozesse der Gruppe
als Batch archiviert (die vorhandene
DEFAULT_SUBAGENT_ARCHIVE_AFTER_MINUTES-Bereinigung wird für die gruppenweise Ausführung erweitert).
10. Fortschrittsoberfläche („die Punkte“) — spätere Lane
- Implizit, Harness-gesteuert. Abgeleitet aus vorhandener
sessions.changed-SSE + Registry; Hinweise zuphase/logergänzen die Semantik. Kein Agent-gesteuertes Rendering. - Control UI:
swarm-Renderer in der Workspace-Widget-Familie (ui/src/lib/workspace/widgets/) — nach Phase gruppiertes Punkteraster, Erzählerzeile, Status/Bezeichnung/Modell pro Punkt; Unterprozessbaum in der Seitenleiste unverändert. - Kanäle: eine gedrosselte, bearbeitete Statusmeldung pro Gruppe (gemäß
docs/concepts/streaming.md; niemals Meldungen pro Unterprozess).
11. Labs-Seite (Control UI, unabhängiger Ausführungspfad)
Settings → Labs: Schalter für experimentelle Funktionen, als erste Einträge Code Mode
und Swarm. Jede Zeile: Name, einzeilige Beschreibung, Dokumentationslink, über
den vorhandenen config.patch-RPC angebundener Schalter (RFC-7396-Merge-Patch —
tools.codeMode.enabled / tools.swarm.enabled setzen) sowie gegebenenfalls ein Hinweis
„Neustart erforderlich“. Auffindbar, wobei die Formulierung den experimentellen
Status klarstellt. i18n: alle Zeichenfolgen über die normale en.ts- und Sync-Pipeline.
12. Platzierung (später)
placementbei der Erzeugung auswählen:"local"(Standard) |"cloud:<profile>"über die vorhandene Worker-Umgebungsweiterleitung (sessions.dispatch); gepoolte Platzierung später, falls SSH-Sandbox-Kindprozesse auf gemeinsam genutzten Boxen nicht ausreichen.- Die Orchestrator-VM verbleibt stets auf dem Gateway; Settle/Dots/Budget sind unabhängig von der Platzierung.
13. Nicht-Ziele
- Keine Graph-DSL — der Kontrollfluss ist der Graph (bewusst so gestaltet und dokumentiert).
- Keine Änderungen am Codex-Quellcode; keine Wiederverwendung interner Komponenten des Codex-Code-Modus.
- Keine gespeicherten/benannten Workflows in v1; kein CLI-Einstiegspunkt.
- Keine Weiterleitung der Operatorgenehmigung pro untergeordnetem Prozess.
- Keine 1:1-Cloud-Bereitstellung im Fan-out-Maßstab.
- Keine Kompatibilitäts-Shims für den Dauerbetrieb; Swarm ist eine neue, durch ein Gate geschützte Oberfläche.
14. Implementierungsphasen / PR-Aufteilung
- Lane A (Kern): §4 Konfiguration + §5 Erzeugen/Warten/Obergrenzen/Genehmigungen + §6 Tests.
- Lane C (Labs-Seite): §11 — unabhängig, kann zuerst integriert werden.
- Lane B (QuickJS-Oberfläche): §7 — nachdem die Verträge aus A integriert wurden.
- Dots-Renderer (§10), Codex-Projektion (§8),
agents.session(§7 v1.1), Platzierung (§12), Überarbeitung der Benutzerdokumentation — Folge-PRs in dieser Reihenfolge.
Jeder PR: grüne CI, $autoreview sauber, standardmäßig durch ein Gate deaktiviert, main auslieferbar.