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 недоступна, запуск завершается ошибкой вместо неявного возврата к широкому набору инструментов для прямого вызова.

Наиболее полезен для агентов с большим каталогом включённых инструментов или рабочих процессов, в которых модели необходимо найти, объединить и вызвать несколько инструментов перед ответом.

Включение

json5
{  tools: {    codeMode: {      enabled: true,    },  },}

Сокращённая форма:

json5
{  tools: {    codeMode: true,  },}

Режим кода остаётся выключенным, если tools.codeMode отсутствует, имеет значение false или является объектом без enabled: true.

Если вы используете изолированных агентов с настроенными серверами MCP, также разрешите встроенный плагин MCP в политике инструментов песочницы, например tools.sandbox.tools.alsoAllow: ["bundle-mcp"]. См. Конфигурация — инструменты и пользовательские поставщики.

Для более строгих ограничений явно задайте пределы:

json5
{  tools: {    codeMode: {      enabled: true,      timeoutMs: 10000,      memoryLimitBytes: 67108864,      maxOutputBytes: 65536,      maxSnapshotBytes: 10485760,      maxPendingToolCalls: 16,      snapshotTtlSeconds: 900,      searchDefaultLimit: 8,      maxSearchLimit: 50,    },  },}

Чтобы при отладке проверить структуру полезной нагрузки модели, запустите Gateway с целевым журналированием:

bash
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 безопасно завершает этот запуск с ошибкой; он не предоставляет неявно обычные инструменты в качестве запасного варианта.

Активация

Режим кода оценивается после определения эффективной политики инструментов и до формирования окончательного запроса модели:

  1. Определить агента, модель, поставщика, песочницу, канал, отправителя и политику запуска.
  2. Сформировать эффективный список инструментов OpenClaw, добавив подходящие инструменты плагинов, MCP и клиентов.
  3. Применить политику разрешений и запретов.
  4. Если tools.codeMode.enabled имеет значение false, продолжить с обычным предоставлением инструментов.
  5. Если режим включён и инструменты активны для запуска, сохранить обязательные инструменты только для прямого вызова и зарегистрировать все эффективные инструменты, подходящие для каталога, в каталоге режима кода.
  6. Удалить добавленные в каталог инструменты из списка, доступного модели; добавить exec и wait вместе с сохранёнными инструментами только для прямого вызова.

Запуски, в которых инструменты намеренно отсутствуют (непосредственные вызовы модели, disableTools: true или пустой список tools.allow), не активируют поверхность режима кода, даже если настроен tools.codeMode.enabled: true. Режим кода и поиск инструментов OpenClaw взаимоисключающи в рамках одного запуска; если активируется режим кода, Compaction поиска инструментов не выполняется.

Каталог режима кода относится к конкретному запуску и не должен допускать утечку инструментов из другого агента, сеанса, отправителя или запуска.

Инструменты, доступные модели

Когда режим кода активен, модель видит exec, wait и все обязательные инструменты только для прямого вызова. Все остальные включённые инструменты скрываются из доступного модели списка инструментов и регистрируются в каталоге режима кода.

Используйте exec для оркестрации инструментов, объединения данных, циклов, параллельных вложенных вызовов и структурированных преобразований. Используйте wait только тогда, когда exec возвращает возобновляемый результат waiting.

exec

exec запускает ячейку режима кода и возвращает один результат. Входной код создаётся моделью и должен считаться враждебным.

Входные данные:

typescript
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 в стиле оболочки, использующих то же имя инструмента.

Результат:

typescript
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 продолжает работу приостановленной виртуальной машины режима кода.

Входные данные:

typescript
type CodeModeWaitInput = {  runId: string;};

Выходные данные представляют собой то же объединение CodeModeResult, которое возвращает exec.

wait существует потому, что вложенные инструменты OpenClaw могут работать медленно, быть интерактивными, требовать одобрения или передавать частичные обновления; модели не нужно удерживать открытым один длительный вызов exec, пока хост ожидает завершения внешней работы.

Механизм возобновления использует создание и восстановление снимков QuickJS-WASI:

  1. exec выполняет код до завершения, сбоя или приостановки.
  2. При приостановке OpenClaw создаёт снимок виртуальной машины QuickJS и регистрирует ожидающую работу хоста.
  3. После завершения ожидающей работы wait восстанавливает снимок виртуальной машины и повторно регистрирует обратные вызовы хоста по стабильным именам.
  4. OpenClaw передаёт результаты вложенных инструментов в восстановленную виртуальную машину и выполняет ожидающие задания QuickJS.
  5. wait возвращает результат completed, failed или ещё один результат waiting.

Снимки являются состоянием среды выполнения, а не пользовательскими артефактами: они хранятся только в карте внутри процесса (без записи в базу данных или на диск), имеют ограничение размера и срок действия, а их область действия ограничена запуском и сеансом, в которых они были созданы.

wait завершается ошибкой (с результатом failed), если:

  • runId неизвестен или срок действия его снимка уже истёк.
  • вызывающая сторона находится вне области того же запуска или сеанса, что и приостановленный запуск.
  • для этого runId уже выполняется wait.
  • не удаётся восстановить QuickJS-WASI.
  • возобновление приведёт к превышению maxOutputBytes или maxSnapshotBytes.

API гостевой среды выполнения

typescript
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 содержит компактные метаданные каталога в области запуска; по умолчанию он не содержит полные схемы.

typescript
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.*, см. ниже).

Полная схема загружается только по запросу:

typescript
type ToolCatalogEntryWithSchema = ToolCatalogEntry & {  parameters: unknown;};

Вспомогательные средства каталога:

typescript
type ToolCatalog = {  search(query: string, options?: { limit?: number }): Promise&lt;ToolCatalogEntry[]&gt;;  describe(id: string): Promise&lt;ToolCatalogEntryWithSchema&gt;;  call(id: string, input?: unknown): Promise<unknown>;  [safeToolName: string]: unknown;};

Удобные функции инструментов устанавливаются только для однозначных безопасных имён:

typescript
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 в запрос:

typescript
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:

typescript
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&lt;McpApiHeader&gt;;   /**   * 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&lt;McpToolResult&gt;;}

Файлы объявлений являются виртуальными и не записываются в рабочую область или каталог состояния. Для каждого вызова 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:

javascript
const open = await Issues.list({ state: "open" });const alsoOpen = await namespaces.Issues.list({ state: "open" });return { count: open.length, alsoCount: alsoOpen.length };

Жизненный цикл реестра

Реестр пространств имён является локальным для процесса и индексируется по идентификатору пространства имён:

  1. Доверенный загрузчик вызывает registerCodeModeNamespaceForPlugin(pluginId, registration).
  2. Режим кода создаёт скрытый ToolSearchRuntime для запуска и считывает его каталог в области запуска.
  3. createCodeModeNamespaceRuntime(ctx, catalog) сохраняет только те регистрации, все requiredToolNames которых видимы и принадлежат одному и тому же pluginId.
  4. Каждое видимое пространство имён вызывает createScope(ctx) для текущего запуска, получая контекст запуска, например agentId, sessionKey, sessionId, runId, конфигурацию и состояние прерывания.
  5. Данные области сериализуются в простой дескриптор и внедряются в QuickJS как непосредственные глобальные объекты и namespaces.<globalName>.
  6. Гостевые вызовы приостанавливаются через мост рабочего процесса, разрешают путь пространства имён на хосте, сопоставляют вызов с объявленным инструментом каталога, принадлежащим плагину, и выполняют этот инструмент через ToolSearchRuntime.callExactId.
  7. Готовые вызовы через мост пространства имён автоматически выполняются внутри активного вызова exec/wait; если работа пространства имён всё ещё ожидается на момент истечения тайм-аута или гостевая среда явно уступает управление, wait позднее возобновляет ту же среду выполнения пространства имён.
  8. При откате или удалении плагина вызывается clearCodeModeNamespacesForPlugin(pluginId), чтобы устаревшие глобальные объекты не сохранялись после неудачной загрузки плагина.

Вызовы пространств имён являются вызовами инструментов каталога: они используют те же хуки политик, одобрения, обработку прерывания, телеметрию, проекцию расшифровки и поведение приостановки и возобновления, что и tools.call(...).

Структура регистрации

Регистрируйте пространства имён из интеграции, которой принадлежат базовые инструменты. Сохраняйте небольшую область и предоставляйте только предметные операции, сопоставленные с объявленными инструментами каталога.

typescript
   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 получает гостевые аргументы и возвращает объект входных данных для соответствующего инструмента каталога; если она отсутствует, используется первый гостевой аргумент или {}, если он не указан.

Необработанные функции хоста отклоняются до запуска гостевого кода:

typescript
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 только тогда, когда пространство имён видимо для данного запуска. Используйте их для описания минимальной полезной поверхности:

typescript
{  description: "Вспомогательные средства сервиса создания художественных произведений.",  prompt:    "Используйте Fictions.riskAudit(), Fictions.promoteIfReady(id, status) и Fictions.unpaidOver(amount).",}

Подсказки должны описывать контракт пространства имён, а не настройку аутентификации, историю реализации или несвязанное поведение плагина.

Очистка

Пространства имён регистрируются локально в процессе. Удаляйте их, когда владеющий ими плагин отключается, удаляется или откатывается:

typescript
clearCodeModeNamespacesForPlugin(pluginId);

Очисткой режима кода управляет плагин; удаляйте регистрации пространств имён плагина, когда завершается его жизненный цикл, вместо хранения отдельных обработчиков удаления для каждого пространства имён. Тесты могут вызывать clearCodeModeNamespacesForTest(), чтобы избежать утечки регистраций между тестовыми случаями.

Контрольный список тестирования

Изменения пространств имён должны охватывать границу безопасности и поведение гостевой среды:

  • текст подсказки пространства имён появляется только тогда, когда соответствующие инструменты видимы
  • одноимённые инструменты из другого sourceName не предоставляют пространство имён
  • необработанные функции области видимости отклоняются
  • поддельные идентификаторы пространств имён и поддельные пути отклоняются
  • вызываемые пути не могут указывать на необъявленные инструменты
  • вложенные объекты и общие ссылки сериализуются правильно
  • вызовы пространства имён выполняются через инструменты каталога и возвращают безопасные для JSON подробности
  • ошибки могут быть перехвачены гостевым кодом
  • приостановленные вызовы пространства имён возобновляются через wait
  • откат плагина удаляет принадлежащие ему регистрации пространств имён

Пространства имён дополняют универсальный каталог tools.search/tools.call: используйте каталог для произвольных включённых инструментов OpenClaw, плагинов и клиентов; используйте MCP для инструментов MCP; используйте другие пространства имён для принадлежащих плагинам документированных API предметной области, где лаконичный код надёжнее многократных обращений к схемам.

API вывода

  • text(value) добавляет удобочитаемый вывод в массив output.
  • json(value) добавляет элемент структурированного вывода после сериализации в совместимый с JSON формат.
  • Итоговое возвращаемое значение гостевого кода становится value в результате completed.
typescript
type CodeModeOutput = { type: "text"; text: string } | { type: "json"; value: unknown };

Правила: порядок вывода соответствует порядку гостевых вызовов; объём вывода ограничен maxOutputBytes; несериализуемые значения преобразуются в обычные строки или ошибки; двоичные значения не поддерживаются. Изображения и файлы передаются через обычные инструменты OpenClaw, а не через мост режима кода.

Каталог инструментов

Скрытый каталог содержит инструменты после применения действующей фильтрации политиками в следующем порядке: основные инструменты OpenClaw, инструменты встроенных плагинов, инструменты внешних плагинов, инструменты MCP, затем инструменты, предоставленные клиентом для текущего запуска.

Идентификаторы каталога стабильны в пределах одного запуска и по возможности детерминированы для эквивалентных наборов инструментов. Фактический формат:

text
<source>:<owner>:<tool-name>

где <source> — это openclaw, mcp или client (инструменты плагинов используют openclaw с идентификатором плагина в качестве <owner>; основные инструменты используют openclaw:core:*). Примеры:

text
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
  • не позволяет коллизиям удобных имён затенять вспомогательные функции каталога

Песочница — лишь один из уровней безопасности; для развёртываний с высоким риском операторам всё равно может потребоваться усиление защиты на уровне ОС.

Коды ошибок

typescript
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 в отношении траекторий.

Отладка

Используйте целевое журналирование транспорта модели, если режим кода ведёт себя иначе, чем обычный запуск инструмента:

bash
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 работают для инструментов OpenClaw
  • API.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 приводят к ошибке
  • повторное воспроизведение и сохранение транскрипта сохраняют управляющие вызовы режима кода
  • транскрипт и телеметрия наглядно показывают вложенные вызовы инструментов

План сквозного тестирования

При изменении среды выполнения запускайте следующие интеграционные или сквозные тесты:

  1. Запустите Gateway с tools.codeMode.enabled: false.
  2. Отправьте ход агента с небольшим набором инструментов прямого доступа.
  3. Убедитесь, что видимые модели инструменты не изменились.
  4. Перезапустите с tools.codeMode.enabled: true.
  5. Отправьте ход агента с тестовыми инструментами OpenClaw, плагина, MCP и клиента.
  6. Убедитесь, что список видимых модели инструментов содержит exec, wait и только настроенные инструменты прямого доступа.
  7. В exec прочитайте ALL_TOOLS и убедитесь, что фактические тестовые инструменты, допускаемые в каталог, присутствуют, а инструменты только для прямого доступа отсутствуют.
  8. В exec вызовите инструменты OpenClaw, плагина и клиента через tools.search, tools.describe и tools.call.
  9. В exec вызовите API.list("mcp") и API.read("mcp/<server>.d.ts") и убедитесь, что файлы объявлений описывают видимые инструменты MCP.
  10. В exec вызовите инструменты MCP через MCP.<server>.<tool>({ ...input }) и убедитесь, что прямые записи каталога MCP отсутствуют в ALL_TOOLS и tools.*.
  11. Убедитесь, что запрещённые инструменты отсутствуют и не могут быть вызваны по угаданному идентификатору.
  12. Запустите вложенный вызов инструмента, который завершается после того, как exec вернёт waiting.
  13. Вызовите wait и убедитесь, что восстановленная виртуальная машина получает результат инструмента.
  14. Убедитесь, что итоговый ответ содержит вывод, созданный после восстановления.
  15. Убедитесь, что тайм-аут, прерывание и истечение срока действия снимка очищают состояние среды выполнения.
  16. Экспортируйте траекторию и убедитесь, что вложенные вызовы видны внутри родительского вызова режима кода.

Даже при изменении только документации на этой странице следует выполнить pnpm check:docs.

Связанные материалы

Was this useful?
On this page

On this page