PODS · OPENCLAW · · 11 MIN READ

De technische kaart van OpenClaw

Engineering-laag toegankelijk gemaakt: gateway, runtime, tools, skills, hooks, heartbeat en cron

Pill that activates the Developer Program
Pill · DEVELOPER PROGRAM

OpenClaw’s fieldguide is geschreven voor de gebruiker die wil weten hoe het systeem te bedienen. Voor de engineer die wil weten hoe het systeem werkt, is een andere lezing nodig. Wat hieronder volgt is een gestructureerd doorlopen van de bouwsystemen die OpenClaw maken wat het is. Niet API-reference, wel verhaal-met-koppen waarin de mechaniek zichtbaar wordt.

01 · DE GATEWAY IN DETAILProvider-onafhankelijke messaging-abstractie

De Gateway is één Node.js-proces dat alles dirigeert. WebSocket en HTTP gecombineerd, alle kanalen beheerd, agent-runtime erbinnen. De gateway is wat de claw zichtbaar maakt voor de buitenwereld.

Channel-adapters. Elk messaging-platform heeft zijn eigen protocol, zijn eigen authenticatie-flow, zijn eigen rate-limits. De Gateway hanteert per kanaal een adapter die het externe protocol normaliseert naar een interne canonieke vorm. Een inkomende WhatsApp-message via Baileys, een Telegram-update via Bot-API, een Discord-event via hun gateway-WebSocket; alle drie eindigen ze in dezelfde interne shape: {channelId, peerId, content, timestamp, attachments, metadata}.

Inkomende canonicalization. Wanneer een externe event binnenkomt, doorloopt hij een pipeline: protocol-decode (provider-specific), filter (DM-policy, allowlist, mention-detection), enrichment (peer-lookup, channel-config), routing (welke agent krijgt dit). Het resultaat is een InboundMessage die door de runtime opgepakt wordt.

Uitgaande de-canonicalization. De omgekeerde route. De agent produceert een respons in canonieke vorm; de channel-adapter vertaalt terug naar provider-specific protocol. Lange responses worden gesplitst naar kanaal-limieten (Telegram 4096 chars, WhatsApp anders). Streaming wordt aangeboden waar het kanaal het ondersteunt.

State per channel. De gateway houdt per channel state bij: connection-status, last-seen-message-id, rate-limit-budget. Bij netwerkstoring of provider-uitval reageert het systeem met exponential backoff en automatic reconnection. Outbound messages krijgen een durable lifecycle (queued, sending, sent, failed) zodat een gateway-restart geen verloren berichten oplevert.

Error-handling per provider. Discord en Telegram hebben officiële Bot-APIs met voorspelbare error-codes. WhatsApp via Baileys is fragieler; sessie-verloop en pairing-resets vragen om expliciete retry-paden. iMessage via osascript heeft platform-specifieke quirks.

02 · DE RUNTIME EN ZIJN STATEHoe geheugen-coherentie tussen beurten werkt

De Agent-Runtime leeft binnen de gateway. Per inkomende message kiest de router welke agent dit krijgt; vervolgens treedt de runtime in werking.

Sessie-state. Een sessie is gebonden aan een (channel, peer)-combinatie. De runtime houdt per sessie bij: actieve LLM-context (system-prompt plus message-history), beschikbare tools, geheugen-handles, lopende tool-calls. Bij elke turn wordt deze state gemuteerd; tussen turns wordt hij geserialiseerd naar disk.

Compaction. Wanneer een sessie de context-window-limiet nadert, treedt automatische compaction in: belangrijke feiten worden naar memory/YYYY-MM-DD.md geschreven, oudere turns worden samengevat, en de actieve context blijft hanteerbaar. Compaction-checkpoints (configureerbaar via sessions.compactionCheckpointOptions) bewaren snapshots zodat een rollback mogelijk blijft.

Soul en Memory in code. SOUL.md, USER.md, AGENTS.md, HEARTBEAT.md worden bij elke turn als system-prompt gemonteerd. MEMORY.md zit erbij tot 20.000 tekens, waarna een truncatie plaatsvindt met markering. Dagnotities in memory/ zijn niet automatisch in de prompt; de agent kan ze opvragen via de memory_search-tool.

Restart-veerkracht. Sessies worden naar disk gepersisteerd; bij een gateway-restart kan de runtime een actieve sessie herstellen. De command:new-event triggert een nieuwe sessie; /reset of /new triggert hetzelfde plus een memory-flush. Compaction-checkpoints maken roll-back tussen turns mogelijk.

03 · HET TOOL-SYSTEEMRegistratie, invocation en error-protocol

Tools zijn de primitieve acties van OpenClaw. Lees een bestand, draai een bash-commando, open een URL, stuur een bericht.

Registratie. Tools worden bij gateway-start gediscoverd: built-in tools (bestand, bash, web, memory) plus tools die door active skills worden meegebracht. Per tool: een naam, een description (LLM-readable), een input-schema (JSON Schema), en een handler.

Invocation-protocol. De agent stelt aan het LLM een lijst beschikbare tools voor; het LLM kiest een tool plus arguments; de runtime valideert tegen het schema; de handler draait. Output is gestructureerd: {ok: true, result} of {ok: false, error}. Errors zijn gemarkeerd zodat het LLM ze kan onderscheiden van legitieme content.

Partial failure. Wanneer een tool deels lukt (drie bestanden lezen waarvan één faalt), bevat de result-payload zowel successes als failures. Het LLM kan dan beslissen of het verder gaat met wat wel lukte.

Tool-policies en gating. Voordat een tool wordt aangeroepen, doorloopt de runtime een policy-check: is deze tool toegestaan in het huidige profiel? Vereist hij explicit user-approval? Welke argument-validaties? De tools.profile, tools.deny, exec.security, exec.ask-instellingen werken hier.

Tool-call result-shape. Per tool een gedefinieerde response-shape: {summary, details, attachments}. Het LLM krijgt het samenvatting-veld direct; details kunnen worden opgehaald via een vervolgvraag. Dat houdt de context-window beheersbaar bij grote tool-outputs.

04 · HET SKILL-SYSTEEMBundels van instructie plus tools plus scripts

Skills zijn herbruikbare vaardigheden. Een skill is een mapje met een SKILL.md (instructie plus metadata) en optioneel scripts.

Discovery. Bij gateway-start scant de runtime de workspace-skills-folder (~/.openclaw/workspace/skills/) plus ingebouwde skills. Per skill wordt SKILL.md geparsed: frontmatter met naam, description, requires (env vars, externe binaries), policy. Een skill die zijn requires niet kan vinden, wordt gemarkeerd als ineligible.

Twee execution-paths. Tool dispatch voor skills die simpel naar een ingebouwde tool wijzen (snel, deterministisch, geen LLM nodig). Model invocation voor skills die contextuele beslissingen vereisen (de agent leest de skill-instructies, denkt na, gebruikt zo nodig meerdere tools).

Parameter-bindings. Een skill kan input-parameters declareren. Wanneer de agent de skill aanroept, vult hij de parameters in op basis van de gespreksvraag. De runtime valideert de parameters tegen het schema voordat de handler draait.

Skill-policy validatie. Voor een skill draait, controleert de runtime of het profile hem toestaat. Skill-policy-validatie gebeurt client-side voordat de execution naar de server gaat; dat geeft snellere feedback dan pas een server-rejection.

Hot-reload. Wijzigingen in skill-bestanden worden binnen ~250ms opgepakt; geen gateway-restart nodig. Dat maakt iteratieve skill-development plezierig.

De claude-code-proxy skill. Een speciale skill die Claude Code conversationeel beschikbaar maakt via messaging-kanalen. Budget-capped en channel-aware. Output wordt geformatteerd voor het kanaal waar je werkt. Voorbeeld van een skill die zelf intern een sub-LLM aanroept.

05 · HOOK-ARCHITECTUUREvent-handlers in de runtime-lifecycle

Hooks zijn handlers op gateway-events. Anders dan skills, die door de agent worden gekozen, draaien hooks automatisch wanneer hun event vuurt.

Hook-points. De fieldguide noemt zeven primaire events: message:received, message:sent, command:new, session:start, agent:bootstrap, agent:end, gateway:start. Voor elk hook-point levert de runtime een event-object met context (channel, peer, content, timing).

Hook-signature. Een hook is een TypeScript-bestand (handler.ts) met een default export-functie: async function(event). Returnt undefined of een vervangende event-shape (voor message-transformaties).

Hook-failure isolation. Wanneer een hook gooit, vangt de runtime de exception op. De event-loop gaat door. Logs registreren de error. Een falende hook blokkeert geen messages.

Trusted versus untrusted hooks. Events uit wake-triggers (Gmail Pub/Sub, externe webhooks) worden gemarkeerd als untrusted. Tools die alleen voor trusted content openstaan blijven dicht. Dit voorkomt dat een aanvaller die een webhook kan vuren, trusted-context kan injecteren.

Built-in webhook-mappings. Voor Gmail levert OpenClaw een setup-helper: openclaw webhooks gmail setup. Onder de motorkap configureert dat Pub/Sub-topic, push-subscription, en de mapping in hooks.mappings van openclaw.json. De canonieke config-key is hooks.internal.entries; hooks.internal.handlers is alleen nog compat-input.

06 · HEARTBEAT-IMPLEMENTATIEHoe agent-leven gesimuleerd wordt

De heartbeat-loop maakt de claw periodiek wakker. Implementatie-detail dat de levende-agent-illusie mogelijk maakt.

Timer en wake-up. Per agent een interval (every: "30m"), met activeHours die stille tijden respecteert. Op het juiste moment vuurt een interne timer een wake-event naar de runtime. De runtime laadt de agent-state, mounteert HEARTBEAT.md als system-extension, en start een speciale heartbeat-turn.

HEARTBEAT_OK stilte. Als de agent geen reden ziet om iets te doen of te zeggen, antwoordt hij met HEARTBEAT_OK. De runtime parseert dat als “geen actie nodig”, zwijgt naar de gebruiker, en logt alleen dat de heartbeat onschuldig was. Dat voorkomt notification-spam.

Target-routing. Een heartbeat-uitkomst (een bericht, een herinnering) gaat ergens naartoe. target: "last" stuurt naar het laatst gebruikte kanaal van deze agent; specifieke channel-id’s sturen daarheen; target: "none" betekent dat het resultaat alleen in logs landt.

Model-keuze per heartbeat. Voor heartbeat-werk wordt vaak een lichter (en goedkoper) model gebruikt: een aparte model op de heartbeat-config overschrijft de hoofdkeuze. Dit bespaart kosten voor het routinematige werk dat de agent in zijn eigen tijd doet.

Heartbeat-systeem-prompt sectie. Standaard wordt een heartbeat-instructie-sectie in de system-prompt opgenomen. Voor agents zonder heartbeat-loop kan includeSystemPromptSection: false deze sectie weglaten, wat tokens bespaart.

07 · CRON EN REPEATING SKILLSInterne scheduling versus externe schedulers

OpenClaw heeft een interne cron-systeem. Waarom intern, en hoe verschilt het van een externe scheduler?

Waarom intern. Een externe scheduler weet niet welke sessie erbij hoort, welke skills relevant zijn, welk model gebruikt mag worden, welke fallback-paden er zijn. Door cron intern te modelleren, kan een geplande job dezelfde rijkdom hebben als een handmatige conversatie.

Job-types. --session main draait de cron-job in de hoofdsessie van de agent. --session isolated start een nieuwe geïsoleerde sessie zonder voorgaande context. --session-key "agent:<id>:<channel>:<peer>" draait in een specifieke bestaande sessie; handig voor terugkerende taken die binnen een doorlopende thread moeten blijven.

Trigger en aflevering. Een cron-job kan een --system-event versturen (een instructie die de agent als systeem-context leest) of een --message (een instructie die de agent als gebruiker-bericht leest). Het verschil is intent: system-event is “doe iets in stilte”, message is “alsof ik dit zelf vroeg”.

Foutafhandeling. Bij transient errors (rate limits, timeouts, 5xx) probeert het systeem opnieuw met exponential backoff: 30s, 60s, 5min, 15min, 60min, daarna failure-alert via een geconfigureerd kanaal.

Idempotency. Cron-jobs die zelf side-effects veroorzaken (mail versturen, post toevoegen) moeten idempotent zijn of expliciet retry-safe ontworpen. Een job die bij re-execution een dubbele actie zou doen, is bewust ontwerp-werk.

08 · MEMORY EN SOULHun implementatie en lifecycles

Soul en Memory zijn architecturaal gescheiden. Implementatie-niveau:

SOUL.md. Een markdown-bestand in de workspace. Bij elke turn wordt het in de system-prompt gemonteerd, ongewijzigd. Geen auto-update door de agent; alleen handmatig of via een expliciete tool-call. Truncatie boven een drempel.

MEMORY.md. Ook in de workspace, ook in de system-prompt, max 20.000 tekens. De agent kan dit bestand zelf bewerken via een tool-call. Bij compaction worden belangrijke feiten hier samengevat opgeslagen.

Dagnotities. memory/YYYY-MM-DD.md-bestanden, niet automatisch in de prompt. Toegankelijk via memory_search-tool. De agent schrijft hier feiten bij naar aanleiding van conversaties; bij /reset of compaction wordt de huidige sessie samengevat in een dagnotitie voordat hij wordt gewist.

Vector-index. Optioneel: een SQLite of QMD-index over alle dagnotities, met embeddings van een geconfigureerde provider (OpenAI, Gemini, lokaal via Llama). memory_search-queries combineren vector-similarity met tekstmatch en tijdsverval.

Multimodal memory. Wanneer multimodal.enabled aan staat, kunnen ook afbeeldingen en audio in de index. Bij retrieval levert dit cross-modal context.

Memory-core lifecycle. Sleep phases, REM-preview, grounded REM backfill. Memory-core schrijft niet direct naar disk; het gaat door een gefaseerde verwerking waarvan REM-preview kan worden geïnspecteerd voordat het wordt gepersisteerd. Grounded REM backfill kan historische dagnotities terugvoeren in actieve memory wanneer ze relevant blijken.

Memory-wiki en active-memory. Twee extensies bovenop memory-core. Wiki-pagina’s met backlinks tussen verwante notities; ingest/compile/lint pipeline. Active-memory is een blocking sub-agent die voor elke reply automatisch relevante herinneringen ophaalt en injecteert, bounded met timeout.

09 · WORKSPACE-ISOLATIEHoe Docker-sandboxing precies werkt

Docker-sandboxing isoleert tool-executie. De implementatie:

Image. Standaard node:22-slim. Aanpasbaar via agents.defaults.sandbox.docker.image. De image hoort minimal te zijn; geen extra tooling tenzij de tools die in de sandbox draaien het nodig hebben.

Mount-strategie. De workspace wordt read-only gemount. De claw kan zijn eigen context lezen maar niet vanuit een tool zijn persoonlijkheid herschrijven. Filesystem buiten de workspace is niet gemount; tools die buiten proberen te lezen, krijgen “no such file”.

Network. Standaard network: "none". Tools die het web op moeten (web_fetch, web_search) doen hun verkeer via de gateway, niet via de container. Dat geeft de gateway controle over outbound verkeer.

Capabilities. capDrop: ["ALL"]. Alle Linux-capabilities verwijderd. Een proces in de container heeft minimale system-privileges, zelfs als het ergens een root-flag heeft.

Memory en pids-limit. memory: "512m" en pidsLimit: 100. Zachte bovengrenzen die voorkomen dat een uit de hand gelopen tool de host opvreet. Voor zware data-processing moet je deze verhogen.

Cold-start. Eerste keer is een paar seconden trager omdat de image geladen moet worden. Volgende invocations binnen honderden milliseconden.

Mode-keuze. off, non-main (subagents in sandbox, hoofdagent op host), all (alles in sandbox). Voor publieke bots is all de juiste keuze; voor persoonlijk gebruik is non-main de pragmatische middenweg.

10 · TERUGKERENDE PATRONENCode-idiomen die OpenClaw kenmerken

Een paar patronen die je in de OpenClaw-codebase vaker tegenkomt en die zijn karakter mede bepalen.

  • Registry-pattern voor pluggable components

    Channels, tools, skills en LLM-providers zijn allemaal pluggable. Bij gateway-start wordt een registry opgebouwd door discovery; runtime-lookups gaan via die registry. Een nieuwe channel-implementatie toevoegen betekent een nieuwe entry in de registry, niet een wijziging in de core-routing.

  • Configuration hierarchy

    Settings cascaden van defaults → agent-level → channel-level → call-level. `agents.defaults.model` is overschrijfbaar door `agents.list[i].model`, dat weer door `channel.model`, dat weer door per-call-flags op CLI. De lookup is consistent door de hele codebase.

  • Event-emitter voor inter-component communicatie

    Channels, agents en hooks praten met elkaar via een centrale event-emitter. Een nieuw inkomend bericht is een event, een agent-respons is een event, een hook-trigger is een event. Loosely coupled, makkelijk uitbreidbaar, observable.

  • Atomic state-writes

    Sessies en geheugen-bestanden worden via temp-file + atomic-rename geschreven. Een crash tijdens een schrijf-actie geeft of de oude of de nieuwe versie, nooit een partial-write. Voor MEMORY.md en `memory/YYYY-MM-DD.md` is dit een belangrijke garantie.

  • Provider-abstractie via uniform interface

    Anthropic, OpenAI, Gemini, Ollama, Bedrock, en de rest, ze hebben elk hun eigen request/response-shape. OpenClaw implementeert per provider een adapter die naar een gedeelde `ChatCompletion`-interface mapt. De fallback-chain en multi-key-rotatie werken bovenop deze gedeelde interface.

Deze patronen samen vormen geen exotische architectuur. Ze zijn solide Node-engineering toegepast op een specifiek probleem. Wat OpenClaw kenmerkt is niet brilliance per patroon, maar de consistente toepassing van bekende patronen op een welomschreven domein.

Voor wie hier dieper in wil duiken: lees de source. De codebase is open en de fieldguide-secties verwijzen op meerdere plekken naar specifieke modules. Begin bij de gateway, werk naar buiten: channels, agents, tools, skills, hooks. De mentale modellen uit deze pagina maken de code daarna makkelijker te lezen.

← Terug naar de OpenClaw Pod