RPC and API
Modo de código
El modo de código es una función experimental del entorno de ejecución de agentes de OpenClaw. Está desactivado de forma
predeterminada. Cuando lo habilitas, OpenClaw cambia lo que el modelo ve durante una ejecución:
en lugar de exponer directamente todos los esquemas de herramientas habilitados, el modelo ve solo
exec y wait.
Esta página documenta el modo de código de OpenClaw. No es el modo de código de Codex. Las dos
funciones comparten un nombre, pero las implementan entornos de ejecución diferentes y exponen
contratos de exec diferentes:
- El modo de código de Codex está habilitado para los hilos del servidor de la aplicación de Codex, a menos que una política
de herramientas restringida desactive el modo de código nativo. Se ejecuta en el arnés de programación de Codex,
donde el modelo escribe comandos de shell mediante un contrato
exec.command. - El modo de código de OpenClaw está deshabilitado a menos que se configure
tools.codeMode.enabled: true. Se ejecuta en el entorno de ejecución genérico de agentes de OpenClaw, donde el modelo escribe programas JavaScript o TypeScript mediante un contratoexec.code.
El modo de código de Codex y la búsqueda dinámica de herramientas nativa de Codex son superficies estables del arnés de Codex.
El modo de código de OpenClaw es un adaptador experimental de superficie de herramientas propiedad de OpenClaw
para ejecuciones genéricas de OpenClaw. Usa quickjs-wasi, un catálogo oculto de herramientas de OpenClaw
y el ejecutor de herramientas normal de OpenClaw.
¿Qué es esto?
El modo de código de OpenClaw permite que el modelo escriba un pequeño programa JavaScript o TypeScript en lugar de elegir directamente de una lista larga de herramientas.
Cuando el modo de código está activo:
- La lista de herramientas visible para el modelo es exactamente
execywait. execevalúa JavaScript o TypeScript generado por el modelo en un worker QuickJS-WASI restringido.- Las herramientas normales de OpenClaw se ocultan del prompt del modelo y se exponen dentro del
programa invitado mediante
ALL_TOOLSytools. - El código invitado puede buscar en el catálogo oculto, describir una herramienta y llamar a una herramienta mediante la misma ruta de ejecución de OpenClaw que usan los turnos normales de agente.
- Las herramientas MCP se agrupan bajo el espacio de nombres
MCP. En modo de código, este espacio de nombres es la única forma compatible de llamar a herramientas MCP. waitreanuda una ejecución en modo de código suspendida cuando todavía hay llamadas anidadas a herramientas pendientes.
La distinción importante: el modo de código cambia la superficie de orquestación orientada al modelo. No reemplaza las herramientas de OpenClaw, las herramientas de Plugin, las herramientas MCP, la autenticación, la política de aprobación, el comportamiento del canal ni la selección de modelo.
¿Por qué es bueno?
El modo de código hace que los catálogos grandes de herramientas sean más fáciles de usar para los modelos.
- Superficie de prompt más pequeña: los proveedores reciben dos herramientas de control en lugar de decenas o cientos de esquemas completos de herramientas.
- Mejor orquestación: el modelo puede usar bucles, uniones, transformaciones pequeñas, lógica condicional y llamadas anidadas paralelas a herramientas dentro de una celda de código.
- Neutral respecto del proveedor: funciona con herramientas de OpenClaw, Plugin, MCP y cliente sin depender de ejecución de código nativa del proveedor.
- La política existente sigue vigente: las llamadas anidadas a herramientas siguen pasando por la política, las aprobaciones, los hooks, el contexto de sesión y las rutas de auditoría de OpenClaw.
- Modo de fallo claro: cuando el modo de código está habilitado explícitamente y el entorno de ejecución no está disponible, OpenClaw falla de forma cerrada en lugar de volver a una exposición amplia directa de herramientas.
El modo de código es especialmente útil para agentes con un catálogo grande de herramientas habilitadas o para flujos de trabajo en los que el modelo necesita repetidamente buscar, combinar y llamar herramientas antes de producir una respuesta.
Cómo habilitarlo
Agrega tools.codeMode.enabled: true a la configuración del agente o del entorno de ejecución:
{ tools: { codeMode: { enabled: true, }, },}También se acepta la forma abreviada:
{ tools: { codeMode: true, },}El modo de código permanece desactivado cuando tools.codeMode se omite, es false o es un objeto
sin enabled: true.
Cuando uses agentes aislados con servidores MCP configurados, asegúrate también de que la
política de herramientas del sandbox permita el Plugin MCP incluido, por ejemplo con
tools.sandbox.tools.alsoAllow: ["bundle-mcp"]. Consulta
Configuración: herramientas y proveedores personalizados.
Usa límites explícitos cuando quieras límites más estrictos:
{ tools: { codeMode: { enabled: true, timeoutMs: 10000, memoryLimitBytes: 67108864, maxOutputBytes: 65536, maxSnapshotBytes: 10485760, maxPendingToolCalls: 16, snapshotTtlSeconds: 900, searchDefaultLimit: 8, maxSearchLimit: 50, }, },}Para confirmar la forma de la carga útil del modelo durante la depuración, ejecuta el Gateway con registro dirigido:
OPENCLAW_DEBUG_CODE_MODE=1 \OPENCLAW_DEBUG_MODEL_TRANSPORT=1 \OPENCLAW_DEBUG_MODEL_PAYLOAD=tools \openclaw gatewayCon el modo de código activo, los nombres de herramientas orientados al modelo registrados deberían ser exec y
wait. Si necesitas la carga útil redactada del proveedor, agrega
OPENCLAW_DEBUG_MODEL_PAYLOAD=full-redacted durante una sesión breve de depuración.
Recorrido técnico
El resto de esta página describe el contrato del entorno de ejecución y los detalles de implementación. Está destinada a mantenedores, autores de Plugin que depuran la exposición de herramientas y operadores que validan despliegues de alto riesgo.
Estado del entorno de ejecución
- Entorno de ejecución:
quickjs-wasi. - Estado predeterminado: deshabilitado.
- Estabilidad: superficie experimental de OpenClaw; el modo de código de Codex es una superficie estable separada del arnés de Codex.
- Superficie objetivo: ejecuciones genéricas de agentes de OpenClaw.
- Postura de seguridad: el código del modelo es hostil.
- Promesa de cara al usuario: habilitar el modo de código nunca vuelve silenciosamente a una exposición amplia directa de herramientas.
Alcance
El modo de código posee la forma de orquestación orientada al modelo para una ejecución preparada. No posee la selección de modelo, el comportamiento del canal, la autenticación, la política de herramientas ni las implementaciones de herramientas.
Dentro del alcance:
- definiciones de herramientas
execywaitvisibles para el modelo - construcción del catálogo oculto de herramientas
- ejecución invitada de JavaScript y TypeScript
- entorno de ejecución worker QuickJS-WASI
- callbacks del host para búsqueda en catálogo, descripción de esquema y llamada a herramienta
- estado reanudable para programas invitados suspendidos
- límites de salida, tiempo de espera, memoria, llamadas pendientes y snapshots
- telemetría y proyección de trayectoria para llamadas anidadas a herramientas
Fuera del alcance:
- ejecución remota de código nativa del proveedor
- semántica de ejecución de shell
- cambiar la autorización existente de herramientas
- scripts persistentes escritos por usuarios
- acceso a gestor de paquetes, archivos, red o módulos en código invitado
- reutilización directa de los componentes internos del modo de código de Codex
Las herramientas propiedad del proveedor, como sandboxes remotos de Python, siguen siendo herramientas separadas. Consulta Ejecución de código.
Términos
Modo de código es el modo del entorno de ejecución de OpenClaw que oculta las herramientas normales del modelo y
expone solo exec y wait.
Entorno de ejecución invitado es la VM JavaScript QuickJS-WASI que evalúa el código del modelo.
Puente de host es la superficie estrecha de callbacks compatibles con JSON desde el código invitado de vuelta a OpenClaw.
Catálogo es la lista con alcance de ejecución de herramientas efectivas después de la política normal de herramientas, la resolución de Plugin, MCP y herramientas de cliente.
Llamada anidada a herramienta es una llamada a herramienta realizada desde código invitado mediante el puente de host.
Snapshot es el estado serializado de la VM QuickJS-WASI guardado para que wait pueda continuar una
ejecución en modo de código suspendida.
Configuración
tools.codeMode.enabled es la puerta de activación. Establecer otros campos de modo de código
no habilita la función.
Campos admitidos:
enabled: booleano. Valor predeterminadofalse. Habilita el modo de código solo cuando estrue.runtime:"quickjs-wasi". Único entorno de ejecución admitido.mode:"only". Exponeexecywait, oculta las herramientas normales del modelo.languages: arreglo de"javascript"y"typescript". El valor predeterminado incluye ambos.timeoutMs: límite de reloj de pared para unexecowait. Valor predeterminado10000. Límite del entorno de ejecución:100a60000.memoryLimitBytes: límite del heap de QuickJS. Valor predeterminado67108864. Límite del entorno de ejecución:1048576a1073741824.maxOutputBytes: límite para texto devuelto, JSON y registros. Valor predeterminado65536. Límite del entorno de ejecución:1024a10485760.maxSnapshotBytes: límite para snapshots serializados de VM. Valor predeterminado10485760. Límite del entorno de ejecución:1024a268435456.maxPendingToolCalls: límite para llamadas anidadas concurrentes a herramientas. Valor predeterminado16. Límite del entorno de ejecución:1a128.snapshotTtlSeconds: cuánto tiempo puede reanudarse una VM suspendida. Valor predeterminado900. Límite del entorno de ejecución:1a86400.searchDefaultLimit: número predeterminado de resultados de búsqueda del catálogo oculto. Valor predeterminado8. El entorno de ejecución lo limita amaxSearchLimit.maxSearchLimit: número máximo de resultados de búsqueda del catálogo oculto. Valor predeterminado50. Límite del entorno de ejecución:1a50.
Si el modo de código está habilitado pero QuickJS-WASI no puede cargarse, OpenClaw falla de forma cerrada para esa ejecución. No expone silenciosamente herramientas normales como alternativa.
Activación
El modo de código se evalúa después de conocer la política efectiva de herramientas y antes de que se ensamble la solicitud final al modelo.
Orden de activación:
- Resolver el agente, modelo, proveedor, sandbox, canal, remitente y política de ejecución.
- Construir la lista efectiva de herramientas de OpenClaw.
- Agregar herramientas de Plugin, MCP y cliente elegibles.
- Aplicar políticas de permitir y denegar.
- Si
tools.codeMode.enabledes falso, continuar con la exposición normal de herramientas. - Si está habilitado y las herramientas están activas para la ejecución, registrar las herramientas efectivas en el catálogo de modo de código.
- Eliminar todas las herramientas normales de la lista de herramientas visible para el modelo.
- Agregar
execywaitde modo de código.
Las ejecuciones que intencionalmente no tienen herramientas, como llamadas sin procesar al modelo, disableTools
o una lista de permitidos vacía, no activan la superficie de modo de código aunque la configuración
contenga tools.codeMode.enabled: true.
El catálogo de modo de código tiene alcance de ejecución. No debe filtrar herramientas de otro agente, sesión, remitente o ejecución.
Herramientas visibles para el modelo
Cuando el modo de código está activo, el modelo ve exactamente estas herramientas de nivel superior:
execwait
Todas las demás herramientas habilitadas se ocultan de la lista de herramientas orientada al modelo y se registran en el catálogo de modo de código.
El modelo debería usar exec para orquestación de herramientas, unión de datos, bucles,
llamadas anidadas paralelas y transformaciones estructuradas. El modelo debería usar
wait solo cuando exec devuelva un resultado waiting reanudable.
exec
exec inicia una celda de modo de código y devuelve un resultado. El código de entrada lo genera el modelo
y debe tratarse como hostil.
Entrada:
type CodeModeExecInput = { code?: string; command?: string; language?: "javascript" | "typescript";};Reglas de entrada:
- Uno de
codeocommanddebe no estar vacío. codees el campo documentado orientado al modelo.commandse acepta como alias compatible con exec para políticas de hooks y reescrituras de confianza; cuando ambos están presentes, los valores deben coincidir.- Los eventos de hooks
execexternos de modo de código incluyentoolKind: "code_mode_exec"e incluyentoolInputKind: "javascript" | "typescript"cuando se conoce el lenguaje de entrada, para que las políticas puedan distinguir las celdas de modo de código de las llamadasexecde estilo shell que comparten el mismo nombre de herramienta. languageusa"javascript"de forma predeterminada.- Si
languagees"typescript", OpenClaw transpila antes de evaluar. execrechazaimport,require, importación dinámica y patrones de cargador de módulos en v1.execno expone recursivamente la implementación normal deexecde shell.
Resultado:
type CodeModeResult = CodeModeCompletedResult | CodeModeWaitingResult | CodeModeFailedResult; type CodeModeCompletedResult = { status: "completed"; value: unknown; output?: CodeModeOutput[]; telemetry: CodeModeTelemetry;}; type CodeModeWaitingResult = { status: "waiting"; runId: string; reason: "pending_tools" | "yield"; pendingToolCalls?: CodeModePendingToolCall[]; output?: CodeModeOutput[]; telemetry: CodeModeTelemetry;}; type CodeModeFailedResult = { status: "failed"; error: string; code?: CodeModeErrorCode; output?: CodeModeOutput[]; telemetry: CodeModeTelemetry;};exec devuelve waiting cuando la VM QuickJS se suspende con estado reanudable que
todavía necesita una continuación visible para el modelo. El resultado incluye un runId para
wait. Las llamadas al puente de espacios de nombres, incluidas las llamadas al espacio de nombres MCP, se vacían automáticamente
dentro de la misma llamada exec/wait mientras están listas, de modo que un bloque de código compacto
pueda inspeccionar $api() y llamar a una herramienta MCP sin forzar una llamada de herramienta del modelo por cada
await de espacio de nombres.
exec devuelve completed solo cuando la VM invitada no tiene trabajo pendiente y el
valor final es compatible con JSON después de que se ejecuta el adaptador de salida de OpenClaw.
wait
wait continúa una VM suspendida en modo código.
Entrada:
type CodeModeWaitInput = { runId: string;};La salida es la misma unión CodeModeResult que devuelve exec.
wait existe porque las herramientas anidadas de OpenClaw pueden ser lentas, interactivas, estar
bloqueadas por aprobaciones o transmitir actualizaciones parciales. El modelo no debería tener que mantener abierta una llamada larga a
exec mientras el host espera trabajo externo.
La instantánea y restauración de QuickJS-WASI es el mecanismo de reanudación v1:
execevalúa código hasta que se completa, falla o se suspende.- Al suspenderse, OpenClaw toma una instantánea de la VM de QuickJS y registra el trabajo de host pendiente.
- Cuando el trabajo pendiente se resuelve,
waitrestaura la instantánea de la VM. - OpenClaw vuelve a registrar callbacks de host mediante nombres estables.
- OpenClaw entrega los resultados de herramientas anidadas en la VM restaurada.
- OpenClaw vacía los trabajos pendientes de QuickJS.
waitdevuelve un resultadocompleted,failedu otro resultadowaiting.
Las instantáneas son estado de runtime, no artefactos de usuario. Tienen límite de tamaño, expiran y están acotadas a la ejecución y la sesión que las crearon.
wait falla cuando:
runIdes desconocido.- la instantánea expiró.
- la ejecución o sesión padre se abortó.
- el llamador no está en el mismo alcance de ejecución/sesión.
- falla la restauración de QuickJS-WASI.
- restaurar superaría los límites configurados.
API de runtime invitado
El runtime invitado expone una API global pequeña:
declare const ALL_TOOLS: ToolCatalogEntry[];declare const tools: ToolCatalog;declare const MCP: Record<string, unknown>;declare const namespaces: Record<string, unknown>; declare function text(value: unknown): void;declare function json(value: unknown): void;declare function yield_control(reason?: string): Promise<void>;ALL_TOOLS es metadato compacto para el catálogo con alcance de ejecución. No contiene
esquemas completos de forma predeterminada.
type ToolCatalogEntry = { id: string; name: string; label?: string; description: string; source: "openclaw" | "plugin" | "mcp" | "client"; sourceName?: string;};El esquema completo se carga solo bajo demanda:
type ToolCatalogEntryWithSchema = ToolCatalogEntry & { parameters: unknown;};Ayudantes de catálogo:
type ToolCatalog = { search(query: string, options?: { limit?: number }): Promise<ToolCatalogEntry[]>; describe(id: string): Promise<ToolCatalogEntryWithSchema>; call(id: string, input?: unknown): Promise<unknown>; [safeToolName: string]: unknown;};Las funciones de herramientas de conveniencia se instalan solo para nombres seguros no ambiguos:
const files = await tools.search("read local file");const fileRead = await tools.describe(files[0].id);const content = await tools.call(fileRead.id, { path: "README.md" }); // If the hidden catalog has an unambiguous `web_search` entry:const hits = await tools.web_search({ query: "OpenClaw code mode" });Las entradas de catálogo MCP no se pueden llamar mediante tools.call(...) ni funciones de conveniencia
en modo código. Se exponen solo mediante el espacio de nombres MCP
generado. Los archivos de declaración de estilo TypeScript están disponibles mediante la
superficie de archivo virtual API de solo lectura, para que los agentes puedan inspeccionar las firmas MCP
sin agregar esquemas MCP al prompt:
const files = await API.list("mcp");const githubApi = await API.read("mcp/github.d.ts"); const issue = await MCP.github.createIssue({ owner: "openclaw", repo: "openclaw", title: "Investigate gateway logs",}); const snapshot = await MCP.chromeDevtools.takeSnapshot({ output: "markdown" });const resource = await MCP.docs.resources.read({ uri: "memo://one" });const prompt = await MCP.docs.prompts.get({ name: "brief", arguments: { topic: "release" },});API.read("mcp/<server>.d.ts") devuelve declaraciones compactas inferidas a partir de los
metadatos de herramientas MCP:
type McpToolResult = { content?: unknown[]; structuredContent?: unknown; isError?: boolean; [key: string]: unknown;}; declare namespace MCP.github { /** Return this TypeScript-style API header. */ function $api(toolName?: string, options?: { schema?: boolean }): Promise<McpApiHeader>; /** * Create a GitHub issue. * @param owner Repository owner * @param repo Repository name * @param title Issue title */ function createIssue(input: { owner: string; repo: string; title: string; body?: string; }): Promise<McpToolResult>;}Los archivos de declaración son virtuales, no archivos escritos bajo el workspace ni el
directorio de estado. Para cada llamada exec en modo código, OpenClaw construye el catálogo de herramientas
con alcance de ejecución, conserva las entradas MCP visibles, renderiza mcp/index.d.ts más una
declaración mcp/<server>.d.ts por cada servidor visible e inyecta esa pequeña
tabla de solo lectura en el worker de QuickJS. El código invitado ve solo el objeto API:
API.list(prefix?) devuelve metadatos de archivo y API.read(path) devuelve el
contenido de declaración seleccionado. Las rutas desconocidas y los segmentos . / .. se rechazan.
Esto mantiene los esquemas MCP grandes fuera del prompt del modelo. El agente aprende que la
API virtual existe a partir de la descripción de la herramienta exec, lee solo el
archivo de declaración necesario y luego llama a MCP.<server>.<tool>() con un argumento de objeto.
MCP.<server>.$api() sigue disponible como alternativa inline cuando el agente
necesita una respuesta de esquema de una sola herramienta dentro del programa.
El runtime invitado no debe exponer objetos del host directamente. Las entradas y salidas cruzan el puente como valores compatibles con JSON con límites de tamaño explícitos.
Espacios de nombres internos
Los espacios de nombres internos dan al modo código una API de dominio concisa sin agregar más
herramientas visibles para el modelo. Una integración propiedad del cargador puede registrar un espacio de nombres
como Issues, Fictions o Calendar; el código invitado luego llama a ese espacio de nombres
dentro del programa QuickJS mientras OpenClaw sigue mostrando solo exec y wait al
modelo.
Los espacios de nombres son internos por ahora. No hay una API pública de espacios de nombres del SDK de Plugin: los espacios de nombres de plugins externos necesitan un contrato propiedad del cargador para que la identidad del plugin, los manifiestos instalados, el estado de autenticación y los descriptores de catálogo en caché no puedan desviarse de las herramientas del plugin que respaldan el espacio de nombres. El modo código del core posee solo el sandbox, la serialización, el filtrado del catálogo y el despacho del puente.
El código invitado puede usar entonces el global directo o el mapa namespaces:
const open = await Issues.list({ state: "open" });const alsoOpen = await namespaces.Issues.list({ state: "open" });return { count: open.length, alsoCount: alsoOpen.length };Ciclo de vida del registro
El registro de espacios de nombres es local al proceso y está indexado por id de espacio de nombres. Una ejecución típica sigue esta ruta:
- Un cargador de confianza llama a
registerCodeModeNamespaceForPlugin(pluginId, registration). - El modo código crea el
ToolSearchRuntimeoculto para la ejecución y lee su catálogo con alcance de ejecución. createCodeModeNamespaceRuntime(ctx, catalog)conserva solo los registros cuyosrequiredToolNamesson todos visibles y propiedad del mismopluginId.- Cada espacio de nombres visible llama a
createScope(ctx)para la ejecución actual. El alcance recibe contexto de ejecución comoagentId,sessionKey,sessionId,runId, configuración y estado de aborto. - Los datos de alcance se serializan en un descriptor simple y se inyectan en QuickJS como
globals directos y
namespaces.<globalName>. - Las llamadas invitadas se suspenden mediante el puente del worker, resuelven la ruta del espacio de nombres en
el host, asignan la llamada a una herramienta de catálogo declarada y propiedad del plugin, y ejecutan
esa herramienta mediante
ToolSearchRuntime.call. - OpenClaw vacía automáticamente las llamadas de puente de espacio de nombres listas dentro de la llamada activa
a la herramienta
exec/wait. Si el trabajo del espacio de nombres sigue pendiente al expirar el tiempo de espera o el invitado cede explícitamente,waitreanuda el mismo runtime de espacio de nombres más tarde. - La reversión o desinstalación del plugin llama a
clearCodeModeNamespacesForPlugin(pluginId)para que los globals obsoletos no sobrevivan a una carga fallida del plugin.
El invariante importante: las llamadas de espacio de nombres son llamadas a herramientas de catálogo. Usan los
mismos hooks de política, aprobaciones, manejo de abortos, telemetría, proyección de transcripción
y comportamiento de suspensión/reanudación que tools.call(...).
Forma de registro
Registra espacios de nombres desde la integración que posee las herramientas subyacentes. Mantén el alcance pequeño y expón solo verbos de dominio que se asignen a herramientas de catálogo declaradas.
createCodeModeNamespaceTool, registerCodeModeNamespaceForPlugin,} from "../agents/code-mode-namespaces.js"; const pluginId = "github"; registerCodeModeNamespaceForPlugin(pluginId, { id: "github-issues", globalName: "Issues", description: "GitHub issue helpers for the current repository.", requiredToolNames: ["github_list_issues", "github_update_issue"], prompt: "Use Issues.list(params) and Issues.update(number, patch).", createScope: (ctx) => ({ repository: ctx.config, list: createCodeModeNamespaceTool("github_list_issues", ([params]) => params ?? {}), update: createCodeModeNamespaceTool("github_update_issue", ([number, patch]) => ({ number, patch, })), }),});createCodeModeNamespaceTool(toolName, inputMapper) marca un miembro de alcance como una
función de espacio de nombres invocable. El inputMapper opcional recibe los argumentos
invitados y devuelve el objeto de entrada para la herramienta de catálogo subyacente. Sin un
mapeador de entrada, se usa el primer argumento invitado, o {} cuando se omite.
Las funciones de host sin procesar se rechazan antes de que se ejecute el código invitado:
createScope: () => ({ // Wrong: this bypasses the catalog tool lifecycle and will be rejected. list: async () => githubClient.listIssues(),});Propiedad y visibilidad
La propiedad del espacio de nombres está vinculada al pluginId del llamador del registro.
requiredToolNames es a la vez una puerta de visibilidad y una comprobación de propiedad:
- toda herramienta requerida debe existir en el catálogo de ejecución
- toda herramienta requerida debe tener
sourceName === pluginId - el espacio de nombres se oculta cuando cualquier herramienta requerida falta o pertenece a otro plugin
- cada ruta invocable puede apuntar solo a una herramienta nombrada en
requiredToolNames
Esto evita que otro plugin exponga un espacio de nombres registrando una herramienta con el mismo nombre. También mantiene los espacios de nombres alineados con la política ordinaria de agentes: si la ejecución no puede ver las herramientas subyacentes, no puede ver el espacio de nombres.
Por ejemplo, un espacio de nombres de GitHub debería vivir detrás de una extensión propiedad de GitHub que posea autenticación de GitHub, clientes REST o GraphQL, límites de tasa, aprobaciones de escritura y pruebas. El modo código del core no debería incrustar APIs específicas de GitHub, manejo de tokens ni política de proveedor.
Reglas de serialización de alcance
createScope(ctx) puede devolver un objeto simple que contenga valores compatibles con JSON,
arrays, objetos anidados y marcadores de llamada createCodeModeNamespaceTool(...).
Los objetos de host nunca entran directamente en QuickJS.
El serializador rechaza:
- funciones sin procesar
- grafos de objetos circulares
- segmentos de ruta inseguros:
__proto__,constructor,prototype, claves vacías o claves que contienen el separador de ruta interno - valores
globalNameque no son identificadores JavaScript - colisiones de
globalNamecon globals integrados del modo código comotools,namespaces,text,json,yield_controlo__openclaw*
Los valores que no se pueden serializar como JSON se convierten a valores de reserva seguros para JSON antes de cruzar el puente. Los datos binarios, handles, sockets, clientes e instancias de clases deberían permanecer detrás de herramientas de catálogo ordinarias.
Prompts
La description del espacio de nombres y el prompt opcional se agregan al esquema exec
visible para el modelo solo cuando el espacio de nombres es visible para esa ejecución. Úsalos
para enseñar la superficie útil más pequeña:
{ description: "Fiction production service helpers.", prompt: "Use Fictions.riskAudit(), Fictions.promoteIfReady(id, status), and Fictions.unpaidOver(amount).",}Mantén los prompts centrados en el contrato del espacio de nombres, no en la configuración de autenticación, el historial de implementación ni comportamiento no relacionado del plugin.
Limpieza
Los espacios de nombres son registros locales al proceso. Elimínalos cuando el plugin propietario se deshabilite, se desinstale o se revierta:
clearCodeModeNamespacesForPlugin(pluginId);La limpieza del modo de código es propiedad del plugin; borra los registros de
espacios de nombres del plugin cuando termine su ciclo de vida, en lugar de
mantener manejadores de desmontaje por espacio de nombres. Las pruebas pueden
llamar a clearCodeModeNamespacesForTest() para evitar fugas de registros
entre casos.
Lista de comprobación de pruebas
Los cambios de espacio de nombres deben cubrir el límite de seguridad y el comportamiento del invitado:
- el texto del prompt del espacio de nombres aparece solo cuando las herramientas de respaldo son visibles
- las herramientas con el mismo nombre de otro
sourceNameno exponen el espacio de nombres - se rechazan las funciones de alcance sin procesar
- se rechazan los ids de espacio de nombres falsificados y las rutas falsificadas
- las rutas invocables no pueden apuntar a herramientas no declaradas
- los objetos anidados y las referencias compartidas se serializan correctamente
- las llamadas de espacio de nombres se ejecutan mediante herramientas de catálogo y devuelven detalles seguros para JSON
- el código invitado puede capturar los fallos
- las llamadas de espacio de nombres suspendidas se reanudan mediante
wait - la reversión del plugin borra los registros de espacio de nombres de su propiedad
Los espacios de nombres complementan el catálogo genérico tools.search / tools.call. Usa el
catálogo para herramientas arbitrarias habilitadas de OpenClaw, plugins y clientes; usa MCP para
herramientas MCP; usa otros espacios de nombres para APIs de dominio documentadas y propiedad de plugins donde
el código conciso sea más fiable que las búsquedas repetidas de esquemas.
API de salida
text(value) agrega salida legible por humanos al arreglo output.
json(value) agrega un elemento de salida estructurado después de una
serialización compatible con JSON.
El valor final devuelto por el código invitado se convierte en value en un resultado completed.
Elemento de salida:
type CodeModeOutput = { type: "text"; text: string } | { type: "json"; value: unknown };Reglas de salida:
- el orden de salida coincide con las llamadas del invitado
- la salida está limitada por
maxOutputBytes - los valores no serializables se convierten en cadenas simples o errores
- los valores binarios no son compatibles en v1
- las imágenes y los archivos viajan mediante herramientas ordinarias de OpenClaw, no mediante el puente del modo de código
Catálogo de herramientas
El catálogo oculto incluye herramientas después del filtrado de políticas efectivo:
- Herramientas principales de OpenClaw.
- Herramientas de plugins incluidos.
- Herramientas de plugins externos.
- Herramientas MCP.
- Herramientas proporcionadas por el cliente para la ejecución actual.
Los ids de catálogo son estables dentro de una ejecución y deterministas entre conjuntos de herramientas equivalentes cuando sea posible.
Forma de id recomendada:
<source>:<owner>:<tool-name>Ejemplos:
openclaw:core:messageplugin:browser:browser_requestmcp:github:create_issueclient:app:select_fileEl catálogo omite las herramientas de control del modo de código:
execwaittool_search_codetool_searchtool_describetool_call
Esto evita la recursión y mantiene estrecho el contrato orientado al modelo.
Las entradas MCP permanecen en el catálogo con alcance de ejecución para que la política, las aprobaciones, los hooks,
la telemetría, la proyección de transcripción y los ids exactos de herramientas sigan compartiéndose con la ejecución
normal de herramientas. Las vistas orientadas al invitado ALL_TOOLS, tools.search(...),
tools.describe(...) y tools.call(...) omiten las entradas MCP. El espacio de nombres
generado MCP.<server>.<tool>({ ...input }) se resuelve de vuelta al
id exacto del catálogo y luego despacha por la misma ruta de ejecutor.
Interacción con Búsqueda de herramientas
El modo de código sustituye la superficie de modelo Búsqueda de herramientas de OpenClaw para ejecuciones donde está activo.
Cuando tools.codeMode.enabled es true y el modo de código se activa:
- OpenClaw no expone
tool_search_code,tool_search,tool_describe, nitool_callcomo herramientas visibles para el modelo. - La misma idea de catalogación se mueve dentro del runtime invitado.
- El runtime invitado recibe metadatos compactos de
ALL_TOOLSy helpers de búsqueda, descripción e invocación para herramientas no MCP. - Las llamadas MCP usan el espacio de nombres
MCPgenerado y sus encabezados$api()en lugar detools.call(...). - Las llamadas anidadas despachan por la misma ruta de ejecutor de OpenClaw que usa Búsqueda de herramientas.
La página existente Búsqueda de herramientas describe el puente de catálogo compacto de OpenClaw.
El modo de código es la alternativa genérica de OpenClaw para ejecuciones que pueden usar
exec y wait.
Nombres de herramientas y colisiones
La herramienta exec visible para el modelo es la herramienta del modo de código. Si la herramienta normal de shell
exec de OpenClaw está habilitada, se oculta del modelo y se cataloga como cualquier
otra herramienta.
Dentro del runtime invitado:
tools.call("openclaw:core:exec", input)puede llamar a la herramienta shell exec si la política lo permite.tools.exec(...)se instala solo si la entrada de catálogo shell exec tiene un nombre seguro no ambiguo.- la herramienta
execdel modo de código nunca está disponible recursivamente mediantetools.
Si dos herramientas se normalizan al mismo nombre de conveniencia seguro, OpenClaw omite la
función de conveniencia y requiere tools.call(id, input).
Ejecución anidada de herramientas
Cada llamada de herramienta anidada cruza el puente del host y vuelve a entrar en OpenClaw.
La ejecución anidada preserva:
- id del agente activo
- id de sesión y clave de sesión
- contexto del remitente y canal
- política de sandbox
- política de aprobación
- hooks
before_tool_calldel plugin - señal de cancelación
- actualizaciones de streaming cuando estén disponibles
- eventos de trayectoria y auditoría
Las llamadas anidadas se proyectan en la transcripción como llamadas de herramientas reales para que los paquetes de soporte puedan mostrar qué ocurrió. La proyección identifica la llamada de herramienta de modo de código padre y el id de la herramienta anidada.
Las llamadas anidadas paralelas se permiten hasta maxPendingToolCalls.
Estado del runtime
Cada ejecución de modo de código tiene una máquina de estados:
running: la VM se está ejecutando o hay llamadas anidadas en curso.waiting: existe una instantánea de la VM y puede reanudarse conwait.completed: se devolvió el valor final; se eliminó la instantánea.failed: se devolvió un error; se eliminó la instantánea.expired: la instantánea o el estado pendiente superó la retención; no puede reanudarse.aborted: se canceló la ejecución/sesión padre; se eliminó la instantánea.
El estado tiene alcance por ejecución de agente, sesión e id de llamada de herramienta. Una llamada wait de una
ejecución o sesión diferente falla.
El almacenamiento de instantáneas está acotado:
- bytes máximos de instantánea por ejecución
- instantáneas vivas máximas por proceso
- TTL de instantánea
- limpieza al final de la ejecución
- limpieza al apagar el Gateway donde no se admite persistencia
Runtime QuickJS-WASI
OpenClaw carga quickjs-wasi como dependencia directa en el paquete propietario. El
runtime no depende de una copia transitiva instalada para proxy, PAC u otras
dependencias no relacionadas.
Responsabilidades del runtime:
- compilar o cargar el módulo WebAssembly QuickJS-WASI
- crear una VM aislada por ejecución o reanudación de modo de código
- registrar callbacks del host con nombres estables
- establecer límites de memoria e interrupción
- evaluar JavaScript
- drenar trabajos pendientes
- tomar instantáneas del estado suspendido de la VM
- restaurar instantáneas para
wait - liberar manejadores de VM e instantáneas después de estados terminales
El runtime se ejecuta fuera del bucle de eventos principal de OpenClaw en un worker. Un bucle infinito del invitado no debe bloquear indefinidamente el proceso Gateway.
TypeScript
La compatibilidad con TypeScript es solo una transformación de código fuente:
- entrada aceptada: una cadena de código TypeScript
- salida: cadena JavaScript evaluada por QuickJS-WASI
- sin verificación de tipos
- sin resolución de módulos
- sin
importnirequireen v1 - los diagnósticos se devuelven como resultados
failed
El compilador de TypeScript se carga de forma diferida solo para celdas TypeScript. Las celdas de JavaScript simple y el modo de código deshabilitado no cargan el compilador.
La transformación debe preservar números de línea útiles cuando sea factible.
Límite de seguridad
El código del modelo es hostil. El runtime usa defensa en profundidad:
- ejecutar QuickJS-WASI fuera del bucle de eventos principal
- cargar
quickjs-wasicomo dependencia directa, no mediante Codex ni un paquete transitivo - sin sistema de archivos, red, subprocesos, importación de módulos, variables de entorno ni objetos globales del host en el invitado
- usar límites de memoria e interrupción de QuickJS
- aplicar timeout de reloj de pared del proceso padre
- aplicar límites de salida, instantánea, log y llamadas pendientes
- serializar valores del puente del host mediante un adaptador JSON estrecho
- convertir errores del host en errores simples del invitado, nunca objetos del realm del host
- descartar instantáneas en timeout, cancelación, fin de sesión o vencimiento
- rechazar acceso recursivo a
exec,waity herramientas de control de Búsqueda de herramientas - evitar que colisiones de nombres de conveniencia oculten helpers de catálogo
El sandbox es una capa de seguridad. Los operadores aún pueden necesitar endurecimiento a nivel de SO para implementaciones de alto riesgo.
Códigos de error
type CodeModeErrorCode = | "runtime_unavailable" | "invalid_config" | "invalid_input" | "unsupported_language" | "typescript_transform_failed" | "module_access_denied" | "timeout" | "memory_limit_exceeded" | "output_limit_exceeded" | "snapshot_limit_exceeded" | "snapshot_expired" | "snapshot_restore_failed" | "too_many_pending_tool_calls" | "nested_tool_failed" | "aborted" | "internal_error";Los errores devueltos al invitado son datos simples. Las instancias Error del host, los objetos de pila,
los prototipos y las funciones del host no cruzan hacia QuickJS.
Telemetría
El modo de código informa:
- nombres de herramientas visibles enviados al modelo
- tamaño del catálogo oculto y desglose por fuente
- recuentos de
execywait - recuentos de búsqueda, descripción e invocación anidadas
- ids de herramientas anidadas llamadas
- fallos de límites de timeout, memoria, instantánea y salida
- eventos del ciclo de vida de instantáneas
La telemetría no debe incluir secretos, valores de entorno sin procesar ni entradas de herramientas sin redactar más allá de la política existente de trayectoria de OpenClaw.
Depuración
Usa logging dirigido de transporte de modelo cuando el modo de código se comporte de forma diferente a una ejecución normal de herramienta:
OPENCLAW_DEBUG_CODE_MODE=1 \OPENCLAW_DEBUG_MODEL_TRANSPORT=1 \OPENCLAW_DEBUG_MODEL_PAYLOAD=tools \OPENCLAW_DEBUG_SSE=events \openclaw gatewayPara depurar la forma de la carga útil, usa OPENCLAW_DEBUG_MODEL_PAYLOAD=full-redacted.
Esto registra una instantánea JSON acotada y redactada de la solicitud al modelo; solo debe
usarse durante la depuración porque los prompts y el texto de mensajes aún pueden aparecer.
Para depuración de streams, usa OPENCLAW_DEBUG_SSE=peek para registrar los primeros cinco
eventos SSE redactados. El modo de código también falla en cerrado si la carga útil final del proveedor
no contiene exactamente exec y wait después de que la superficie de modo de código se haya
activado.
Diseño de implementación
Unidades de implementación:
- contrato de configuración:
tools.codeMode - constructor de catálogo: herramientas efectivas a entradas compactas y mapa de ids
- adaptador de superficie de modelo: reemplazar herramientas visibles con
execywait - adaptador de runtime QuickJS-WASI: cargar, evaluar, instantánea, restaurar, liberar
- supervisor de worker: timeout, cancelación, aislamiento de fallos
- adaptador de puente: callbacks del host seguros para JSON y entrega de resultados
- adaptador de transformación TypeScript
- almacén de instantáneas: TTL, límites de tamaño, alcance por ejecución/sesión
- proyección de trayectoria para llamadas de herramientas anidadas
- contadores de telemetría y diagnósticos
La implementación reutiliza conceptos de catálogo y ejecutor de Búsqueda de herramientas, pero
no usa el hijo node:vm como sandbox.
Lista de comprobación de validación
La cobertura del modo de código debe demostrar:
- la configuración deshabilitada deja sin cambios la exposición de herramientas existente
- la configuración de objeto sin
enabled: truedeja deshabilitado el modo de código - la configuración habilitada expone solo
execywaital modelo cuando las herramientas están activas para la ejecución - las ejecuciones sin herramientas sin procesar,
disableToolsy las listas de permitidos vacías no activan la aplicación obligatoria de la carga útil del modo de código - todas las herramientas efectivas que no son MCP aparecen en
ALL_TOOLS - las herramientas denegadas no aparecen en
ALL_TOOLS tools.search,tools.describeytools.callfuncionan para herramientas de OpenClawAPI.list("mcp")yAPI.read("mcp/<server>.d.ts")exponen declaraciones MCP de estilo TypeScript sin una llamada de puente/herramienta- el espacio de nombres MCP
$api()permanece disponible como alternativa insertada para esquemas - las llamadas al espacio de nombres MCP funcionan para herramientas MCP visibles con una entrada de objeto, mientras que
las entradas directas del catálogo MCP están ausentes de
tools.* - las herramientas de control de Búsqueda de herramientas están ocultas tanto de la superficie del modelo como del catálogo oculto
- las llamadas anidadas conservan el comportamiento de aprobación y hooks
- el
execde shell está oculto para el modelo, pero puede llamarse por id de catálogo cuando está permitido execywaitrecursivos del modo de código no pueden llamarse desde código invitado- la entrada TypeScript se transforma y evalúa sin cargar TypeScript en rutas deshabilitadas o solo JavaScript
import,require, el sistema de archivos, la red y el acceso al entorno fallan- los bucles infinitos agotan el tiempo de espera y no pueden bloquear el Gateway
- los fallos del límite de memoria terminan la VM invitada
- los límites de salida e instantánea se aplican para llamadas completadas y suspendidas
waitreanuda una instantánea suspendida y devuelve el valor final- los valores
runIdcaducados, abortados, de sesión incorrecta y desconocidos fallan - la reproducción y persistencia de la transcripción conservan las llamadas de control del modo de código
- la transcripción y la telemetría muestran claramente las llamadas de herramienta anidadas
Plan de pruebas E2E
Ejecuta estas como pruebas de integración o de extremo a extremo al cambiar el runtime:
- Inicia un Gateway con
tools.codeMode.enabled: false. - Envía un turno de agente con un pequeño conjunto directo de herramientas.
- Comprueba que las herramientas visibles para el modelo no cambian.
- Reinicia con
tools.codeMode.enabled: true. - Envía un turno de agente con herramientas de prueba de OpenClaw, plugin, MCP y cliente.
- Comprueba que la lista de herramientas visible para el modelo es exactamente
exec,wait. - En
exec, leeALL_TOOLSy comprueba que las herramientas de prueba efectivas están presentes. - En
exec, llama a herramientas de OpenClaw/plugin/cliente mediantetools.search,tools.describeytools.call. - En
exec, llama aAPI.list("mcp")yAPI.read("mcp/<server>.d.ts"), y comprueba que los archivos de declaración describen las herramientas MCP visibles. - En
exec, llama a herramientas MCP medianteMCP.<server>.<tool>({ ...input })y comprueba que las entradas directas del catálogo MCP están ausentes deALL_TOOLSytools.*. - Comprueba que las herramientas denegadas están ausentes y no pueden llamarse mediante un id adivinado.
- Inicia una llamada de herramienta anidada que se resuelve después de que
execdevuelvawaiting. - Llama a
waity comprueba que la VM restaurada recibe el resultado de la herramienta. - Comprueba que la respuesta final contiene la salida producida después de restaurar.
- Comprueba que el tiempo de espera, la cancelación y la caducidad de instantáneas limpian el estado del runtime.
- Exporta la trayectoria y comprueba que las llamadas anidadas son visibles bajo la llamada principal de modo de código.
Los cambios solo de documentación en esta página aun así deben ejecutar pnpm check:docs.