Get started
Swarms — agent-fan-out en orkestratie in codemodus
Swarms — agent-fan-out en orkestratie in codemodus
Status: Uitgebracht — vervangen door docs/tools/swarm.md. Dit document blijft behouden als
het ontwerpverslag van de implementatie.
1. Wat en waarom
Een swarm bestaat uit meerdere subagents die deterministisch worden georkestreerd vanuit een
script in codemodus: waaier uit naar N lezers, verifieer bevindingen kritisch, synthetiseer via een
statusbehoudende prioriteerder en herhaal op beslissingspoorten. De besturingsstroom (Promise.all,
while, if) is de orkestratie — er is bewust geen grafiek-DSL,
geen nieuwe modus en geen nieuw tooloppervlak op topniveau.
De codemodus van OpenClaw (QuickJS-WASI, momentopname/hervatten, bridge-verzoeken) vormt de basis. Een geparkeerde bridge-aanroep overleeft een VM-momentopname en herstart van de Gateway, en wordt precies hervat waar die is gestopt — krachtiger dan ontwerpen met journal-replay, zonder determinismebeperkingen voor scripts.
Naamgeving: de naam in het product en de documentatie is Swarm. Code-identificatoren blijven letterlijk:
agents.*-gast-API, tools.swarm-configuratie, swarm-groepskolommen.
2. Besluiten (maintainer, 2026-07-17)
- Kosten: afgedwongen configuratielimieten; tokenbudget per swarm optioneel. Geen verplicht budget.
- Goedkeuringen: kinderen worden fail-closed/niet-interactief uitgevoerd. Acties waarvoor goedkeuring vereist is, worden geweigerd; de weigering wordt gemeld in het resultaat van het kind; het script beslist. Geen overvloed aan operatorprompts door fan-out.
- v1 bestaat uitsluitend uit ad-hocscripts die door het model zijn geschreven. Opgeslagen/benoemde workflows, invoer via CLI/Cron: later (headless codemodus bestaat al voor Cron).
- Identiteit van het kind: standaard een speciale worker-agent via de
tools.swarm.defaultAgentId- configuratie (gevalideerd tegen de bestaande allowlist voor subagentdoelen); overschrijving per spawn viaagentId. Core levert geen gebundelde agent-id; de documentatie beveelt een gestroomlijndeworker-agentconfiguratie aan. - Geen wijzigingen aan de Codex-broncode. De Codex-harness gebruikt het spawn/wait-idioom (§8).
3. Architectuuroverzicht
script in codemodus (QuickJS-VM, gateway) Codex V8-script (Codex-proces) agents.run(...) ── geparkeerde bridge-aanroep tools.sessions_spawn / tools.agents_wait │ │ item/tool/call-RPC (elk ≤600s) ▼ ▼ CORE (harness-agnostisch, deze repository) sessions_spawn {collect:true, outputSchema, fastMode, groupId} agents_wait {ids, timeoutSeconds} │ subagentregister (SQLite): collector-voltooiingsrecords, swarmgroep-id │ kinderen = gewone subagentsessies (beperkt per lane, fail-closed-goedkeuringen) │ sessions.changed SSE ──► stippen in Control UI / zijbalk / kanaalstatusberichtEén canonieke eigenaar van de semantiek voor spawnen/voltooien/afhandelen (core-tools + register).
Twee wachttransports: QuickJS parkeert onbeperkt een bridge-aanroep (momentopname);
Codex pollt agents_wait in begrensde RPC's.
4. Configuratiepoort (v1)
Nieuwe tools.swarm (globaal + overschrijving per agent, hetzelfde samenvoegpatroon als
tools.codeMode):
"tools": { "swarm": { "enabled": false, // hoofdpoort, standaard UIT "maxConcurrent": 8, // tegelijk actieve kinderen (lane-limiet voor swarm) "maxChildrenPerGroup": 50, // actieve kinderen per swarmgroep "maxTotalPerGroup": 200, // totaal aantal spawns gedurende de levensduur per groep (noodrem tegen ontsporing) "waitTimeoutSecondsMax": 600, "defaultAgentId": "" // optioneel; agent-id van kind wanneer agentId bij spawn ontbreekt }}- Zod: union
boolean | strict objectzoalsCodeModeSchema(src/config/zod-schema.agent-runtime.ts);swarm: true→{enabled: true}. - Typen in
src/config/types.tools.ts(zowel per agent alstoolsop topniveau), labels inschema.labels.ts, hulptekst inschema.help.runtime.ts. - Resolutiehelper
resolveSwarmConfig(cfg, agentId), naar het voorbeeld vanresolveCodeModeConfig(src/agents/code-mode.ts:215), met begrenzing van alle getallen. - Effecten van de poort wanneer uitgeschakeld: de tool
agents_waitontbreekt in catalogi;collect-/outputSchema-/fastMode-/groupId-parameters voorsessions_spawnworden geweigerd met een duidelijke foutmelding die de configuratiesleutel noemt. Geen andere gedragswijziging. defaultAgentIdwordt gevalideerd viaresolveSubagentAllowedTargetIds(src/agents/subagent-target-policy.ts); onbekende id → spawnfout, geen fallback.
5. Core: spawn in collectormodus + agents_wait (v1)
5.1 Toevoegingen aan sessions_spawn (allemaal afhankelijk van ingeschakelde swarm)
collect: boolean— wanneer true, wordt de uitvoering van het kind geregistreerd metexpectsCompletionMessage: falseen een collector-voltooiingsrecord in plaats van levering via aankondiging/sturing. De tool retourneert onmiddellijk{ runId, sessionKey }. Geen binding aan kanaal/thread.outputSchema: object— JSON Schema. Het kind krijgt een synthetischestructured_output-tool toegevoegd aan zijn tooloppervlak; een aanvulling op de systeemprompt instrueert het om die precies eenmaal aan te roepen met het eindresultaat. Bij een validatiefout krijgt het kind één aansporing om het opnieuw te proberen; daarna bevat het voltooiingsrecordstructured: undefined, plus de onbewerkte tekst en eenschemaError.fastMode: true | "auto" | false— wordt naast model/denkniveau doorgegeven aan de patch van de kindsessie viaresolveSubagentModelAndThinkingPlan(src/agents/subagent-spawn-plan.ts), met gebruik van de bestaandeFastMode-as (src/shared/fast-mode.ts). Weggelaten = overnemen.groupId: string— stempel voor de swarmgroep. Standaardswarm:<requesterSessionKey>:<runId-of-requesting-run>. Wordt opgeslagen in het registerrecord en de rij van de kindsessie. Wordt gebruikt voor limieten, lijsten, batcharchivering en de stippen.label: stringbestaat al — wordt weergegeven in de stippen ensubagents list.- Agent-id van kind:
params.agentId→ anderstools.swarm.defaultAgentId→ anders aanvragende agent (bestaand gedrag).
5.2 Goedkeuringen fail-closed
Collectorkinderen worden uitgevoerd met een niet-interactieve goedkeuringscontext: elke toolaanroep
waarvoor goedkeuring van een operator vereist zou zijn, resulteert in een gestructureerde weigering
(approval_required) die zichtbaar is voor het kind, dat geacht wordt de
blokkering in zijn resultaat te melden. Implementatie: hergebruik de bestaande infrastructuur voor het
goedkeuringsbeleid van exec/tools met een afgedwongen deny-resolver voor uitvoeringen van kinderen in collectormodus.
Vanuit collectorkinderen worden geen goedkeuringsgebeurtenissen naar operatoroppervlakken verzonden.
5.3 Tool agents_wait (nieuw, achter poort)
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[] }- Retourneert zodra ten minste één id is voltooid (semantiek van eerste voltooiing/race,
maakt pijplijnen mogelijk), of bij een time-out met
completed: []. timeoutSecondsstandaard 30, begrensd totwaitTimeoutSecondsMax.- Idempotent: reeds voltooide id's retourneren hun records opnieuw (records worden bewaard tot de groepsarchivering). Onbekende id → foutitem per id, geen exception.
- Eigendom: alleen de sessie die een uitvoering heeft gespawnd (of de bovenliggende keten ervan) mag erop wachten
— dezelfde eigendomsregel als
waitin codemodus (code-mode.ts:1684). - Register: voltooiingsrecords worden opgeslagen in de bestaande SQLite-opslag van het subagentregister
(
subagent-registry.store.sqlite.ts) — nieuwe velden, geen nieuwe opslag en geen verhoging van de schemaversie (uitsluitend aanvullende kolommen; zie beperking in §9).
5.4 Afdwingen van limieten
maxConcurrent: collectorkinderen worden uitgevoerd op de bestaande subagentlane, maar per swarmgroep geteld; spawns boven de limiet worden FIFO in de wachtrij geplaatst (aan de hostzijde, in het spawnpad — retourneer runId onmiddellijk, uitvoering start zodra een plaats vrijkomt).maxChildrenPerGroup/maxTotalPerGroup: spawn weigert met een getypeerde foutmelding zodra de limiet is overschreden; de fouttekst noemt de configuratiesleutel.- Diepte: collectorkinderen behouden de semantiek van
DEFAULT_SUBAGENT_MAX_SPAWN_DEPTH(kinderen zijn bladeren, tenzij nesting expliciet is geconfigureerd).
6. Testcontract (v1, lane A)
- Unit: configuratieresolutie/-begrenzing; poortweigeringen wanneer uitgeschakeld; standaardwaarde voor groupId; afdwingen van limieten (wachtrij + weigering); racesemantiek van wait; idempotentie van wait; eigendomsweigering; validatie van gestructureerde uitvoer + aansporing om opnieuw te proberen + schemaError-pad; doorvoer van fastMode naar sessiepatch; validatie van defaultAgentId.
- Integratie (vitest, nagebootste modelruntime): spawn 3 collectorkinderen, wacht in een lus, controleer de volgorde van eerste voltooiingen en de uiteindelijke leegloop; simulatie van Gateway-herstart: register opnieuw laden → wait wordt afgehandeld vanuit opgeslagen voltooiing.
- Alle tests staan bij elkaar in
*.test.ts; geen live modelaanroepen.
7. QuickJS-gastoppervlak (lane B, na core)
- Gastglobals geïnstalleerd in
CONTROLLER_SOURCE(src/agents/code-mode.worker.ts:190-374), gereserveerde namen toegevoegd incode-mode-namespaces.ts:agents.run(prompt, opts) → Promise<result|structured>— syntactische suiker: collectorspawn + geparkeerd wachten via een speciale bridge-methode (agentWait) die de host bij voltooiing afhandelt (geen polling; veilig voor momentopnamen).agents.session(system, opts) → Promise<handle>;handle.send(input, opts) → Promise<...>;handle.close(). (v1.1 — wordt na run() uitgebracht; gebruiktmode:"session"+ collectorrecords per beurt.)phase(title),log(message)— bridge-meldingen zonder wachten op resultaat → voortgangsgebeurtenissen van de swarm.
- Bridge-methoden toegevoegd aan
CodeModeBridgeMethod(code-mode.ts:91):agentSpawn,agentWait,swarmNote.agentSpawn/agentWaitzijn door hun constructie veilig voor replay: idempotentiesleutel(codeModeRunId, bridgeId)opgeslagen in het registerrecord; bij herstart wordt opnieuw afgehandeld vanuit opgeslagen voltooiingen en worden nooit dubbele spawns uitgevoerd. - Openstaande
agentWait-bridge-aanroepen verlengen de TTL van de momentopname van de uitvoering (de set openstaande agents is het signaal; geen vlag). - Het virtuele bestand
API.read("agents.d.ts")documenteert het getypeerde oppervlak en de idiomen voor fan-out/poort/cyclus (createCodeModeApiVirtualFiles,code-mode-namespaces.ts:876).
8. Projectie van de Codex-harness (latere lane)
sessions_spawn(met nieuwe parameters) enagents_waitlopen via de bestaande bridge voor dynamische tools; binnen Codex-scripts in codemodus verschijnen ze automatisch alstools.*(geverifieerd:codex-rs/code-mode/src/runtime/globals.rs:14-65,codex-rs/core/src/tools/spec_plan.rs:448-507).agents_waitkrijgt de lange time-outklasse voor dynamische tools (limiet van 600s;extensions/codex/src/app-server/dynamic-tool-execution.ts:37-39) en wordt gemarkeerd als veilig voor time-out/replay.- Groepssleutel voor Codex-ouders:
swarm:<parentSessionKey>:<turnId>. - Codex-eigen
spawn_agent-subagents bestaan naast elkaar; hun taakspiegelrijen voeden hetzelfde voortgangsoppervlak.
9. Persistentie en bewaring
- Geen nieuwe opslagplaatsen. Registerrecords breiden de bestaande SQLite-tabellen van het subagentregister
uit; kinderen zijn gewone
sessions-rijen. Uitsluitend aanvullende kolommen — voor elke wijziging waarvoor de versie van het SQLite-schema moet worden verhoogd, is eerst expliciete goedkeuring van een maintainer vereist (repositorybeleid). - Swarmgroep-id in registerrecord + metadata van kindsessie.
- Bewaring: voltooide collectorrecords blijven bestaan tot groepsarchivering:
wanneer de uitvoering van de ouder is voltooid (of de TTL verloopt), worden de kinderen van de groep
als batch gearchiveerd (breid de bestaande
DEFAULT_SUBAGENT_ARCHIVE_AFTER_MINUTES- opschoning uit zodat deze per groep werkt).
10. Voortgangsoppervlak ("de stippen") — latere lane
- Impliciet, aangestuurd door de harness. Afgeleid van bestaande
sessions.changed-SSE + register;phase-/log-notities voegen semantiek toe. Geen door agents aangestuurde rendering. - Control UI:
swarm-renderer in de familie van workspace-widgets (ui/src/lib/workspace/widgets/) — stippenraster gegroepeerd per fase, vertellerregel, status/label/model per stip; kindboom in zijbalk ongewijzigd. - Kanalen: één beperkt bijgewerkt statusbericht per groep (volg
docs/concepts/streaming.md; nooit berichten per kind).
11. Labs-pagina (Control UI, onafhankelijk traject)
Settings → Labs: schakelaars voor experimentele functies, met als eerste opties Code Mode
en Swarm. Elke rij: naam, beschrijving van één regel, documentatielink, schakelaar gekoppeld
via de bestaande config.patch-RPC (RFC 7396 merge-patch — stel
tools.codeMode.enabled / tools.swarm.enabled in), plus indien van toepassing de
hint "opnieuw opstarten vereist". Vindbaar, maar de tekst maakt de experimentele status
duidelijk. i18n: alle tekenreeksen via de normale en.ts + synchronisatiepijplijn.
12. Plaatsing (later)
placement-keuze bij starten:"local"(standaard) |"cloud:<profile>"via de bestaande dispatch voor werkomgevingen (sessions.dispatch); gepoolde plaatsing later als SSH-sandboxkinderen op een gedeelde box onvoldoende blijken.- De orchestrator-VM blijft altijd op de Gateway; settle/dots/budget zijn plaatsingsonafhankelijk.
13. Niet-doelstellingen
- Geen grafiek-DSL — de besturingsstroom is de grafiek (bewust, gedocumenteerd).
- Geen wijzigingen aan de Codex-broncode; geen hergebruik van interne onderdelen van Codex Code Mode.
- Geen opgeslagen/benoemde workflows in v1; geen CLI-ingangspunt.
- Geen escalatie van operatorgoedkeuring per kind.
- Geen 1:1-cloudprovisioning op fan-out-schaal.
- Geen compatibiliteitsshims in de stabiele runtime; swarm is een nieuw, afgeschermd oppervlak.
14. Bouwfasen / opsplitsing van PR's
- Traject A (core): §4-configuratie + §5 starten/wachten/limieten/goedkeuringen + §6-tests.
- Traject C (Labs-pagina): §11 — onafhankelijk, kan als eerste worden samengevoegd.
- Traject B (QuickJS-oppervlak): §7 — nadat de contracten van A zijn samengevoegd.
- Dots-renderer (§10), Codex-projectie (§8),
agents.session(§7 v1.1), plaatsing (§12), herschrijving van gebruikersdocumentatie — vervolg-PR's in die volgorde.
Elke PR: groene CI, $autoreview schoon, standaard uitgeschakeld, main gereed voor uitgifte.