RPC and API
Режим кода
Режим кода — экспериментальная, включаемая по желанию функция среды выполнения агентов OpenClaw. Когда
она включена, модель больше не видит схемы всех включённых инструментов; вместо этого она видит
exec, wait и все инструменты только для прямого вызова, структурированный результат которых не может пройти
через гостевой мост, поддерживающий только JSON. Модель пишет небольшую программу на JavaScript или TypeScript,
которая ищет и описывает инструменты в скрытом каталоге и вызывает их.
На этой странице описан режим кода OpenClaw, а не Codex Code Mode. У этих двух функций
одинаковое название и одинаковые имена управляющих инструментов (exec, wait), но это
отдельные реализации:
- Codex Code Mode работает внутри среды программирования Codex. Его инструмент
exec— это инструмент с грамматикой свободной формы: модель пишет исходный код JavaScript без обёртки (при необходимости добавляя в начало строку прагмы// @exec: {...}с параметрами выполнения), который выполняется в среде выполнения Deno/V8. - Режим кода OpenClaw работает в универсальной среде выполнения агентов OpenClaw и
отключён, если не настроен параметр
tools.codeMode.enabled: true. Его инструментexecпринимает полезную нагрузку JSON{ code, language }, выполняемую в рабочем процессе QuickJS-WASI.
Обе функции предоставляют среду выполнения JavaScript, а не оболочечных команд. Считайте их
независимыми функциями с разными реализациями, которые лишь предоставляют
инструменты exec/wait с одинаковыми именами.
Что он делает
- Список видимых модели инструментов сокращается до
exec,waitи всех инструментов только для прямого вызова, таких какcomputer, чьи результаты с изображениями не могут пройти через гостевой мост. execвыполняет созданный моделью код JavaScript или TypeScript в изолированном рабочем потоке QuickJS-WASI.- Все включённые инструменты, которые могут быть добавлены в каталог (ядро OpenClaw, плагины, MCP, клиент), скрываются из
запроса модели и предоставляются внутри гостевой программы через
ALL_TOOLSиtools. - Гостевой код ищет в скрытом каталоге, получает описание схемы инструмента и вызывает инструмент через тот же путь выполнения, который используется в обычных ходах агента (политики, подтверждения, хуки и телеметрия по-прежнему применяются).
- Инструменты MCP сгруппированы в пространстве имён
MCP; в режиме кода это единственный поддерживаемый способ их вызова. waitвозобновляет приостановленный запуск режима кода, когда вложенные вызовы инструментов всё ещё ожидают завершения.
Режим кода изменяет только доступную модели поверхность оркестрации. Он не заменяет инструменты, инструменты плагинов, инструменты MCP, аутентификацию, политику подтверждений, поведение каналов или выбор модели.
Зачем его использовать
- Меньше данных в запросе: поставщики получают два управляющих инструмента и лишь несколько обязательных прямых инструментов вместо десятков или сотен полных схем инструментов.
- Улучшенная оркестрация: модель может использовать циклы, объединения, небольшие преобразования, условную логику и параллельные вложенные вызовы инструментов в одной ячейке кода.
- Независимость от поставщика: работает с инструментами OpenClaw, плагинов, MCP и клиентов без зависимости от встроенного выполнения кода на стороне поставщика.
- Безопасный отказ: если режим кода включён, но среда выполнения QuickJS-WASI недоступна, запуск завершается ошибкой вместо неявного возврата к широкому набору инструментов для прямого вызова.
Наиболее полезен для агентов с большим каталогом включённых инструментов или рабочих процессов, в которых модели необходимо найти, объединить и вызвать несколько инструментов перед ответом.
Включение
{ tools: { codeMode: { enabled: true, }, },}Сокращённая форма:
{ tools: { codeMode: true, },}Режим кода остаётся выключенным, если tools.codeMode отсутствует, имеет значение false или является объектом
без enabled: true.
Если вы используете изолированных агентов с настроенными серверами MCP, также разрешите
встроенный плагин MCP в политике инструментов песочницы, например
tools.sandbox.tools.alsoAllow: ["bundle-mcp"]. См.
Конфигурация — инструменты и пользовательские поставщики.
Для более строгих ограничений явно задайте пределы:
{ tools: { codeMode: { enabled: true, timeoutMs: 10000, memoryLimitBytes: 67108864, maxOutputBytes: 65536, maxSnapshotBytes: 10485760, maxPendingToolCalls: 16, snapshotTtlSeconds: 900, searchDefaultLimit: 8, maxSearchLimit: 50, }, },}Чтобы при отладке проверить структуру полезной нагрузки модели, запустите Gateway с целевым журналированием:
OPENCLAW_DEBUG_CODE_MODE=1 \OPENCLAW_DEBUG_MODEL_TRANSPORT=1 \OPENCLAW_DEBUG_MODEL_PAYLOAD=tools \openclaw gatewayПри активном режиме кода в журнале должны отображаться имена инструментов, доступных модели: exec и
wait. Чтобы получить полную отредактированную полезную нагрузку поставщика, добавьте
OPENCLAW_DEBUG_MODEL_PAYLOAD=full-redacted на время короткого сеанса отладки.
Технический обзор
В оставшейся части страницы рассматриваются контракт среды выполнения и подробности реализации для сопровождающих, авторов плагинов, отлаживающих предоставление инструментов, и операторов, проверяющих развёртывания с высоким уровнем риска.
Состояние среды выполнения
| Среда выполнения | quickjs-wasi |
| Состояние по умолчанию | отключено |
| Стабильность | экспериментальная поверхность OpenClaw (Codex Code Mode — отдельная стабильная поверхность среды Codex) |
| Целевая область | универсальные запуски агентов OpenClaw |
| Модель безопасности | код модели считается враждебным |
| Обещание пользователю | включение режима кода никогда не приводит к неявному возврату к широкому набору инструментов для прямого вызова |
Область действия
Режим кода определяет доступную модели форму оркестрации для подготовленного запуска. Он не управляет выбором модели, поведением каналов, аутентификацией, политикой инструментов или реализациями инструментов.
В область действия входят: доступные модели определения управляющих и прямых инструментов, построение скрытого каталога инструментов, выполнение гостевого кода JavaScript/TypeScript, рабочая среда QuickJS-WASI, обратные вызовы хоста для поиска, описания и вызова, возобновляемое состояние приостановленных гостевых программ, ограничения вывода, времени ожидания, памяти, ожидающих вызовов и снимков, а также проекция телеметрии и траектории для вложенных вызовов инструментов.
В область действия не входят: удалённое выполнение кода средствами поставщика, семантика выполнения оболочечных команд, изменение существующей авторизации инструментов, постоянные пользовательские скрипты, доступ к менеджеру пакетов, файлам, сети и модулям из гостевого кода, а также прямое повторное использование внутренних компонентов Codex Code Mode.
Инструменты, принадлежащие поставщику, например удалённые песочницы Python, являются отдельными инструментами. См. Выполнение кода.
Термины
- Режим кода: режим среды выполнения OpenClaw, который скрывает совместимые с каталогом инструменты
модели и предоставляет
exec,wait, а также обязательные инструменты только для прямого вызова. - Гостевая среда выполнения: виртуальная машина JavaScript QuickJS-WASI, выполняющая код модели.
- Мост хоста: узкая поверхность обратных вызовов, совместимая с JSON, из гостевого кода обратно в OpenClaw.
- Каталог: относящийся к запуску список эффективных инструментов после обычного разрешения политики инструментов, плагинов, MCP и клиентских инструментов.
- Вложенный вызов инструмента: вызов инструмента из гостевого кода через мост хоста.
- Снимок: сериализованное состояние виртуальной машины QuickJS-WASI, сохранённое, чтобы
waitмог продолжить приостановленный запуск режима кода.
Конфигурация
tools.codeMode.enabled является условием активации; настройка других полей сама по себе
не включает эту функцию.
| Поле | По умолчанию | Ограничение |
|---|---|---|
enabled |
false |
логическое значение; режим кода включает только true |
runtime |
"quickjs-wasi" |
единственное поддерживаемое значение |
mode |
"only" |
предоставляет управляющие и прямые инструменты, остальные добавляет в каталог |
languages |
["javascript", "typescript"] |
любое подмножество этих двух |
timeoutMs |
10000 |
100-60000 |
memoryLimitBytes |
67108864 |
1048576-1073741824 |
maxOutputBytes |
65536 |
1024-10485760 |
maxSnapshotBytes |
10485760 |
1024-268435456 |
maxPendingToolCalls |
16 |
1-128 |
snapshotTtlSeconds |
900 |
1-86400 |
searchDefaultLimit |
8 |
ограничивается значением maxSearchLimit |
maxSearchLimit |
50 |
1-50 |
Если режим кода включён, но QuickJS-WASI не удаётся загрузить, OpenClaw безопасно завершает этот запуск с ошибкой; он не предоставляет неявно обычные инструменты в качестве запасного варианта.
Активация
Режим кода оценивается после определения эффективной политики инструментов и до формирования окончательного запроса модели:
- Определить агента, модель, поставщика, песочницу, канал, отправителя и политику запуска.
- Сформировать эффективный список инструментов OpenClaw, добавив подходящие инструменты плагинов, MCP и клиентов.
- Применить политику разрешений и запретов.
- Если
tools.codeMode.enabledимеет значение false, продолжить с обычным предоставлением инструментов. - Если режим включён и инструменты активны для запуска, сохранить обязательные инструменты только для прямого вызова и зарегистрировать все эффективные инструменты, подходящие для каталога, в каталоге режима кода.
- Удалить добавленные в каталог инструменты из списка, доступного модели; добавить
execиwaitвместе с сохранёнными инструментами только для прямого вызова.
Запуски, в которых инструменты намеренно отсутствуют (непосредственные вызовы модели, disableTools: true
или пустой список tools.allow), не активируют поверхность режима кода, даже
если настроен tools.codeMode.enabled: true. Режим кода и поиск инструментов OpenClaw
взаимоисключающи в рамках одного запуска; если активируется режим кода, Compaction поиска инструментов
не выполняется.
Каталог режима кода относится к конкретному запуску и не должен допускать утечку инструментов из другого агента, сеанса, отправителя или запуска.
Инструменты, доступные модели
Когда режим кода активен, модель видит exec, wait и все обязательные
инструменты только для прямого вызова. Все остальные включённые инструменты скрываются из доступного модели
списка инструментов и регистрируются в каталоге режима кода.
Используйте exec для оркестрации инструментов, объединения данных, циклов, параллельных вложенных вызовов
и структурированных преобразований. Используйте wait только тогда, когда exec возвращает возобновляемый
результат waiting.
exec
exec запускает ячейку режима кода и возвращает один результат. Входной код создаётся
моделью и должен считаться враждебным.
Входные данные:
type CodeModeExecInput = { code?: string; command?: string; language?: "javascript" | "typescript";};Правила:
- Одно из значений
codeилиcommandдолжно быть непустым. code— документированное поле, доступное модели.commandпринимается как совместимый с exec псевдоним для политик хуков и доверенных преобразований (обычный инструмент выполнения команд оболочки OpenClaw также использует полеcommand); если присутствуют оба поля, их значения должны совпадать.- Значение
languageпо умолчанию равно"javascript"; схема представляет его как плоское строковое перечисление ("javascript" | "typescript"), а не объединениеoneOf/anyOf, поскольку некоторые провайдеры отклоняют такие структуры. - Если
languageимеет значение"typescript", OpenClaw выполняет транспиляцию перед вычислением. execотклоняетimport,require, динамический импорт и шаблоны загрузчиков модулей.execникогда рекурсивно не предоставляет обычную реализациюexecдля оболочки.- События хуков
execвнешнего режима кода содержатtoolKind: "code_mode_exec"иtoolInputKind: "javascript" | "typescript"(если они известны), поэтому политики могут отличать ячейки режима кода от вызововexecв стиле оболочки, использующих то же имя инструмента.
Результат:
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 возвращает waiting, когда виртуальная машина QuickJS приостанавливается с возобновляемым состоянием,
которому всё ещё требуется видимое модели продолжение; результат включает runId для
wait. Вызовы через мост пространств имён, включая вызовы пространств имён MCP, автоматически выполняются
в рамках того же вызова exec/wait, пока они готовы, поэтому компактный блок
кода может вызвать инструмент MCP, не требуя отдельного вызова инструмента моделью для каждого
ожидания в пространстве имён.
exec возвращает completed только тогда, когда у гостевой виртуальной машины нет ожидающей работы, а
итоговое значение совместимо с JSON после обработки адаптером вывода OpenClaw.
wait
wait продолжает работу приостановленной виртуальной машины режима кода.
Входные данные:
type CodeModeWaitInput = { runId: string;};Выходные данные представляют собой то же объединение CodeModeResult, которое возвращает exec.
wait существует потому, что вложенные инструменты OpenClaw могут работать медленно, быть интерактивными,
требовать одобрения или передавать частичные обновления; модели не нужно удерживать открытым один длительный
вызов exec, пока хост ожидает завершения внешней работы.
Механизм возобновления использует создание и восстановление снимков QuickJS-WASI:
execвыполняет код до завершения, сбоя или приостановки.- При приостановке OpenClaw создаёт снимок виртуальной машины QuickJS и регистрирует ожидающую работу хоста.
- После завершения ожидающей работы
waitвосстанавливает снимок виртуальной машины и повторно регистрирует обратные вызовы хоста по стабильным именам. - OpenClaw передаёт результаты вложенных инструментов в восстановленную виртуальную машину и выполняет ожидающие задания QuickJS.
waitвозвращает результатcompleted,failedили ещё один результатwaiting.
Снимки являются состоянием среды выполнения, а не пользовательскими артефактами: они хранятся только в карте внутри процесса (без записи в базу данных или на диск), имеют ограничение размера и срок действия, а их область действия ограничена запуском и сеансом, в которых они были созданы.
wait завершается ошибкой (с результатом failed), если:
runIdнеизвестен или срок действия его снимка уже истёк.- вызывающая сторона находится вне области того же запуска или сеанса, что и приостановленный запуск.
- для этого
runIdуже выполняетсяwait. - не удаётся восстановить QuickJS-WASI.
- возобновление приведёт к превышению
maxOutputBytesилиmaxSnapshotBytes.
API гостевой среды выполнения
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 содержит компактные метаданные каталога в области запуска; по умолчанию он не
содержит полные схемы.
type ToolCatalogEntry = { id: string; name: string; label?: string; description: string; source: "openclaw" | "mcp" | "client"; sourceName?: string;};Инструменты плагинов используют source: "openclaw", где sourceName содержит идентификатор
владеющего плагина; отдельного значения источника "plugin" не существует. source: "mcp"
используется только для записей MCP в метаданных sourceName/mcp (и исключается
из ALL_TOOLS/tools.*, см. ниже).
Полная схема загружается только по запросу:
type ToolCatalogEntryWithSchema = ToolCatalogEntry & { parameters: unknown;};Вспомогательные средства каталога:
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;};Удобные функции инструментов устанавливаются только для однозначных безопасных имён:
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" });Записи каталога MCP нельзя вызывать через tools.call(...) или удобные
функции в режиме кода; они доступны только через созданное пространство имён MCP.
Файлы объявлений в стиле TypeScript доступны через виртуальную файловую поверхность
API только для чтения, поэтому агенты могут просматривать сигнатуры MCP,
не добавляя схемы MCP в запрос:
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") возвращает компактные объявления, выведенные из метаданных
инструментов 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>;}Файлы объявлений являются виртуальными и не записываются в рабочую область или каталог
состояния. Для каждого вызова exec в режиме кода OpenClaw создаёт каталог инструментов
в области запуска, сохраняет видимые записи MCP, формирует mcp/index.d.ts и по одному
mcp/<server>.d.ts для каждого видимого сервера, а затем внедряет эту небольшую таблицу
только для чтения в рабочий процесс QuickJS. Гостевой код видит только объект API:
API.list(prefix?) возвращает метаданные файлов, а API.read(path) возвращает
содержимое выбранного объявления. Неизвестные пути и сегменты ./..
отклоняются.
Это позволяет не включать крупные схемы MCP в запрос модели: агент узнаёт
о существовании виртуального API из описания инструмента exec, читает только нужный
файл объявления, а затем вызывает MCP.<server>.<tool>() с одним объектным аргументом.
MCP.<server>.$api() остаётся доступным как встроенный резервный вариант для ответа
со схемой одного инструмента внутри программы.
Гостевая среда выполнения никогда не получает прямого доступа к объектам хоста. Входные и выходные данные передаются через мост как совместимые с JSON значения с явными ограничениями размера.
Внутренние пространства имён
Внутренние пространства имён предоставляют режиму кода лаконичный предметный API без добавления новых
видимых модели инструментов. Интеграция, принадлежащая загрузчику, регистрирует пространство имён, например
Issues или Calendar; затем гостевой код вызывает это пространство имён внутри
программы QuickJS, а модель по-прежнему видит компактную управляющую и прямую поверхность.
Пока пространства имён являются внутренними. Публичного API пространств имён в SDK плагинов нет: для пространств имён внешних плагинов требуется контракт, принадлежащий загрузчику, чтобы идентификатор плагина, установленные манифесты, состояние аутентификации и кэшированные дескрипторы каталога не могли рассинхронизироваться с инструментами плагина, лежащими в основе пространства имён. Основной режим кода отвечает только за песочницу, сериализацию, фильтрацию каталога и диспетчеризацию моста.
Гостевой код может использовать как непосредственный глобальный объект, так и карту namespaces:
const open = await Issues.list({ state: "open" });const alsoOpen = await namespaces.Issues.list({ state: "open" });return { count: open.length, alsoCount: alsoOpen.length };Жизненный цикл реестра
Реестр пространств имён является локальным для процесса и индексируется по идентификатору пространства имён:
- Доверенный загрузчик вызывает
registerCodeModeNamespaceForPlugin(pluginId, registration). - Режим кода создаёт скрытый
ToolSearchRuntimeдля запуска и считывает его каталог в области запуска. createCodeModeNamespaceRuntime(ctx, catalog)сохраняет только те регистрации, всеrequiredToolNamesкоторых видимы и принадлежат одному и тому жеpluginId.- Каждое видимое пространство имён вызывает
createScope(ctx)для текущего запуска, получая контекст запуска, напримерagentId,sessionKey,sessionId,runId, конфигурацию и состояние прерывания. - Данные области сериализуются в простой дескриптор и внедряются в QuickJS
как непосредственные глобальные объекты и
namespaces.<globalName>. - Гостевые вызовы приостанавливаются через мост рабочего процесса, разрешают путь пространства имён
на хосте, сопоставляют вызов с объявленным инструментом каталога, принадлежащим плагину, и
выполняют этот инструмент через
ToolSearchRuntime.callExactId. - Готовые вызовы через мост пространства имён автоматически выполняются внутри активного
вызова
exec/wait; если работа пространства имён всё ещё ожидается на момент истечения тайм-аута или гостевая среда явно уступает управление,waitпозднее возобновляет ту же среду выполнения пространства имён. - При откате или удалении плагина вызывается
clearCodeModeNamespacesForPlugin(pluginId), чтобы устаревшие глобальные объекты не сохранялись после неудачной загрузки плагина.
Вызовы пространств имён являются вызовами инструментов каталога: они используют те же хуки политик,
одобрения, обработку прерывания, телеметрию, проекцию расшифровки и
поведение приостановки и возобновления, что и tools.call(...).
Структура регистрации
Регистрируйте пространства имён из интеграции, которой принадлежат базовые инструменты. Сохраняйте небольшую область и предоставляйте только предметные операции, сопоставленные с объявленными инструментами каталога.
createCodeModeNamespaceTool, registerCodeModeNamespaceForPlugin,} from "../agents/code-mode-namespaces.js"; const pluginId = "github"; registerCodeModeNamespaceForPlugin(pluginId, { id: "github-issues", globalName: "Issues", description: "Вспомогательные средства для работы с задачами GitHub в текущем репозитории.", requiredToolNames: ["github_list_issues", "github_update_issue"], prompt: "Используйте Issues.list(params) и 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) помечает член области видимости как
вызываемую функцию пространства имён. Необязательная функция inputMapper получает гостевые
аргументы и возвращает объект входных данных для соответствующего инструмента каталога; если
она отсутствует, используется первый гостевой аргумент или {}, если он не указан.
Необработанные функции хоста отклоняются до запуска гостевого кода:
createScope: () => ({ // Неверно: это обходит жизненный цикл инструмента каталога и будет отклонено. list: async () => githubClient.listIssues(),});Владение и видимость
Владение пространством имён привязано к pluginId вызывающей стороны, выполняющей регистрацию.
requiredToolNames служит одновременно проверкой видимости и владения:
- каждый обязательный инструмент должен существовать в каталоге запуска
- каждый обязательный инструмент должен иметь
sourceName === pluginId - пространство имён скрывается, если какой-либо обязательный инструмент отсутствует или принадлежит другому плагину
- каждый вызываемый путь может указывать только на инструмент, указанный в
requiredToolNames
Это не позволяет другому плагину предоставить пространство имён путём регистрации одноимённого инструмента и согласует пространства имён с обычной политикой агента: если запуск не видит соответствующие инструменты, он не видит и пространство имён.
Например, пространство имён GitHub должно предоставляться плагином, принадлежащим GitHub, который отвечает за аутентификацию GitHub, клиенты REST/GraphQL, ограничения частоты запросов, подтверждения записи и тесты. Основной режим кода не должен включать специализированные API GitHub, обработку токенов или политику провайдера.
Правила сериализации области видимости
createScope(ctx) может возвращать обычный объект, содержащий совместимые с JSON
значения, массивы, вложенные объекты и маркеры вызова createCodeModeNamespaceTool(...).
Объекты хоста никогда не передаются непосредственно в QuickJS.
Сериализатор отклоняет:
- необработанные функции
- циклические графы объектов
- небезопасные сегменты пути:
__proto__,constructor,prototype, пустые ключи или ключи, содержащие внутренний разделитель пути - значения
globalName, не являющиеся идентификаторами JavaScript - конфликты
globalNameсо встроенными глобальными объектами режима кода, такими какtools,namespaces,text,json,yield_control,MCP,API,ALL_TOOLSили__openclaw*
Значения, которые невозможно сериализовать в JSON, преобразуются в безопасные для JSON резервные значения перед передачей через мост. Двоичные данные, дескрипторы, сокеты, клиенты и экземпляры классов должны оставаться за обычными инструментами каталога.
Подсказки
description пространства имён и необязательный prompt добавляются в видимую модели
схему exec только тогда, когда пространство имён видимо для данного запуска. Используйте
их для описания минимальной полезной поверхности:
{ description: "Вспомогательные средства сервиса создания художественных произведений.", prompt: "Используйте Fictions.riskAudit(), Fictions.promoteIfReady(id, status) и Fictions.unpaidOver(amount).",}Подсказки должны описывать контракт пространства имён, а не настройку аутентификации, историю реализации или несвязанное поведение плагина.
Очистка
Пространства имён регистрируются локально в процессе. Удаляйте их, когда владеющий ими плагин отключается, удаляется или откатывается:
clearCodeModeNamespacesForPlugin(pluginId);Очисткой режима кода управляет плагин; удаляйте регистрации пространств имён плагина,
когда завершается его жизненный цикл, вместо хранения отдельных обработчиков удаления для каждого пространства имён.
Тесты могут вызывать clearCodeModeNamespacesForTest(), чтобы избежать утечки
регистраций между тестовыми случаями.
Контрольный список тестирования
Изменения пространств имён должны охватывать границу безопасности и поведение гостевой среды:
- текст подсказки пространства имён появляется только тогда, когда соответствующие инструменты видимы
- одноимённые инструменты из другого
sourceNameне предоставляют пространство имён - необработанные функции области видимости отклоняются
- поддельные идентификаторы пространств имён и поддельные пути отклоняются
- вызываемые пути не могут указывать на необъявленные инструменты
- вложенные объекты и общие ссылки сериализуются правильно
- вызовы пространства имён выполняются через инструменты каталога и возвращают безопасные для JSON подробности
- ошибки могут быть перехвачены гостевым кодом
- приостановленные вызовы пространства имён возобновляются через
wait - откат плагина удаляет принадлежащие ему регистрации пространств имён
Пространства имён дополняют универсальный каталог tools.search/tools.call: используйте
каталог для произвольных включённых инструментов OpenClaw, плагинов и клиентов; используйте MCP
для инструментов MCP; используйте другие пространства имён для принадлежащих плагинам документированных API предметной области,
где лаконичный код надёжнее многократных обращений к схемам.
API вывода
text(value)добавляет удобочитаемый вывод в массивoutput.json(value)добавляет элемент структурированного вывода после сериализации в совместимый с JSON формат.- Итоговое возвращаемое значение гостевого кода становится
valueв результатеcompleted.
type CodeModeOutput = { type: "text"; text: string } | { type: "json"; value: unknown };Правила: порядок вывода соответствует порядку гостевых вызовов; объём вывода ограничен
maxOutputBytes; несериализуемые значения преобразуются в обычные строки или
ошибки; двоичные значения не поддерживаются. Изображения и файлы передаются через
обычные инструменты OpenClaw, а не через мост режима кода.
Каталог инструментов
Скрытый каталог содержит инструменты после применения действующей фильтрации политиками в следующем порядке: основные инструменты OpenClaw, инструменты встроенных плагинов, инструменты внешних плагинов, инструменты MCP, затем инструменты, предоставленные клиентом для текущего запуска.
Идентификаторы каталога стабильны в пределах одного запуска и по возможности детерминированы для эквивалентных наборов инструментов. Фактический формат:
<source>:<owner>:<tool-name>где <source> — это openclaw, mcp или client (инструменты плагинов используют
openclaw с идентификатором плагина в качестве <owner>; основные инструменты используют openclaw:core:*).
Примеры:
openclaw:core:messageopenclaw:browser:browser_requestmcp:github:create_issueclient:app:select_fileКаталог не включает управляющие инструменты режима кода (exec, wait, tool_search_code,
tool_search, tool_describe, tool_call) и инструменты только для прямого вызова. Управляющие инструменты
не должны рекурсивно вызываться через каталог; инструменты только для прямого вызова остаются видимыми модели,
поскольку их структурированные результаты невозможно передать через мост QuickJS.
Элементы MCP остаются в каталоге, ограниченном текущим запуском, чтобы политики, подтверждения, хуки,
телеметрия, проекция транскрипта и точные идентификаторы инструментов были общими с
обычным выполнением инструментов. Доступные гостевой среде представления ALL_TOOLS, tools.search(...),
tools.describe(...) и tools.call(...) не включают элементы MCP.
Сгенерированное пространство имён MCP.<server>.<tool>({ ...input }) разрешается обратно в
точный идентификатор каталога и выполняет диспетчеризацию по тому же пути исполнителя.
Взаимодействие с поиском инструментов
Режим кода заменяет поверхность модели поиска инструментов OpenClaw в запусках, где он активен.
Когда tools.codeMode.enabled имеет значение true и режим кода активируется:
- OpenClaw не предоставляет
tool_search_code,tool_search,tool_describeилиtool_callкак видимые модели инструменты. - Та же концепция каталогизации переносится внутрь гостевой среды выполнения.
- Гостевая среда выполнения получает компактные метаданные
ALL_TOOLSи вспомогательные средства поиска, описания и вызова для инструментов, не относящихся к MCP. - Вызовы MCP используют сгенерированное пространство имён
MCPи его заголовки$api()вместоtools.call(...). - Вложенные вызовы диспетчеризуются по тому же пути исполнителя OpenClaw, который использует поиск инструментов.
См. раздел Поиск инструментов, посвящённый компактному мосту каталога OpenClaw, который режим кода заменяет для активных запусков.
Имена инструментов и конфликты
Видимый модели инструмент exec является инструментом режима кода. Если обычный инструмент
оболочки OpenClaw exec включён, он скрывается от модели и добавляется в каталог как
любой другой инструмент.
Внутри гостевой среды выполнения:
tools.call("openclaw:core:exec", input)может вызывать инструмент выполнения команд оболочки, если это разрешено политикой.tools.exec(...)устанавливается только в том случае, если запись инструмента выполнения команд оболочки в каталоге имеет однозначное безопасное имя.- инструмент режима кода
execникогда не доступен рекурсивно черезtools.
Если два инструмента нормализуются в одно и то же безопасное сокращённое имя, OpenClaw не создаёт
вспомогательную функцию и требует использовать tools.call(id, input).
Выполнение вложенных инструментов
Каждый вложенный вызов инструмента пересекает мост хоста и повторно входит в OpenClaw,
сохраняя: идентификатор активного агента, идентификатор и ключ сеанса, контекст отправителя и канала,
политику песочницы, политику подтверждений, хуки плагина before_tool_call, сигнал
прерывания, потоковые обновления, если они доступны, а также события траектории и аудита.
Вложенные вызовы проецируются в транскрипт как реальные вызовы инструментов, чтобы пакеты поддержки показывали произошедшее, причём проекция идентифицирует родительский вызов инструмента режима кода и идентификатор вложенного инструмента.
Допускается до maxPendingToolCalls параллельных вложенных вызовов.
Жизненный цикл запуска и снимка
Каждый запуск режима кода отслеживается во внутрипроцессной карте с ключом runId
(без сохранения на диск или в базу данных). exec/wait возвращают один из трёх статусов
результата: completed, waiting или failed.
- Результат
waitingхранит снимок QuickJS, ожидающие запросы моста и метаданные области действия (идентификатор запуска агента, идентификатор/ключ сеанса), покаwaitне возобновит его или пока не истечёт срок его действия. - Истечение срока действия, неверный сеанс, неверный запуск и неизвестные/уже возобновляемые значения
runIdне создают отдельный конечный статус; они возвращаются как результатfailed(code: "invalid_input") с сообщением, напримерcode mode run is unavailable or expired.илиcode mode run belongs to a different session.. - Снимок запуска удаляется из карты сразу после перехода в состояние
completedилиfailedлибо отбрасывается при завершении работы Gateway (после перезапуска ничего не сохраняется: это временное состояние среды выполнения). - Для работы только для чтения
execможет задатьrestartSafe: true. После этого OpenClaw отклоняет изменяющие состояние вызовы каталога и пространства имён плагинов до выполнения и помечает приостановленные результаты как безопасные для повторного воспроизведения. Если перезапуск прерываетwait, восстановление после перезапуска воссоздаёт ход из транскрипта вместо восстановления локального для процесса снимка. Сам ход восстановления по-прежнему ограничен прошедшими аудит основными инструментами только для чтения и явно безопасными для повторного воспроизведения инструментами плагинов. - OpenClaw ограничивает количество одновременно приостановленных запусков на процесс (64) и
отклоняет новые приостановки сверх этого ограничения с
too many suspended code mode runs..
Размер хранилища снимков ограничен maxSnapshotBytes на запуск, указанным выше ограничением
приостановленных запусков на процесс и snapshotTtlSeconds.
Среда выполнения QuickJS-WASI
OpenClaw загружает quickjs-wasi как прямую зависимость в пакете-владельце; он
не полагается на транзитивную копию, установленную для несвязанной зависимости.
Обязанности среды выполнения: компиляция и загрузка WebAssembly-модуля QuickJS-WASI;
создание одной изолированной виртуальной машины для каждого запуска или возобновления режима кода; регистрация обратных вызовов хоста
под стабильными именами; установка ограничений памяти и прерываний; выполнение JavaScript; обработка
ожидающих заданий; создание снимка состояния приостановленной виртуальной машины; восстановление снимков для wait;
освобождение дескрипторов виртуальной машины и снимков после достижения конечных состояний.
Среда выполнения работает в рабочем потоке Node.js, вне основного цикла событий OpenClaw. Бесконечный цикл в гостевой среде не должен блокировать процесс Gateway на неопределённое время; обработчик прерываний рабочего потока обеспечивает соблюдение тайм-аута по реальному времени независимо от содействия со стороны гостевого кода.
TypeScript
Поддержка TypeScript представляет собой только преобразование исходного кода: на вход принимается одна
строка кода TypeScript; результатом является строка JavaScript, выполняемая
QuickJS-WASI. Проверка типов и разрешение модулей отсутствуют, как и
import/require. Диагностические сообщения возвращаются как результаты failed.
Компилятор TypeScript загружается отложенно только для ячеек TypeScript; обычные ячейки JavaScript и отключённый режим кода никогда его не загружают.
Граница безопасности
Код модели считается враждебным. Среда выполнения использует многоуровневую защиту:
- запускает QuickJS-WASI вне основного цикла событий, в рабочем потоке
- загружает
quickjs-wasiкак прямую зависимость, а не через Codex или транзитивный пакет - не предоставляет гостевой среде доступ к файловой системе, сети, подпроцессам, импорту модулей, переменным окружения или глобальным объектам хоста
- использует ограничения памяти и прерываний QuickJS, а также тайм-аут родительского процесса по реальному времени
- обеспечивает соблюдение ограничений для вывода, снимков, журналов и ожидающих вызовов
- сериализует значения моста хоста через узкий JSON-адаптер
- преобразует ошибки хоста в обычные ошибки гостевой среды, никогда не передавая объекты области хоста
- удаляет снимки при тайм-ауте, прерывании, завершении сеанса или истечении срока действия
- запрещает рекурсивный доступ к
exec,waitи управляющим инструментам Tool Search - не позволяет коллизиям удобных имён затенять вспомогательные функции каталога
Песочница — лишь один из уровней безопасности; для развёртываний с высоким риском операторам всё равно может потребоваться усиление защиты на уровне ОС.
Коды ошибок
type CodeModeErrorCode = | "invalid_input" | "runtime_unavailable" | "timeout" | "output_limit_exceeded" | "snapshot_limit_exceeded" | "internal_error";invalid_input охватывает недопустимые аргументы exec/wait, отключённые языки,
запрещённый доступ к модулям, ошибки преобразования TypeScript, неизвестные, просроченные
или относящиеся к другой области значения runId, а также чрезмерное количество приостановленных запусков. runtime_unavailable
охватывает случаи, когда рабочий процесс QuickJS не запускается или завершается с ненулевым кодом.
Ошибки, возвращаемые гостевой среде, представляют собой обычные данные; экземпляры Error хоста, объекты
стека, прототипы и функции хоста не передаются в QuickJS.
Телеметрия
Поле telemetry каждого результата содержит: размер скрытого каталога и распределение
по источникам (количество openclaw/mcp/client), совокупное количество операций поиска, описания и вызова
для каталога запуска, а также имена инструментов, видимые модели (exec,
wait и сохранённые инструменты только для прямого доступа).
Телеметрия не должна содержать секреты, необработанные значения окружения или нередактированные входные данные инструментов сверх того, что допускает действующая политика OpenClaw в отношении траекторий.
Отладка
Используйте целевое журналирование транспорта модели, если режим кода ведёт себя иначе, чем обычный запуск инструмента:
OPENCLAW_DEBUG_CODE_MODE=1 \OPENCLAW_DEBUG_MODEL_TRANSPORT=1 \OPENCLAW_DEBUG_MODEL_PAYLOAD=tools \OPENCLAW_DEBUG_SSE=events \openclaw gatewayДля отладки структуры полезной нагрузки используйте OPENCLAW_DEBUG_MODEL_PAYLOAD=full-redacted.
При этом записывается ограниченный по размеру, отредактированный JSON-снимок запроса к модели; используйте эту возможность только
во время отладки, поскольку запросы и текст сообщений всё равно могут попасть в журнал.
Для отладки потока используйте OPENCLAW_DEBUG_SSE=peek, чтобы записать первые пять
отредактированных событий SSE. Режим кода также прекращает работу с ошибкой, если итоговая полезная нагрузка провайдера
не содержит ровно один exec, один wait и только разрешённые
инструменты для прямого доступа после активации поверхности режима кода.
Структура реализации
- контракт конфигурации:
tools.codeMode - построитель каталога: преобразование фактических инструментов в компактные записи и карту идентификаторов
- адаптер поверхности модели: замена видимых инструментов управляющими инструментами и инструментами прямого доступа
- адаптер среды выполнения QuickJS-WASI: загрузка, выполнение, создание и восстановление снимков, освобождение ресурсов
- супервизор рабочего процесса: тайм-аут, прерывание, изоляция сбоев
- адаптер моста: безопасные для JSON обратные вызовы хоста и доставка результатов
- адаптер преобразования TypeScript
- хранилище снимков: TTL, ограничения размера, привязка к запуску и сеансу
- проекция траектории для вложенных вызовов инструментов
- счётчики телеметрии и диагностические данные
Реализация повторно использует концепции каталога и исполнителя из Tool Search, но
не использует дочерний node:vm в качестве песочницы.
Контрольный список проверки
Покрытие режима кода должно подтверждать следующее:
- отключённая конфигурация не изменяет существующее предоставление инструментов
- объект конфигурации без
enabled: trueоставляет режим кода отключённым - включённая конфигурация предоставляет модели
exec,waitи только необходимые инструменты прямого доступа, когда инструменты активны для запуска - необработанные запуски без инструментов,
disableToolsи пустые списки разрешений не активируют проверку полезной нагрузки режима кода - все фактические инструменты, не относящиеся к MCP и допускаемые в каталог, представлены в
ALL_TOOLS - инструменты только для прямого доступа остаются видимыми модели и не представлены в
ALL_TOOLS - запрещённые инструменты не представлены в
ALL_TOOLS tools.search,tools.describeиtools.callработают для инструментов OpenClawAPI.list("mcp")иAPI.read("mcp/<server>.d.ts")предоставляют объявления MCP в стиле TypeScript без вызова моста или инструмента- пространство имён MCP
$api()остаётся доступным как встроенный резервный вариант для схем - вызовы пространства имён MCP работают для видимых инструментов MCP с одним объектом на входе, а
прямые записи каталога MCP отсутствуют в
tools.* - управляющие инструменты Tool Search скрыты как от поверхности модели, так и от скрытого каталога
- вложенные вызовы сохраняют поведение подтверждений и перехватчиков
- оболочка
execскрыта от модели, но при наличии разрешения вызывается по идентификатору каталога - рекурсивные
execиwaitрежима кода нельзя вызвать из гостевого кода - входные данные TypeScript преобразуются и выполняются без загрузки TypeScript в отключённых путях или путях только для JavaScript
- доступ к
import,require, файловой системе, сети и окружению завершается ошибкой - бесконечные циклы завершаются по тайм-ауту и не могут блокировать Gateway
- превышение ограничения памяти завершает работу гостевой виртуальной машины
- ограничения вывода и снимков соблюдаются для завершённых и приостановленных вызовов
waitвозобновляет выполнение приостановленного снимка и возвращает итоговое значение- просроченные, прерванные, относящиеся к другому сеансу и неизвестные значения
runIdприводят к ошибке - повторное воспроизведение и сохранение транскрипта сохраняют управляющие вызовы режима кода
- транскрипт и телеметрия наглядно показывают вложенные вызовы инструментов
План сквозного тестирования
При изменении среды выполнения запускайте следующие интеграционные или сквозные тесты:
- Запустите Gateway с
tools.codeMode.enabled: false. - Отправьте ход агента с небольшим набором инструментов прямого доступа.
- Убедитесь, что видимые модели инструменты не изменились.
- Перезапустите с
tools.codeMode.enabled: true. - Отправьте ход агента с тестовыми инструментами OpenClaw, плагина, MCP и клиента.
- Убедитесь, что список видимых модели инструментов содержит
exec,waitи только настроенные инструменты прямого доступа. - В
execпрочитайтеALL_TOOLSи убедитесь, что фактические тестовые инструменты, допускаемые в каталог, присутствуют, а инструменты только для прямого доступа отсутствуют. - В
execвызовите инструменты OpenClaw, плагина и клиента черезtools.search,tools.describeиtools.call. - В
execвызовитеAPI.list("mcp")иAPI.read("mcp/<server>.d.ts")и убедитесь, что файлы объявлений описывают видимые инструменты MCP. - В
execвызовите инструменты MCP черезMCP.<server>.<tool>({ ...input })и убедитесь, что прямые записи каталога MCP отсутствуют вALL_TOOLSиtools.*. - Убедитесь, что запрещённые инструменты отсутствуют и не могут быть вызваны по угаданному идентификатору.
- Запустите вложенный вызов инструмента, который завершается после того, как
execвернётwaiting. - Вызовите
waitи убедитесь, что восстановленная виртуальная машина получает результат инструмента. - Убедитесь, что итоговый ответ содержит вывод, созданный после восстановления.
- Убедитесь, что тайм-аут, прерывание и истечение срока действия снимка очищают состояние среды выполнения.
- Экспортируйте траекторию и убедитесь, что вложенные вызовы видны внутри родительского вызова режима кода.
Даже при изменении только документации на этой странице следует выполнить pnpm check:docs.