RPC and API

Режим кода

Режим кода — экспериментальная функция среды выполнения агентов OpenClaw. По умолчанию он отключен. Когда вы включаете его, OpenClaw меняет то, что модель видит для одного запуска: вместо прямого показа каждой схемы включенного инструмента модель видит только exec и wait.

Эта страница документирует режим кода OpenClaw. Это не режим кода Codex. У этих двух функций общее название, но они реализованы разными средами выполнения и предоставляют разные контракты exec:

  • Режим кода Codex включен для потоков app-server Codex, если ограничительная политика инструментов не отключает нативный режим кода. Он работает в среде программирования Codex, где модель записывает команды оболочки через контракт exec.command.
  • Режим кода OpenClaw отключен, если не настроено tools.codeMode.enabled: true. Он работает в общей среде выполнения агентов OpenClaw, где модель записывает программы JavaScript или TypeScript через контракт exec.code.

Режим кода Codex и нативный для Codex динамический поиск инструментов — стабильные поверхности среды Codex. Режим кода OpenClaw — принадлежащий OpenClaw экспериментальный адаптер поверхности инструментов для общих запусков OpenClaw. Он использует quickjs-wasi, скрытый каталог инструментов OpenClaw и обычный исполнитель инструментов OpenClaw.

Что это?

Режим кода OpenClaw позволяет модели написать небольшую программу на JavaScript или TypeScript вместо прямого выбора из длинного списка инструментов.

Когда режим кода активен:

  • Список инструментов, видимый модели, — ровно exec и wait.
  • exec выполняет созданный моделью JavaScript или TypeScript в ограниченном рабочем процессе QuickJS-WASI.
  • Обычные инструменты OpenClaw скрыты из подсказки модели и доступны внутри гостевой программы через ALL_TOOLS и tools.
  • Гостевой код может искать в скрытом каталоге, описывать инструмент и вызывать инструмент через тот же путь выполнения OpenClaw, который используется обычными ходами агента.
  • Инструменты MCP сгруппированы в пространстве имен MCP. В режиме кода это пространство имен является единственным поддерживаемым способом вызова инструментов MCP.
  • wait возобновляет приостановленный запуск в режиме кода, когда вложенные вызовы инструментов все еще ожидают завершения.

Важное различие: режим кода меняет обращенную к модели поверхность оркестрации. Он не заменяет инструменты OpenClaw, инструменты Plugin, инструменты MCP, аутентификацию, политику подтверждений, поведение каналов или выбор модели.

Почему это хорошо?

Режим кода упрощает использование больших каталогов инструментов моделями.

  • Меньшая поверхность подсказки: провайдеры получают два управляющих инструмента вместо десятков или сотен полных схем инструментов.
  • Лучшая оркестрация: модель может использовать циклы, объединения, небольшие преобразования, условную логику и параллельные вложенные вызовы инструментов внутри одной ячейки кода.
  • Нейтральность к провайдерам: он работает для инструментов OpenClaw, Plugin, MCP и клиентских инструментов без зависимости от нативного выполнения кода провайдером.
  • Существующая политика остается в силе: вложенные вызовы инструментов по-прежнему проходят через политику OpenClaw, подтверждения, хуки, контекст сессии и пути аудита.
  • Ясный режим отказа: когда режим кода явно включен, а среда выполнения недоступна, OpenClaw завершает запуск закрытым отказом вместо отката к широкому прямому показу инструментов.

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

Как включить

Добавьте tools.codeMode.enabled: true в конфигурацию агента или среды выполнения:

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

Также принимается сокращенная форма:

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

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

Когда вы используете изолированных агентов с настроенными MCP-серверами, также убедитесь, что политика инструментов песочницы разрешает встроенный MCP Plugin, например через 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 на короткую сессию отладки.

Технический обзор

Остальная часть этой страницы описывает контракт среды выполнения и детали реализации. Она предназначена для сопровождающих, авторов Plugin, отлаживающих показ инструментов, и операторов, проверяющих развертывания с высоким риском.

Состояние среды выполнения

  • Среда выполнения: quickjs-wasi.
  • Состояние по умолчанию: отключено.
  • Стабильность: экспериментальная поверхность OpenClaw; режим кода Codex — отдельная стабильная поверхность среды Codex.
  • Целевая поверхность: общие запуски агентов OpenClaw.
  • Позиция безопасности: код модели считается враждебным.
  • Обещание для пользователей: включение режима кода никогда не приводит к тихому откату к широкому прямому показу инструментов.

Область действия

Режим кода отвечает за обращенную к модели форму оркестрации для подготовленного запуска. Он не отвечает за выбор модели, поведение каналов, аутентификацию, политику инструментов или реализации инструментов.

Входит в область действия:

  • видимые модели определения инструментов exec и wait
  • построение скрытого каталога инструментов
  • выполнение гостевого JavaScript и TypeScript
  • рабочая среда QuickJS-WASI
  • обратные вызовы хоста для поиска в каталоге, описания схемы и вызова инструмента
  • возобновляемое состояние для приостановленных гостевых программ
  • лимиты вывода, тайм-аута, памяти, ожидающих вызовов и снимков
  • телеметрия и проекция траектории для вложенных вызовов инструментов

Не входит в область действия:

  • нативное удаленное выполнение кода провайдером
  • семантика выполнения оболочки
  • изменение существующей авторизации инструментов
  • постоянные пользовательские скрипты
  • доступ к менеджеру пакетов, файлам, сети или модулям в гостевом коде
  • прямое повторное использование внутренних компонентов режима кода Codex

Инструменты, принадлежащие провайдеру, такие как удаленные песочницы Python, остаются отдельными инструментами. См. Выполнение кода.

Термины

Режим кода — режим среды выполнения OpenClaw, который скрывает обычные инструменты модели и предоставляет только exec и wait.

Гостевая среда выполнения — VM JavaScript QuickJS-WASI, которая выполняет код модели.

Мост хоста — узкая JSON-совместимая поверхность обратных вызовов из гостевого кода обратно в OpenClaw.

Каталог — ограниченный запуском список эффективных инструментов после обычной политики инструментов, Plugin, MCP и разрешения клиентских инструментов.

Вложенный вызов инструмента — вызов инструмента, сделанный из гостевого кода через мост хоста.

Снимок — сериализованное состояние VM QuickJS-WASI, сохраненное, чтобы wait мог продолжить приостановленный запуск в режиме кода.

Конфигурация

tools.codeMode.enabled — переключатель активации. Установка других полей режима кода не включает функцию.

Поддерживаемые поля:

  • enabled: boolean. По умолчанию false. Включает режим кода только при true.
  • runtime: "quickjs-wasi". Единственная поддерживаемая среда выполнения.
  • mode: "only". Предоставляет exec и wait, скрывает обычные инструменты модели.
  • languages: массив "javascript" и "typescript". По умолчанию включает оба.
  • timeoutMs: лимит реального времени для одного exec или wait. По умолчанию 10000. Ограничение среды выполнения: от 100 до 60000.
  • memoryLimitBytes: лимит кучи QuickJS. По умолчанию 67108864. Ограничение среды выполнения: от 1048576 до 1073741824.
  • maxOutputBytes: лимит для возвращаемого текста, JSON и журналов. По умолчанию 65536. Ограничение среды выполнения: от 1024 до 10485760.
  • maxSnapshotBytes: лимит для сериализованных снимков VM. По умолчанию 10485760. Ограничение среды выполнения: от 1024 до 268435456.
  • maxPendingToolCalls: лимит параллельных вложенных вызовов инструментов. По умолчанию 16. Ограничение среды выполнения: от 1 до 128.
  • snapshotTtlSeconds: как долго можно возобновлять приостановленную VM. По умолчанию 900. Ограничение среды выполнения: от 1 до 86400.
  • searchDefaultLimit: количество результатов поиска в скрытом каталоге по умолчанию. По умолчанию 8. Среда выполнения ограничивает это значение до maxSearchLimit.
  • maxSearchLimit: максимальное количество результатов поиска в скрытом каталоге. По умолчанию 50. Ограничение среды выполнения: от 1 до 50.

Если режим кода включен, но QuickJS-WASI не может загрузиться, OpenClaw завершает этот запуск закрытым отказом. Он не открывает обычные инструменты тихо в качестве отката.

Активация

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

Порядок активации:

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

Запуски, в которых намеренно нет инструментов, например прямые вызовы модели, disableTools или пустой список разрешений, не активируют поверхность режима кода, даже если конфигурация содержит tools.codeMode.enabled: true.

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

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

Когда режим кода активен, модель видит ровно эти инструменты верхнего уровня:

  • exec
  • wait

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

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

exec

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

Ввод:

typescript
type CodeModeExecInput = {  code?: string;  command?: string;  language?: "javascript" | "typescript";};

Правила ввода:

  • Одно из code или command должно быть непустым.
  • code — документированное обращенное к модели поле.
  • command принимается как совместимый с exec псевдоним для политик хуков и доверенных переписываний; когда присутствуют оба, значения должны совпадать.
  • Внешние события хуков exec режима кода включают toolKind: "code_mode_exec" и включают toolInputKind: "javascript" | "typescript", когда язык ввода известен, чтобы политики могли отличать ячейки режима кода от shell-style вызовов exec, которые используют то же имя инструмента.
  • language по умолчанию равно "javascript".
  • Если language равно "typescript", OpenClaw транспилирует перед выполнением.
  • exec отклоняет import, require, динамический импорт и шаблоны загрузчика модулей в v1.
  • exec не предоставляет обычную реализацию shell 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, когда VM QuickJS приостанавливается с возобновляемым состоянием, которому все еще нужно продолжение, видимое модели. Результат включает runId для wait. Вызовы моста пространства имен, включая вызовы пространства имен MCP, автоматически исчерпываются внутри того же вызова exec/wait, пока они готовы, поэтому компактный блок кода может проверить $api() и вызвать инструмент MCP без принудительного одного вызова инструмента модели на каждое ожидание пространства имен.

exec возвращает completed только когда у гостевой ВМ нет ожидающей работы, а итоговое значение JSON-совместимо после выполнения адаптера вывода OpenClaw.

wait

wait продолжает приостановленную ВМ в режиме кода.

Ввод:

typescript
type CodeModeWaitInput = {  runId: string;};

Вывод — тот же union CodeModeResult, который возвращает exec.

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

Снимок и восстановление QuickJS-WASI — механизм возобновления v1:

  1. exec выполняет код до завершения, сбоя или приостановки.
  2. При приостановке OpenClaw создает снимок ВМ QuickJS и записывает ожидающую работу хоста.
  3. Когда ожидающая работа завершается, wait восстанавливает снимок ВМ.
  4. OpenClaw повторно регистрирует callback-функции хоста по стабильным именам.
  5. OpenClaw доставляет результаты вложенных инструментов в восстановленную ВМ.
  6. OpenClaw опустошает ожидающие задания QuickJS.
  7. wait возвращает результат completed, failed или еще один результат waiting.

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

wait завершается с ошибкой, когда:

  • runId неизвестен.
  • срок действия снимка истек.
  • родительский запуск или сессия были прерваны.
  • вызывающий находится не в той же области запуска/сессии.
  • восстановление QuickJS-WASI завершается ошибкой.
  • восстановление превысило бы настроенные лимиты.

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

Гостевая среда выполнения предоставляет небольшой глобальный 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" | "plugin" | "mcp" | "client";  sourceName?: string;};

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

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 в prompt:

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;;}

Файлы объявлений виртуальные; это не файлы, записанные в workspace или каталог состояния. Для каждого вызова exec в режиме кода OpenClaw строит каталог инструментов в области запуска, сохраняет видимые записи MCP, формирует mcp/index.d.ts плюс одно объявление mcp/<server>.d.ts для каждого видимого сервера и внедряет эту небольшую таблицу только для чтения в worker QuickJS. Гостевой код видит только объект API: API.list(prefix?) возвращает метаданные файлов, а API.read(path) возвращает содержимое выбранного объявления. Неизвестные пути и сегменты . / .. отклоняются.

Это не дает большим схемам MCP попасть в prompt модели. Агент узнает о существовании виртуального API из описания инструмента exec, читает только нужный файл объявлений, а затем вызывает MCP.<server>.<tool>() с одним объектным аргументом. MCP.<server>.$api() остается доступным как встроенный fallback, когда агенту нужен ответ со схемой одного инструмента внутри программы.

Гостевая среда выполнения не должна напрямую раскрывать объекты хоста. Входы и выходы проходят через мост как JSON-совместимые значения с явными лимитами размера.

Внутренние пространства имен

Внутренние пространства имен дают режиму кода краткий доменный API без добавления новых видимых для модели инструментов. Интеграция, принадлежащая загрузчику, может зарегистрировать пространство имен, например Issues, Fictions или Calendar; затем гостевой код вызывает это пространство имен внутри программы QuickJS, тогда как OpenClaw по-прежнему показывает модели только exec и wait.

Пока пространства имен внутренние. Публичного API пространства имен в Plugin SDK нет: внешним пространствам имен Plugin нужен контракт, принадлежащий загрузчику, чтобы идентичность Plugin, установленные манифесты, состояние аутентификации и кэшированные дескрипторы каталога не расходились с инструментами Plugin, на которых основано пространство имен. Базовый режим кода владеет только песочницей, сериализацией, ограничением каталога и диспетчеризацией через мост.

Гостевой код затем может использовать либо прямой глобальный объект, либо карту namespaces:

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

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

Реестр пространств имен локален для процесса и индексируется по id пространства имен. Типичный запуск проходит такой путь:

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

Важный инвариант: вызовы пространств имен — это вызовы инструментов каталога. Они используют те же хуки политик, approvals, обработку прерывания, телеметрию, проекцию transcript и поведение приостановки/возобновления, что и tools.call(...).

Форма регистрации

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

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

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

typescript
createScope: () => ({  // Wrong: this bypasses the catalog tool lifecycle and will be rejected.  list: async () => githubClient.listIssues(),});

Владение и видимость

Владение пространством имен привязано к pluginId вызывающего регистрацию. requiredToolNames — это одновременно фильтр видимости и проверка владения:

  • каждый требуемый инструмент должен существовать в каталоге запуска
  • каждый требуемый инструмент должен иметь sourceName === pluginId
  • пространство имен скрывается, когда любой требуемый инструмент отсутствует или принадлежит другому Plugin
  • каждый вызываемый путь может указывать только на инструмент, имя которого есть в requiredToolNames

Это не позволяет другому Plugin раскрыть пространство имен, зарегистрировав инструмент с тем же именем. Это также удерживает пространства имен в соответствии с обычной политикой агента: если запуск не видит базовые инструменты, он не видит и пространство имен.

Например, пространство имен GitHub должно находиться за расширением, принадлежащим GitHub, которое владеет аутентификацией GitHub, REST- или GraphQL-клиентами, лимитами запросов, approvals на запись и тестами. Базовый режим кода не должен встраивать API, обработку токенов или политику провайдера, специфичные для GitHub.

Правила сериализации области

createScope(ctx) может вернуть простой объект, содержащий JSON-совместимые значения, массивы, вложенные объекты и маркеры вызовов createCodeModeNamespaceTool(...). Объекты хоста никогда не попадают напрямую в QuickJS.

Сериализатор отклоняет:

  • необработанные функции
  • циклические графы объектов
  • небезопасные сегменты пути: __proto__, constructor, prototype, пустые ключи или ключи, содержащие внутренний разделитель пути
  • значения globalName, которые не являются идентификаторами JavaScript
  • конфликты globalName со встроенными глобальными объектами режима кода, такими как tools, namespaces, text, json, yield_control или __openclaw*

Значения, которые нельзя сериализовать в JSON, преобразуются в JSON-безопасные fallback значения перед пересечением моста. Двоичные данные, дескрипторы, сокеты, клиенты и экземпляры классов должны оставаться за обычными инструментами каталога.

Prompts

description пространства имен и необязательный prompt добавляются в видимую модели схему exec только когда пространство имен видимо для этого запуска. Используйте их, чтобы объяснить минимально полезную поверхность:

typescript
{  description: "Fiction production service helpers.",  prompt:    "Use Fictions.riskAudit(), Fictions.promoteIfReady(id, status), and Fictions.unpaidOver(amount).",}

Держите prompts о контракте пространства имен, а не о настройке аутентификации, истории реализации или несвязанном поведении Plugin.

Очистка

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

typescript
clearCodeModeNamespacesForPlugin(pluginId);

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

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

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

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

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

API вывода

text(value) добавляет человекочитаемый вывод в массив output.

json(value) добавляет структурированный элемент вывода после JSON-совместимой сериализации.

Финальное возвращенное значение гостевого кода становится value в результате completed.

Элемент вывода:

typescript
type CodeModeOutput = { type: "text"; text: string } | { type: "json"; value: unknown };

Правила вывода:

  • порядок вывода соответствует вызовам гостевой среды
  • вывод ограничивается maxOutputBytes
  • несериализуемые значения преобразуются в обычные строки или ошибки
  • двоичные значения не поддерживаются в v1
  • изображения и файлы передаются через обычные инструменты OpenClaw, а не через мост code-mode

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

Скрытый каталог включает инструменты после фильтрации по эффективной политике:

  1. Основные инструменты OpenClaw.
  2. Инструменты встроенных Plugin.
  3. Инструменты внешних Plugin.
  4. Инструменты MCP.
  5. Инструменты, предоставленные клиентом для текущего запуска.

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

Рекомендуемая форма идентификатора:

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

Примеры:

text
openclaw:core:messageplugin:browser:browser_requestmcp:github:create_issueclient:app:select_file

Каталог исключает управляющие инструменты code-mode:

  • exec
  • wait
  • tool_search_code
  • tool_search
  • tool_describe
  • tool_call

Это предотвращает рекурсию и сохраняет узким контракт, видимый модели.

Записи MCP остаются в каталоге, ограниченном запуском, чтобы политика, утверждения, хуки, телеметрия, проекция стенограммы и точные идентификаторы инструментов оставались общими с обычным выполнением инструментов. Представления гостевой среды ALL_TOOLS, tools.search(...), tools.describe(...) и tools.call(...) исключают записи MCP. Сгенерированное пространство имен MCP.<server>.<tool>({ ...input }) разрешается обратно в точный идентификатор каталога, а затем отправляется через тот же путь исполнителя.

Code mode заменяет модельную поверхность OpenClaw Tool Search для запусков, где он активен.

Когда tools.codeMode.enabled равно true и code mode активируется:

  • OpenClaw не предоставляет tool_search_code, tool_search, tool_describe или tool_call как инструменты, видимые модели.
  • Та же идея каталогизации переносится внутрь гостевой среды выполнения.
  • Гостевая среда выполнения получает компактные метаданные ALL_TOOLS и вспомогательные функции поиска, описания и вызова для инструментов не-MCP.
  • Вызовы MCP используют сгенерированное пространство имен MCP и его заголовки $api() вместо tools.call(...).
  • Вложенные вызовы отправляются через тот же путь исполнителя OpenClaw, который использует Tool Search.

Существующая страница Tool Search описывает компактный мост каталога OpenClaw. Code mode — универсальная альтернатива OpenClaw для запусков, которые могут использовать exec и wait.

Имена инструментов и коллизии

Видимый модели инструмент exec — это инструмент code-mode. Если обычный shell-инструмент OpenClaw exec включен, он скрывается от модели и каталогизируется как любой другой инструмент.

Внутри гостевой среды выполнения:

  • tools.call("openclaw:core:exec", input) может вызвать shell-инструмент exec, если политика это разрешает.
  • tools.exec(...) устанавливается только если запись каталога shell-инструмента exec имеет однозначное безопасное имя.
  • инструмент code-mode exec никогда не доступен рекурсивно через tools.

Если два инструмента нормализуются в одно и то же безопасное удобное имя, OpenClaw исключает удобную функцию и требует tools.call(id, input).

Вложенное выполнение инструментов

Каждый вложенный вызов инструмента пересекает мост хоста и повторно входит в OpenClaw.

Вложенное выполнение сохраняет:

  • идентификатор активного агента
  • идентификатор сеанса и ключ сеанса
  • отправителя и контекст канала
  • политику песочницы
  • политику утверждений
  • хуки Plugin before_tool_call
  • сигнал прерывания
  • потоковые обновления, где они доступны
  • события траектории и аудита

Вложенные вызовы проецируются в стенограмму как реальные вызовы инструментов, чтобы пакеты поддержки могли показывать, что произошло. Проекция идентифицирует родительский вызов инструмента code-mode и идентификатор вложенного инструмента.

Параллельные вложенные вызовы разрешены до maxPendingToolCalls.

Состояние среды выполнения

Каждый запуск code-mode имеет конечный автомат:

  • running: VM выполняется или выполняются вложенные вызовы.
  • waiting: снимок VM существует и может быть возобновлен с помощью wait.
  • completed: финальное значение возвращено; снимок удален.
  • failed: ошибка возвращена; снимок удален.
  • expired: снимок или ожидающее состояние превысили срок хранения; возобновление невозможно.
  • aborted: родительский запуск/сеанс отменен; снимок удален.

Состояние ограничено запуском агента, сеансом и идентификатором вызова инструмента. Вызов wait из другого запуска или сеанса завершается с ошибкой.

Хранилище снимков ограничено:

  • максимальный размер снимка в байтах на запуск
  • максимальное количество живых снимков на процесс
  • TTL снимка
  • очистка при завершении запуска
  • очистка при завершении работы Gateway, если постоянное хранение не поддерживается

Среда выполнения QuickJS-WASI

OpenClaw загружает quickjs-wasi как прямую зависимость во владеющем пакете. Среда выполнения не полагается на транзитивную копию, установленную для proxy, PAC или других несвязанных зависимостей.

Обязанности среды выполнения:

  • компилировать или загружать WebAssembly-модуль QuickJS-WASI
  • создавать одну изолированную VM на запуск или возобновление code-mode
  • регистрировать обратные вызовы хоста под стабильными именами
  • задавать ограничения памяти и прерываний
  • выполнять JavaScript
  • выгружать ожидающие задания
  • создавать снимок приостановленного состояния VM
  • восстанавливать снимки для wait
  • освобождать дескрипторы VM и снимки после терминальных состояний

Среда выполнения работает вне основного цикла событий OpenClaw в worker. Бесконечный цикл в гостевой среде не должен бессрочно блокировать процесс Gateway.

TypeScript

Поддержка TypeScript — только исходное преобразование:

  • принимаемый ввод: одна строка кода TypeScript
  • вывод: строка JavaScript, выполняемая QuickJS-WASI
  • без проверки типов
  • без разрешения модулей
  • без import или require в v1
  • диагностика возвращается как результаты failed

Компилятор TypeScript загружается лениво только для ячеек TypeScript. Обычные ячейки JavaScript и отключенный code mode не загружают компилятор.

Преобразование по возможности должно сохранять полезные номера строк.

Граница безопасности

Код модели враждебен. Среда выполнения использует многоуровневую защиту:

  • запускать QuickJS-WASI вне основного цикла событий
  • загружать quickjs-wasi как прямую зависимость, а не через Codex или транзитивный пакет
  • без файловой системы, сети, подпроцессов, импорта модулей, переменных среды или глобальных объектов хоста в гостевой среде
  • использовать ограничения памяти и прерываний QuickJS
  • применять тайм-аут по wall-clock времени родительского процесса
  • применять ограничения вывода, снимков, журналов и ожидающих вызовов
  • сериализовать значения моста хоста через узкий JSON-адаптер
  • преобразовывать ошибки хоста в обычные ошибки гостевой среды, никогда не в объекты области хоста
  • удалять снимки при тайм-ауте, прерывании, завершении сеанса или истечении срока
  • отклонять рекурсивный доступ к exec, wait и управляющим инструментам Tool Search
  • предотвращать затенение вспомогательных функций каталога из-за коллизий удобных имен

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

Коды ошибок

typescript
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";

Ошибки, возвращаемые гостевой среде, являются обычными данными. Экземпляры Error хоста, объекты стека, прототипы и функции хоста не переходят в QuickJS.

Телеметрия

Code mode сообщает:

  • видимые имена инструментов, отправленные модели
  • размер скрытого каталога и разбивку по источникам
  • количества exec и wait
  • количества вложенных поисков, описаний и вызовов
  • идентификаторы вызванных вложенных инструментов
  • сбои из-за ограничений тайм-аута, памяти, снимков и вывода
  • события жизненного цикла снимков

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

Отладка

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

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. Code mode также завершается закрыто, если финальная полезная нагрузка провайдера не содержит ровно exec и wait после активации поверхности code-mode.

Схема реализации

Единицы реализации:

  • контракт конфигурации: tools.codeMode
  • построитель каталога: эффективные инструменты в компактные записи и карту идентификаторов
  • адаптер модельной поверхности: заменить видимые инструменты на exec и wait
  • адаптер среды выполнения QuickJS-WASI: загрузить, выполнить eval, создать снимок, восстановить, освободить
  • супервизор worker: тайм-аут, прерывание, изоляция сбоев
  • адаптер моста: JSON-безопасные обратные вызовы хоста и доставка результатов
  • адаптер преобразования TypeScript
  • хранилище снимков: TTL, ограничения размера, область запуска/сеанса
  • проекция траектории для вложенных вызовов инструментов
  • счетчики телеметрии и диагностика

Реализация повторно использует концепции каталога и исполнителя из Tool Search, но не использует дочерний node:vm как песочницу.

Контрольный список валидации

Покрытие code mode должно доказать:

  • отключенная конфигурация оставляет существующую доступность инструментов без изменений
  • объектная конфигурация без enabled: true оставляет режим кода отключенным
  • включенная конфигурация предоставляет модели только exec и wait, когда инструменты активны для запуска
  • сырые запуски без инструментов, disableTools и пустые списки разрешений не запускают принудительную проверку полезной нагрузки режима кода
  • все эффективные инструменты не-MCP отображаются в 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 скрыты как с поверхности модели, так и из скрытого каталога
  • вложенные вызовы сохраняют поведение утверждений и хуков
  • shell exec скрыт от модели, но вызывается по id каталога, если разрешен
  • рекурсивные exec и wait режима кода не могут вызываться из гостевого кода
  • ввод TypeScript преобразуется и выполняется без загрузки TypeScript на отключенных путях или путях только для JavaScript
  • доступ к import, require, файловой системе, сети и окружению завершается ошибкой
  • бесконечные циклы истекают по тайм-ауту и не могут заблокировать Gateway
  • сбои ограничения памяти завершают гостевую VM
  • ограничения вывода и снимков применяются для завершенных и приостановленных вызовов
  • wait возобновляет приостановленный снимок и возвращает итоговое значение
  • истекшие, прерванные, относящиеся к неправильной сессии и неизвестные значения runId завершаются ошибкой
  • воспроизведение и сохранение транскрипта сохраняют управляющие вызовы режима кода
  • транскрипт и телеметрия ясно показывают вложенные вызовы инструментов

План E2E-тестирования

Запускайте эти проверки как интеграционные или end-to-end тесты при изменении runtime:

  1. Запустите Gateway с tools.codeMode.enabled: false.
  2. Отправьте ход агента с небольшим прямым набором инструментов.
  3. Убедитесь, что инструменты, видимые модели, не изменились.
  4. Перезапустите с tools.codeMode.enabled: true.
  5. Отправьте ход агента с тестовыми инструментами OpenClaw, plugin, MCP и клиента.
  6. Убедитесь, что список инструментов, видимых модели, ровно exec, wait.
  7. В exec прочитайте ALL_TOOLS и убедитесь, что эффективные тестовые инструменты присутствуют.
  8. В exec вызовите инструменты OpenClaw/plugin/клиента через 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. Убедитесь, что запрещенные инструменты отсутствуют и не могут быть вызваны по предполагаемому id.
  12. Запустите вложенный вызов инструмента, который завершается после того, как exec возвращает waiting.
  13. Вызовите wait и убедитесь, что восстановленная VM получает результат инструмента.
  14. Убедитесь, что итоговый ответ содержит вывод, созданный после восстановления.
  15. Убедитесь, что тайм-аут, прерывание и истечение срока снимка очищают состояние runtime.
  16. Экспортируйте траекторию и убедитесь, что вложенные вызовы видны под родительским вызовом режима кода.

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

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

Was this useful?
On this page

On this page