exec und wait.
Diese Seite dokumentiert den OpenClaw-Codemodus. Er ist nicht der
Codex-Codemodus. Die beiden Features teilen sich einen Namen, werden aber von
unterschiedlichen Runtimes implementiert und stellen unterschiedliche
exec-Verträge bereit:
- Der Codex-Codemodus ist für Codex-App-Server-Threads aktiviert, sofern eine
eingeschränkte Tool-Richtlinie den nativen Codemodus nicht deaktiviert. Er
läuft im Codex-Coding-Harness, in dem das Modell Shell-Befehle über einen
exec.command-Vertrag schreibt. - Der OpenClaw-Codemodus ist deaktiviert, sofern nicht
tools.codeMode.enabled: truekonfiguriert ist. Er läuft in der generischen Agent-Runtime von OpenClaw, in der das Modell JavaScript- oder TypeScript-Programme über einenexec.code-Vertrag schreibt.
quickjs-wasi, einen verborgenen
OpenClaw-Toolkatalog und den normalen OpenClaw-Tool-Executor.
Was ist das?
Der OpenClaw-Codemodus lässt das Modell ein kleines JavaScript- oder TypeScript-Programm schreiben, statt direkt aus einer langen Liste von Tools auszuwählen. Wenn der Codemodus aktiv ist:- Die für das Modell sichtbare Tool-Liste besteht genau aus
execundwait. execwertet modellgeneriertes JavaScript oder TypeScript in einem eingeschränkten QuickJS-WASI-Worker aus.- Normale OpenClaw-Tools werden aus dem Modell-Prompt verborgen und innerhalb des
Gastprogramms über
ALL_TOOLSundtoolsbereitgestellt. - Gastcode kann den verborgenen Katalog durchsuchen, ein Tool beschreiben und ein Tool über denselben OpenClaw-Ausführungspfad aufrufen, der von normalen Agent-Ausführungen verwendet wird.
- MCP-Tools werden unter dem Namespace
MCPgruppiert. Im Codemodus ist dieser Namespace die einzige unterstützte Methode, MCP-Tools aufzurufen. waitsetzt eine angehaltene Codemodus-Ausführung fort, wenn verschachtelte Tool-Aufrufe noch ausstehen.
Warum ist das gut?
Der Codemodus erleichtert Modellen die Nutzung großer Tool-Kataloge.- Kleinere Prompt-Oberfläche: Provider erhalten zwei Steuerungs-Tools statt Dutzender oder Hunderter vollständiger Tool-Schemas.
- Bessere Orchestrierung: Das Modell kann Schleifen, Joins, kleine Transformationen, bedingte Logik und parallele verschachtelte Tool-Aufrufe innerhalb einer Codezelle verwenden.
- Provider-neutral: Er funktioniert für OpenClaw-, Plugin-, MCP- und Client-Tools, ohne von provider-nativer Codeausführung abhängig zu sein.
- Bestehende Richtlinien bleiben wirksam: Verschachtelte Tool-Aufrufe laufen weiterhin durch OpenClaw-Richtlinien, Genehmigungen, Hooks, Sitzungskontext und Audit-Pfade.
- Klarer Fehlermodus: Wenn der Codemodus ausdrücklich aktiviert ist und die Runtime nicht verfügbar ist, schlägt OpenClaw geschlossen fehl, statt auf eine breite direkte Tool-Offenlegung zurückzufallen.
Aktivierung
Fügen Sie der Agent- oder Runtime-Konfigurationtools.codeMode.enabled: true hinzu:
tools.codeMode ausgelassen wird,
false ist oder ein Objekt ohne enabled: true ist.
Wenn Sie sandboxed Agents mit konfigurierten MCP-Servern verwenden, stellen Sie
außerdem sicher, dass die Sandbox-Tool-Richtlinie das gebündelte MCP-Plugin
erlaubt, zum Beispiel mit
tools.sandbox.tools.alsoAllow: ["bundle-mcp"]. Siehe
Konfiguration - Tools und benutzerdefinierte Provider.
Verwenden Sie ausdrückliche Limits, wenn Sie engere Grenzen festlegen möchten:
exec und wait sein. Wenn Sie die redigierte Provider-Payload benötigen,
fügen Sie für eine kurze Debugging-Sitzung
OPENCLAW_DEBUG_MODEL_PAYLOAD=full-redacted hinzu.
Technische Tour
Der Rest dieser Seite beschreibt den Runtime-Vertrag und Implementierungsdetails. Er richtet sich an Maintainer, Plugin-Autoren, die die Tool-Offenlegung debuggen, und Operatoren, die Hochrisiko-Deployments validieren.Runtime-Status
- Runtime:
quickjs-wasi. - Standardzustand: deaktiviert.
- Stabilität: experimentelle OpenClaw-Oberfläche; der Codex-Codemodus ist eine separate stabile Codex-Harness-Oberfläche.
- Zieloberfläche: generische OpenClaw-Agent-Ausführungen.
- Sicherheitsposition: Modellcode ist feindlich.
- Benutzerseitiges Versprechen: Die Aktivierung des Codemodus fällt niemals stillschweigend auf breite direkte Tool-Offenlegung zurück.
Umfang
Der Codemodus besitzt die modellseitige Orchestrierungsform für eine vorbereitete Ausführung. Er besitzt nicht Modellauswahl, Kanalverhalten, Authentifizierung, Tool-Richtlinien oder Tool-Implementierungen. Im Umfang:- für das Modell sichtbare Tool-Definitionen
execundwait - Aufbau des verborgenen Tool-Katalogs
- JavaScript- und TypeScript-Gastausführung
- QuickJS-WASI-Worker-Runtime
- Host-Callbacks für Katalogsuche, Schemabeschreibung und Tool-Aufruf
- fortsetzbarer Zustand für angehaltene Gastprogramme
- Limits für Ausgabe, Timeout, Speicher, ausstehende Aufrufe und Snapshots
- Telemetrie und Trajektorienprojektion für verschachtelte Tool-Aufrufe
- provider-native Remote-Codeausführung
- Shell-Ausführungssemantik
- Änderung bestehender Tool-Autorisierung
- persistente, von Benutzern verfasste Skripte
- Paketmanager-, Datei-, Netzwerk- oder Modulzugriff in Gastcode
- direkte Wiederverwendung von Codex-Codemodus-Interna
Begriffe
Codemodus ist der OpenClaw-Runtime-Modus, der normale Modell-Tools verbirgt und nurexec und wait offenlegt.
Gast-Runtime ist die QuickJS-WASI-JavaScript-VM, die Modellcode auswertet.
Host-Bridge ist die schmale JSON-kompatible Callback-Oberfläche vom Gastcode
zurück in OpenClaw.
Katalog ist die ausführungsbezogene Liste wirksamer Tools nach normaler
Tool-Richtlinie sowie Plugin-, MCP- und Client-Tool-Auflösung.
Verschachtelter Tool-Aufruf ist ein Tool-Aufruf, der aus Gastcode über die
Host-Bridge erfolgt.
Snapshot ist serialisierter QuickJS-WASI-VM-Zustand, der gespeichert wird,
damit wait eine angehaltene Codemodus-Ausführung fortsetzen kann.
Konfiguration
tools.codeMode.enabled ist die Aktivierungsschranke. Das Setzen anderer
Codemodus-Felder aktiviert das Feature nicht.
Unterstützte Felder:
enabled: boolesch. Standardfalse. Aktiviert den Codemodus nur beitrue.runtime:"quickjs-wasi". Einzige unterstützte Runtime.mode:"only". Legtexecundwaitoffen, verbirgt normale Modell-Tools.languages: Array aus"javascript"und"typescript". Standard enthält beide.timeoutMs: Echtzeitgrenze für einexecoderwait. Standard10000. Runtime-Begrenzung:100bis60000.memoryLimitBytes: QuickJS-Heap-Grenze. Standard67108864. Runtime-Begrenzung:1048576bis1073741824.maxOutputBytes: Grenze für zurückgegebenen Text, JSON und Logs. Standard65536. Runtime-Begrenzung:1024bis10485760.maxSnapshotBytes: Grenze für serialisierte VM-Snapshots. Standard10485760. Runtime-Begrenzung:1024bis268435456.maxPendingToolCalls: Grenze für gleichzeitige verschachtelte Tool-Aufrufe. Standard16. Runtime-Begrenzung:1bis128.snapshotTtlSeconds: wie lange eine angehaltene VM fortgesetzt werden kann. Standard900. Runtime-Begrenzung:1bis86400.searchDefaultLimit: Standardanzahl für Suchergebnisse im verborgenen Katalog. Standard8. Die Runtime begrenzt dies aufmaxSearchLimit.maxSearchLimit: maximale Anzahl für Suchergebnisse im verborgenen Katalog. Standard50. Runtime-Begrenzung:1bis50.
Aktivierung
Der Codemodus wird ausgewertet, nachdem die wirksame Tool-Richtlinie bekannt ist und bevor die endgültige Modellanfrage zusammengesetzt wird. Aktivierungsreihenfolge:- Agent, Modell, Provider, Sandbox, Kanal, Absender und Ausführungsrichtlinie auflösen.
- Die wirksame OpenClaw-Tool-Liste erstellen.
- Geeignete Plugin-, MCP- und Client-Tools hinzufügen.
- Allow- und Deny-Richtlinie anwenden.
- Wenn
tools.codeMode.enabledfalsch ist, mit normaler Tool-Offenlegung fortfahren. - Wenn aktiviert und Tools für die Ausführung aktiv sind, die wirksamen Tools im Codemodus-Katalog registrieren.
- Alle normalen Tools aus der für das Modell sichtbaren Tool-Liste entfernen.
- Codemodus-
execundwaithinzufügen.
disableTools oder eine leere Allowlist, aktivieren die Codemodus-Oberfläche
nicht, selbst wenn die Konfiguration tools.codeMode.enabled: true enthält.
Der Codemodus-Katalog ist ausführungsbezogen. Er darf keine Tools aus einem
anderen Agenten, einer anderen Sitzung, einem anderen Absender oder einer anderen
Ausführung preisgeben.
Für das Modell sichtbare Tools
Wenn der Codemodus aktiv ist, sieht das Modell genau diese Top-Level-Tools:execwait
exec für Tool-Orchestrierung, Datenzusammenführung,
Schleifen, parallele verschachtelte Aufrufe und strukturierte Transformationen
verwenden. Das Modell sollte wait nur verwenden, wenn exec ein fortsetzbares
waiting-Ergebnis zurückgibt.
exec
exec startet eine Codemodus-Zelle und gibt ein Ergebnis zurück. Der Eingabecode
wird vom Modell generiert und muss als feindlich behandelt werden.
Eingabe:
- Eines von
codeodercommandmuss nicht leer sein. codeist das dokumentierte modellseitige Feld.commandwird als exec-kompatibler Alias für Hook-Richtlinien und vertrauenswürdige Umschreibungen akzeptiert; wenn beide vorhanden sind, müssen die Werte übereinstimmen.- Äußere Codemodus-
exec-Hook-Events enthaltentoolKind: "code_mode_exec"und enthaltentoolInputKind: "javascript" | "typescript", wenn die Eingabesprache bekannt ist, damit Richtlinien Codemodus-Zellen von shellartigenexec-Aufrufen unterscheiden können, die denselben Tool-Namen teilen. languageist standardmäßig"javascript".- Wenn
language"typescript"ist, transpiliert OpenClaw vor der Auswertung. execlehnt in v1import,require, dynamischen Import und Modul-Loader-Muster ab.execlegt die normale Shell-exec-Implementierung nicht rekursiv offen.
exec gibt waiting zurück, wenn die QuickJS-VM mit fortsetzbarem Zustand
angehalten wird, der noch eine für das Modell sichtbare Fortsetzung benötigt.
Das Ergebnis enthält eine runId für wait. Namespace-Bridge-Aufrufe,
einschließlich MCP-Namespace-Aufrufen, werden innerhalb desselben
exec-/wait-Aufrufs automatisch geleert, während sie bereit sind, sodass ein
kompakter Codeblock $api() inspizieren und ein MCP-Tool aufrufen kann, ohne
einen Modell-Tool-Aufruf pro Namespace-await zu erzwingen.
exec gibt completed nur zurück, wenn die Gast-VM keine ausstehende Arbeit hat und der
Endwert JSON-kompatibel ist, nachdem der Ausgabeadapter von OpenClaw ausgeführt wurde.
wait
wait setzt eine angehaltene VM im Code-Modus fort.
Eingabe:
CodeModeResult-Union, die von exec zurückgegeben wird.
wait existiert, weil verschachtelte OpenClaw-Tools langsam, interaktiv, genehmigungspflichtig
sein oder Teilaktualisierungen streamen können. Das Modell sollte keinen langen
exec-Aufruf offen halten müssen, während der Host auf externe Arbeit wartet.
QuickJS-WASI-Snapshot und -Wiederherstellung ist der Fortsetzungsmechanismus in v1:
execwertet Code bis zum Abschluss, Fehler oder Anhalten aus.- Beim Anhalten erstellt OpenClaw einen Snapshot der QuickJS-VM und zeichnet ausstehende Host-Arbeit auf.
- Wenn ausstehende Arbeit abgeschlossen ist, stellt
waitden VM-Snapshot wieder her. - OpenClaw registriert Host-Callbacks erneut über stabile Namen.
- OpenClaw liefert verschachtelte Tool-Ergebnisse in die wiederhergestellte VM.
- OpenClaw leert ausstehende QuickJS-Jobs.
waitgibtcompleted,failedoder ein weitereswaiting-Ergebnis zurück.
wait schlägt fehl, wenn:
runIdunbekannt ist.- der Snapshot abgelaufen ist.
- der übergeordnete Run oder die Sitzung abgebrochen wurde.
- der Aufrufer sich nicht im selben Run-/Sitzungsumfang befindet.
- die QuickJS-WASI-Wiederherstellung fehlschlägt.
- die Wiederherstellung konfigurierte Grenzen überschreiten würde.
API der Gast-Laufzeitumgebung
Die Gast-Laufzeitumgebung stellt eine kleine globale API bereit:ALL_TOOLS sind kompakte Metadaten für den Run-spezifischen Katalog. Standardmäßig enthält es
keine vollständigen Schemas.
tools.call(...) oder Komfortfunktionen
aufrufbar. Sie werden nur über den generierten MCP-Namespace bereitgestellt. Deklarationsdateien
im TypeScript-Stil sind über die schreibgeschützte virtuelle API-Dateioberfläche verfügbar,
sodass Agenten MCP-Signaturen prüfen können, ohne MCP-Schemas zum Prompt hinzuzufügen:
API.read("mcp/<server>.d.ts") gibt kompakte Deklarationen zurück, die aus MCP-Tool-Metadaten
abgeleitet wurden:
exec-Aufruf erstellt OpenClaw den
Run-spezifischen Tool-Katalog, behält die sichtbaren MCP-Einträge bei, rendert mcp/index.d.ts
plus eine mcp/<server>.d.ts-Deklaration pro sichtbarem Server und injiziert diese kleine
schreibgeschützte Tabelle in den QuickJS-Worker. Gastcode sieht nur das API-Objekt:
API.list(prefix?) gibt Dateimetadaten zurück und API.read(path) gibt den ausgewählten
Deklarationsinhalt zurück. Unbekannte Pfade und Segmente . / .. werden abgelehnt.
Dadurch bleiben große MCP-Schemas aus dem Modell-Prompt heraus. Der Agent erfährt aus der
Beschreibung des exec-Tools, dass die virtuelle API existiert, liest nur die benötigte
Deklarationsdatei und ruft dann MCP.<server>.<tool>() mit einem Objektargument auf.
MCP.<server>.$api() bleibt als Inline-Fallback verfügbar, wenn der Agent innerhalb des
Programms eine Schemaantwort für ein einzelnes Tool benötigt.
Die Gast-Laufzeitumgebung darf Host-Objekte nicht direkt offenlegen. Eingaben und Ausgaben
überqueren die Bridge als JSON-kompatible Werte mit expliziten Größenobergrenzen.
Interne Namespaces
Interne Namespaces geben dem Code-Modus eine knappe Domänen-API, ohne weitere modell-sichtbare Tools hinzuzufügen. Eine vom Loader verwaltete Integration kann einen Namespace wieIssues, Fictions oder Calendar registrieren; Gastcode ruft diesen Namespace dann
innerhalb des QuickJS-Programms auf, während OpenClaw dem Modell weiterhin nur exec und wait
anzeigt.
Namespaces sind vorerst intern. Es gibt keine öffentliche Plugin-SDK-Namespace-API:
Externe Plugin-Namespaces benötigen einen vom Loader verwalteten Vertrag, damit Plugin-Identität,
installierte Manifeste, Auth-Status und zwischengespeicherte Katalogdeskriptoren nicht von den
Plugin-Tools abweichen können, die den Namespace stützen. Der zentrale Code-Modus besitzt nur
Sandbox, Serialisierung, Katalog-Gating und Bridge-Dispatch.
Gastcode kann dann entweder das direkte globale Objekt oder die namespaces-Map verwenden:
Registry-Lebenszyklus
Die Namespace-Registry ist prozesslokal und nach Namespace-ID verschlüsselt. Ein typischer Run folgt diesem Pfad:- Ein vertrauenswürdiger Loader ruft
registerCodeModeNamespaceForPlugin(pluginId, registration)auf. - Der Code-Modus erstellt die verborgene
ToolSearchRuntimefür den Run und liest ihren Run-spezifischen Katalog. createCodeModeNamespaceRuntime(ctx, catalog)behält nur Registrierungen bei, derenrequiredToolNamesalle sichtbar sind und demselbenpluginIdgehören.- Jeder sichtbare Namespace ruft
createScope(ctx)für den aktuellen Run auf. Der Scope erhält Run-Kontext wieagentId,sessionKey,sessionId,runId, Konfiguration und Abbruchstatus. - Scope-Daten werden in einen einfachen Deskriptor serialisiert und als direkte Globals und
namespaces.<globalName>in QuickJS injiziert. - Gastaufrufe werden über die Worker-Bridge angehalten, lösen den Namespace-Pfad auf dem
Host auf, ordnen den Aufruf einem deklarierten Plugin-eigenen Katalog-Tool zu und führen
dieses Tool über
ToolSearchRuntime.callaus. - OpenClaw leert bereite Namespace-Bridge-Aufrufe automatisch innerhalb des aktiven
exec-/wait-Tool-Aufrufs. Wenn Namespace-Arbeit beim Timeout noch aussteht oder der Gast explizit die Kontrolle abgibt, setztwaitdieselbe Namespace-Laufzeit später fort. - Plugin-Rollback oder -Deinstallation ruft
clearCodeModeNamespacesForPlugin(pluginId)auf, damit veraltete Globals einen fehlgeschlagenen Plugin-Ladevorgang nicht überdauern.
tools.call(...).
Registrierungsform
Registrieren Sie Namespaces aus der Integration, die die zugrunde liegenden Tools besitzt. Halten Sie den Scope klein und legen Sie nur Domänenverben offen, die deklarierte Katalog-Tools abbilden.createCodeModeNamespaceTool(toolName, inputMapper) markiert ein Scope-Mitglied als aufrufbare
Namespace-Funktion. Der optionale inputMapper erhält die Gastargumente und gibt das Eingabeobjekt
für das zugrunde liegende Katalog-Tool zurück. Ohne Eingabe-Mapper wird das erste Gastargument
verwendet oder {}, wenn es ausgelassen wird.
Raw-Host-Funktionen werden abgelehnt, bevor Gastcode ausgeführt wird:
Besitz und Sichtbarkeit
Namespace-Besitz ist an diepluginId des Registrierungsaufrufers gebunden.
requiredToolNames ist sowohl Sichtbarkeits-Gate als auch Besitzprüfung:
- jedes erforderliche Tool muss im Run-Katalog vorhanden sein
- jedes erforderliche Tool muss
sourceName === pluginIdhaben - der Namespace wird verborgen, wenn ein erforderliches Tool fehlt oder einem anderen Plugin gehört
- jeder aufrufbare Pfad darf nur auf ein Tool zielen, das in
requiredToolNamesbenannt ist
Regeln für Scope-Serialisierung
createScope(ctx) kann ein einfaches Objekt zurückgeben, das JSON-kompatible Werte,
Arrays, verschachtelte Objekte und Aufrufmarker von createCodeModeNamespaceTool(...) enthält.
Host-Objekte gelangen nie direkt in QuickJS.
Der Serializer lehnt ab:
- rohe Funktionen
- zirkuläre Objektgraphen
- unsichere Pfadsegmente:
__proto__,constructor,prototype, leere Schlüssel oder Schlüssel, die den internen Pfadseparator enthalten globalName-Werte, die keine JavaScript-Bezeichner sindglobalName-Kollisionen mit integrierten Code-Modus-Globals wietools,namespaces,text,json,yield_controloder__openclaw*
Prompts
Die Namespace-description und der optionale prompt werden nur dann an das für das Modell
sichtbare exec-Schema angehängt, wenn der Namespace für diesen Run sichtbar ist. Verwenden Sie
sie, um die kleinste nützliche Oberfläche zu vermitteln:
Bereinigung
Namespaces sind prozesslokale Registrierungen. Entfernen Sie sie, wenn das besitzende Plugin deaktiviert, deinstalliert oder zurückgerollt wird:clearCodeModeNamespacesForTest() aufrufen, um zu vermeiden,
dass Registrierungen zwischen Fällen weiterbestehen.
Test-Checkliste
Namespace-Änderungen sollten die Sicherheitsgrenze und das Gastverhalten abdecken:- Namespace-Prompttext erscheint nur, wenn die zugrunde liegenden Tools sichtbar sind
- gleichnamige Tools von einem anderen
sourceNamelegen den Namespace nicht offen - rohe Scope-Funktionen werden abgewiesen
- gefälschte Namespace-IDs und gefälschte Pfade werden abgewiesen
- aufrufbare Pfade können nicht auf nicht deklarierte Tools zielen
- verschachtelte Objekte und gemeinsam genutzte Referenzen werden korrekt serialisiert
- Namespace-Aufrufe werden über Katalog-Tools ausgeführt und geben JSON-sichere Details zurück
- Fehler können von Gastcode abgefangen werden
- angehaltene Namespace-Aufrufe werden über
waitfortgesetzt - Plugin-Rollback löscht die besitzenden Namespace-Registrierungen
tools.search / tools.call. Verwenden Sie den
Katalog für beliebige aktivierte OpenClaw-, Plugin- und Client-Tools; verwenden Sie MCP für
MCP-Tools; verwenden Sie andere Namespaces für Plugin-eigene, dokumentierte Domain-APIs, bei denen
knapper Code zuverlässiger ist als wiederholte Schema-Lookups.
Ausgabe-API
text(value) hängt menschenlesbare Ausgabe an das Array output an.
json(value) hängt nach JSON-kompatibler Serialisierung ein strukturiertes Ausgabeelement an.
Der endgültig zurückgegebene Wert des Gastcodes wird in einem completed-Ergebnis zu value.
Ausgabeelement:
- die Ausgabereihenfolge entspricht den Gastaufrufen
- die Ausgabe ist durch
maxOutputBytesbegrenzt - nicht serialisierbare Werte werden in einfache Strings oder Fehler umgewandelt
- Binärwerte werden in v1 nicht unterstützt
- Bilder und Dateien laufen über normale OpenClaw-Tools, nicht über die Code-Modus-Bridge
Tool-Katalog
Der verborgene Katalog enthält Tools nach effektiver Richtlinienfilterung:- OpenClaw-Core-Tools.
- Gebündelte Plugin-Tools.
- Externe Plugin-Tools.
- MCP-Tools.
- Vom Client bereitgestellte Tools für den aktuellen Lauf.
execwaittool_search_codetool_searchtool_describetool_call
ALL_TOOLS, tools.search(...),
tools.describe(...) und tools.call(...) lassen MCP-Einträge aus. Der generierte Namespace
MCP.<server>.<tool>({ ...input }) wird zurück auf die exakte Katalog-ID aufgelöst und dann über
denselben Executor-Pfad dispatcht.
Interaktion mit Tool Search
Der Code-Modus ersetzt die OpenClaw-Tool-Search-Modelloberfläche für Läufe, in denen er aktiv ist. Wenntools.codeMode.enabled wahr ist und der Code-Modus aktiviert wird:
- OpenClaw stellt
tool_search_code,tool_search,tool_describeodertool_callnicht als modellsichtbare Tools bereit. - Die gleiche Katalogisierungsidee wandert in die Gastlaufzeit.
- Die Gastlaufzeit erhält kompakte
ALL_TOOLS-Metadaten sowie Such-, Beschreibungs- und Aufruf-Helper für Nicht-MCP-Tools. - MCP-Aufrufe verwenden den generierten Namespace
MCPund dessen$api()-Header statttools.call(...). - Verschachtelte Aufrufe dispatchen über denselben OpenClaw-Executor-Pfad, den Tool Search verwendet.
exec und wait verwenden können.
Tool-Namen und Kollisionen
Das modellsichtbare Toolexec ist das Code-Modus-Tool. Wenn das normale OpenClaw-
Shell-Tool exec aktiviert ist, wird es vor dem Modell verborgen und wie jedes
andere Tool katalogisiert.
Innerhalb der Gastlaufzeit:
tools.call("openclaw:core:exec", input)kann das Shell-Exec-Tool aufrufen, wenn die Richtlinie es erlaubt.tools.exec(...)wird nur installiert, wenn der Shell-Exec-Katalogeintrag einen eindeutigen sicheren Namen hat.- das Code-Modus-Tool
execist niemals rekursiv übertoolsverfügbar.
tools.call(id, input).
Verschachtelte Tool-Ausführung
Jeder verschachtelte Tool-Aufruf überschreitet die Host-Bridge und tritt erneut in OpenClaw ein. Verschachtelte Ausführung erhält:- aktive Agent-ID
- Sitzungs-ID und Sitzungsschlüssel
- Sender- und Channel-Kontext
- Sandbox-Richtlinie
- Genehmigungsrichtlinie
- Plugin-
before_tool_call-Hooks - Abbruchsignal
- Streaming-Updates, wo verfügbar
- Trajectory- und Audit-Ereignisse
maxPendingToolCalls erlaubt.
Laufzeitstatus
Jeder Code-Modus-Lauf hat eine Zustandsmaschine:running: VM führt aus oder verschachtelte Aufrufe sind unterwegs.waiting: VM-Snapshot existiert und kann mitwaitfortgesetzt werden.completed: endgültiger Wert zurückgegeben; Snapshot gelöscht.failed: Fehler zurückgegeben; Snapshot gelöscht.expired: Snapshot oder ausstehender Zustand hat die Aufbewahrung überschritten; kann nicht fortgesetzt werden.aborted: übergeordneter Lauf/Sitzung abgebrochen; Snapshot gelöscht.
wait-Aufruf aus einem
anderen Lauf oder einer anderen Sitzung schlägt fehl.
Snapshot-Speicherung ist begrenzt:
- maximale Snapshot-Bytes pro Lauf
- maximale Live-Snapshots pro Prozess
- Snapshot-TTL
- Bereinigung bei Laufende
- Bereinigung beim Herunterfahren des Gateway, wo Persistenz nicht unterstützt wird
QuickJS-WASI-Laufzeit
OpenClaw lädtquickjs-wasi als direkte Abhängigkeit im besitzenden Paket. Die
Laufzeit verlässt sich nicht auf eine transitive Kopie, die für Proxy, PAC oder andere
nicht verwandte Abhängigkeiten installiert wurde.
Laufzeitverantwortlichkeiten:
- das QuickJS-WASI-WebAssembly-Modul kompilieren oder laden
- pro Code-Modus-Lauf oder Fortsetzung eine isolierte VM erstellen
- Host-Callbacks unter stabilen Namen registrieren
- Speicher- und Interrupt-Limits setzen
- JavaScript auswerten
- ausstehende Jobs abarbeiten
- angehaltenen VM-Status als Snapshot speichern
- Snapshots für
waitwiederherstellen - VM-Handles und Snapshots nach terminalen Zuständen entsorgen
TypeScript
TypeScript-Unterstützung ist nur eine Quelltransformation:- akzeptierte Eingabe: ein TypeScript-Code-String
- Ausgabe: JavaScript-String, der von QuickJS-WASI ausgewertet wird
- kein Typechecking
- keine Modulauflösung
- kein
importoderrequirein v1 - Diagnosemeldungen werden als
failed-Ergebnisse zurückgegeben
Sicherheitsgrenze
Modellcode ist feindlich. Die Laufzeit nutzt mehrschichtige Verteidigung:- QuickJS-WASI außerhalb der Haupt-Event-Loop ausführen
quickjs-wasials direkte Abhängigkeit laden, nicht über Codex oder ein transitives Paket- kein Dateisystem, Netzwerk, Subprozess, Modulimport, keine Umgebungsvariablen oder Host-globalen Objekte im Gast
- QuickJS-Speicher- und Interrupt-Limits verwenden
- Wall-Clock-Timeout des übergeordneten Prozesses erzwingen
- Ausgabe-, Snapshot-, Log- und Pending-Call-Grenzen erzwingen
- Host-Bridge-Werte über einen schmalen JSON-Adapter serialisieren
- Host-Fehler in einfache Gastfehler umwandeln, niemals in Host-Realm-Objekte
- Snapshots bei Timeout, Abbruch, Sitzungsende oder Ablauf verwerfen
- rekursiven Zugriff auf
exec,waitund Tool-Search-Steuerungstools abweisen - verhindern, dass Convenience-Namen-Kollisionen Katalog-Helper verdecken
Fehlercodes
Error-Instanzen, Stack-
Objekte, Prototypen und Host-Funktionen gelangen nicht in QuickJS.
Telemetry
Der Code-Modus meldet:- sichtbare Tool-Namen, die an das Modell gesendet wurden
- verborgene Kataloggröße und Aufschlüsselung nach Quelle
exec- undwait-Zählwerte- Zählwerte für verschachtelte Suchen, Beschreibungen und Aufrufe
- aufgerufene verschachtelte Tool-IDs
- Fehler durch Timeout-, Speicher-, Snapshot- und Ausgabegrenzen
- Snapshot-Lebenszyklusereignisse
Debugging
Verwenden Sie gezieltes Modelltransport-Logging, wenn sich der Code-Modus anders verhält als ein normaler Tool-Lauf:OPENCLAW_DEBUG_MODEL_PAYLOAD=full-redacted.
Dies protokolliert einen begrenzten, redigierten JSON-Snapshot der Modellanfrage; es sollte nur
während des Debuggings verwendet werden, weil Prompts und Nachrichtentext weiterhin erscheinen können.
Für Stream-Debugging verwenden Sie OPENCLAW_DEBUG_SSE=peek, um die ersten fünf
redigierten SSE-Ereignisse zu protokollieren. Der Code-Modus schlägt außerdem fail-closed fehl, wenn die finale Provider-Payload
nicht exakt exec und wait enthält, nachdem die Code-Modus-Oberfläche
aktiviert wurde.
Implementierungsaufbau
Implementierungseinheiten:- Konfigurationsvertrag:
tools.codeMode - Katalog-Builder: effektive Tools zu kompakten Einträgen und ID-Map
- Modelloberflächenadapter: sichtbare Tools durch
execundwaitersetzen - QuickJS-WASI-Laufzeitadapter: laden, auswerten, Snapshot erstellen, wiederherstellen, entsorgen
- Worker-Supervisor: Timeout, Abbruch, Crash-Isolation
- Bridge-Adapter: JSON-sichere Host-Callbacks und Ergebniszustellung
- TypeScript-Transformationsadapter
- Snapshot-Speicher: TTL, Größengrenzen, Lauf-/Sitzungsabgrenzung
- Trajectory-Projektion für verschachtelte Tool-Aufrufe
- Telemetry-Zähler und Diagnosen
node:vm-Child als Sandbox.
Validierungs-Checkliste
Die Code-Modus-Abdeckung sollte beweisen:- deaktivierte Konfiguration lässt die bestehende Tool-Freigabe unverändert
- Objektkonfiguration ohne
enabled: truelässt den Code-Modus deaktiviert - aktivierte Konfiguration gibt dem Modell nur
execundwaitfrei, wenn Tools für den Lauf aktiv sind - rohe Läufe ohne Tools,
disableToolsund leere Allowlists lösen keine Payload-Durchsetzung für den Code-Modus aus - alle effektiv verfügbaren Nicht-MCP-Tools erscheinen in
ALL_TOOLS - abgelehnte Tools erscheinen nicht in
ALL_TOOLS tools.search,tools.describeundtools.callfunktionieren für OpenClaw-ToolsAPI.list("mcp")undAPI.read("mcp/<server>.d.ts")stellen TypeScript-artige MCP-Deklarationen ohne Bridge-/Tool-Aufruf bereit- der MCP-Namespace
$api()bleibt als Inline-Fallback für Schemas verfügbar - MCP-Namespace-Aufrufe funktionieren für sichtbare MCP-Tools mit einer Objekteingabe, während direkte MCP-Katalogeinträge in
tools.*fehlen - Steuerungs-Tools für Tool Search sind sowohl vor der Modelloberfläche als auch vor dem versteckten Katalog verborgen
- verschachtelte Aufrufe behalten Genehmigungs- und Hook-Verhalten bei
- Shell-
execist vor dem Modell verborgen, aber bei Erlaubnis über die Katalog-ID aufrufbar - rekursive Code-Modus-Aufrufe von
execundwaitsind aus Gast-Code nicht aufrufbar - TypeScript-Eingabe wird transformiert und ausgewertet, ohne TypeScript auf deaktivierten oder nur JavaScript nutzenden Pfaden zu laden
import,require, Dateisystem-, Netzwerk- und Umgebungszugriff schlagen fehl- Endlosschleifen laufen in ein Timeout und können den Gateway nicht blockieren
- Fehler durch Speicherlimits beenden die Gast-VM
- Ausgabe- und Snapshot-Limits werden für abgeschlossene und angehaltene Aufrufe durchgesetzt
waitsetzt einen angehaltenen Snapshot fort und gibt den endgültigen Wert zurück- abgelaufene, abgebrochene, sitzungsfremde und unbekannte
runId-Werte schlagen fehl - Transkriptwiedergabe und Persistenz bewahren Code-Modus-Steuerungsaufrufe
- Transkript und Telemetrie zeigen verschachtelte Tool-Aufrufe klar an
E2E-Testplan
Führen Sie diese als Integrations- oder End-to-End-Tests aus, wenn Sie die Runtime ändern:- Starten Sie einen Gateway mit
tools.codeMode.enabled: false. - Senden Sie einen Agent-Turn mit einem kleinen direkten Tool-Set.
- Stellen Sie sicher, dass die für das Modell sichtbaren Tools unverändert sind.
- Starten Sie mit
tools.codeMode.enabled: trueneu. - Senden Sie einen Agent-Turn mit OpenClaw-, Plugin-, MCP- und Client-Test-Tools.
- Stellen Sie sicher, dass die für das Modell sichtbare Tool-Liste exakt
exec,waitist. - Lesen Sie in
execALL_TOOLSund stellen Sie sicher, dass die effektiven Test-Tools vorhanden sind. - Rufen Sie in
execOpenClaw-/Plugin-/Client-Tools übertools.search,tools.describeundtools.callauf. - Rufen Sie in
execAPI.list("mcp")undAPI.read("mcp/<server>.d.ts")auf und stellen Sie sicher, dass die Deklarationsdateien sichtbare MCP-Tools beschreiben. - Rufen Sie in
execMCP-Tools überMCP.<server>.<tool>({ ...input })auf und stellen Sie sicher, dass direkte MCP-Katalogeinträge inALL_TOOLSundtools.*fehlen. - Stellen Sie sicher, dass abgelehnte Tools fehlen und nicht über eine erratene ID aufgerufen werden können.
- Starten Sie einen verschachtelten Tool-Aufruf, der aufgelöst wird, nachdem
execwaitingzurückgegeben hat. - Rufen Sie
waitauf und stellen Sie sicher, dass die wiederhergestellte VM das Tool-Ergebnis erhält. - Stellen Sie sicher, dass die endgültige Antwort Ausgaben enthält, die nach der Wiederherstellung erzeugt wurden.
- Stellen Sie sicher, dass Timeout, Abbruch und Snapshot-Ablauf den Runtime-Zustand bereinigen.
- Exportieren Sie die Trajektorie und stellen Sie sicher, dass verschachtelte Aufrufe unter dem übergeordneten Code-Modus-Aufruf sichtbar sind.
pnpm check:docs ausgeführt werden.