RPC and API
Chế độ mã
Chế độ mã là một tính năng agent-runtime thử nghiệm của OpenClaw. Tính năng này tắt theo
mặc định. Khi bạn bật tính năng này, OpenClaw thay đổi những gì mô hình thấy trong một lần chạy:
thay vì hiển thị trực tiếp mọi schema công cụ đã bật, mô hình chỉ thấy
exec và wait.
Trang này ghi lại chế độ mã của OpenClaw. Đây không phải là chế độ mã của Codex. Hai
tính năng có cùng tên, nhưng được triển khai bởi các runtime khác nhau và hiển thị
các hợp đồng exec khác nhau:
- Codex Code Mode được bật cho các luồng app-server của Codex trừ khi chính sách
công cụ hạn chế tắt chế độ mã gốc. Nó chạy trong harness lập trình của Codex,
nơi mô hình viết lệnh shell thông qua hợp đồng
exec.command. - Chế độ mã của OpenClaw bị tắt trừ khi
tools.codeMode.enabled: trueđược cấu hình. Nó chạy trong runtime agent tổng quát của OpenClaw, nơi mô hình viết chương trình JavaScript hoặc TypeScript thông qua hợp đồngexec.code.
Codex Code Mode và tìm kiếm công cụ động gốc của Codex là các bề mặt harness Codex
ổn định. Chế độ mã của OpenClaw là một bộ điều hợp bề mặt công cụ thử nghiệm
do OpenClaw sở hữu cho các lần chạy OpenClaw tổng quát. Nó sử dụng quickjs-wasi,
một danh mục công cụ OpenClaw ẩn, và trình thực thi công cụ OpenClaw thông thường.
Đây là gì?
Chế độ mã của OpenClaw cho phép mô hình viết một chương trình JavaScript hoặc TypeScript nhỏ thay vì chọn trực tiếp từ một danh sách dài các công cụ.
Khi chế độ mã đang hoạt động:
- Danh sách công cụ mà mô hình thấy chính xác là
execvàwait. execđánh giá JavaScript hoặc TypeScript do mô hình tạo trong một worker QuickJS-WASI bị ràng buộc.- Các công cụ OpenClaw thông thường được ẩn khỏi prompt của mô hình và được hiển thị bên trong
chương trình khách thông qua
ALL_TOOLSvàtools. - Mã khách có thể tìm kiếm danh mục ẩn, mô tả một công cụ, và gọi một công cụ thông qua cùng đường dẫn thực thi OpenClaw dùng bởi các lượt agent thông thường.
- Công cụ MCP được nhóm dưới namespace
MCP. Trong chế độ mã, namespace này là cách duy nhất được hỗ trợ để gọi công cụ MCP. waittiếp tục một lần chạy chế độ mã đã tạm dừng khi các lệnh gọi công cụ lồng nhau vẫn đang chờ.
Điểm khác biệt quan trọng: chế độ mã thay đổi bề mặt điều phối hướng tới mô hình. Nó không thay thế công cụ OpenClaw, công cụ Plugin, công cụ MCP, xác thực, chính sách phê duyệt, hành vi kênh, hay lựa chọn mô hình.
Vì sao điều này tốt?
Chế độ mã giúp mô hình dễ dùng các danh mục công cụ lớn hơn.
- Bề mặt prompt nhỏ hơn: nhà cung cấp nhận hai công cụ điều khiển thay vì hàng chục hoặc hàng trăm schema công cụ đầy đủ.
- Điều phối tốt hơn: mô hình có thể dùng vòng lặp, phép nối, biến đổi nhỏ, logic điều kiện, và các lệnh gọi công cụ lồng nhau song song bên trong một ô mã.
- Trung lập với nhà cung cấp: nó hoạt động cho OpenClaw, Plugin, MCP, và công cụ phía client mà không phụ thuộc vào thực thi mã gốc của nhà cung cấp.
- Chính sách hiện có vẫn được áp dụng: các lệnh gọi công cụ lồng nhau vẫn đi qua chính sách OpenClaw, phê duyệt, hook, ngữ cảnh phiên, và đường dẫn kiểm toán.
- Chế độ lỗi rõ ràng: khi chế độ mã được bật rõ ràng và runtime không khả dụng, OpenClaw thất bại đóng thay vì quay về hiển thị trực tiếp công cụ rộng.
Chế độ mã đặc biệt hữu ích cho các agent có danh mục công cụ đã bật lớn hoặc cho các quy trình nơi mô hình thường xuyên cần tìm kiếm, kết hợp, và gọi công cụ trước khi tạo câu trả lời.
Cách bật
Thêm tools.codeMode.enabled: true vào cấu hình agent hoặc runtime:
{ tools: { codeMode: { enabled: true, }, },}Dạng rút gọn cũng được chấp nhận:
{ tools: { codeMode: true, },}Chế độ mã vẫn tắt khi tools.codeMode bị bỏ qua, là false, hoặc là một đối tượng
không có enabled: true.
Khi bạn dùng agent sandbox với các máy chủ MCP đã cấu hình, cũng hãy đảm bảo
chính sách công cụ sandbox cho phép Plugin MCP đi kèm, ví dụ với
tools.sandbox.tools.alsoAllow: ["bundle-mcp"]. Xem
Cấu hình - công cụ và nhà cung cấp tùy chỉnh.
Dùng giới hạn rõ ràng khi bạn muốn các ràng buộc chặt hơn:
{ tools: { codeMode: { enabled: true, timeoutMs: 10000, memoryLimitBytes: 67108864, maxOutputBytes: 65536, maxSnapshotBytes: 10485760, maxPendingToolCalls: 16, snapshotTtlSeconds: 900, searchDefaultLimit: 8, maxSearchLimit: 50, }, },}Để xác nhận dạng payload của mô hình khi gỡ lỗi, chạy Gateway với ghi log có mục tiêu:
OPENCLAW_DEBUG_CODE_MODE=1 \OPENCLAW_DEBUG_MODEL_TRANSPORT=1 \OPENCLAW_DEBUG_MODEL_PAYLOAD=tools \openclaw gatewayKhi chế độ mã đang hoạt động, tên công cụ hướng tới mô hình trong log phải là exec và
wait. Nếu bạn cần payload nhà cung cấp đã biên tập, hãy thêm
OPENCLAW_DEBUG_MODEL_PAYLOAD=full-redacted cho một phiên gỡ lỗi ngắn.
Chuyến tham quan kỹ thuật
Phần còn lại của trang này mô tả hợp đồng runtime và chi tiết triển khai. Nó dành cho maintainer, tác giả Plugin đang gỡ lỗi việc hiển thị công cụ, và operator xác thực các triển khai rủi ro cao.
Trạng thái runtime
- Runtime:
quickjs-wasi. - Trạng thái mặc định: đã tắt.
- Độ ổn định: bề mặt OpenClaw thử nghiệm; Codex Code mode là một bề mặt harness Codex ổn định riêng biệt.
- Bề mặt mục tiêu: các lần chạy agent OpenClaw tổng quát.
- Tư thế bảo mật: mã mô hình là thù địch.
- Cam kết hướng tới người dùng: bật chế độ mã không bao giờ âm thầm quay về hiển thị trực tiếp công cụ rộng.
Phạm vi
Chế độ mã sở hữu dạng điều phối hướng tới mô hình cho một lần chạy đã chuẩn bị. Nó không sở hữu lựa chọn mô hình, hành vi kênh, xác thực, chính sách công cụ, hay các triển khai công cụ.
Trong phạm vi:
- định nghĩa công cụ
execvàwaitmà mô hình thấy - xây dựng danh mục công cụ ẩn
- thực thi khách JavaScript và TypeScript
- runtime worker QuickJS-WASI
- callback host cho tìm kiếm danh mục, mô tả schema, và gọi công cụ
- trạng thái có thể tiếp tục cho các chương trình khách bị tạm dừng
- giới hạn đầu ra, timeout, bộ nhớ, lệnh gọi đang chờ, và snapshot
- telemetry và chiếu trajectory cho các lệnh gọi công cụ lồng nhau
Ngoài phạm vi:
- thực thi mã từ xa gốc của nhà cung cấp
- ngữ nghĩa thực thi shell
- thay đổi ủy quyền công cụ hiện có
- script do người dùng tạo được lưu bền vững
- quyền truy cập package manager, file, mạng, hoặc module trong mã khách
- tái sử dụng trực tiếp nội bộ của Codex Code mode
Các công cụ do nhà cung cấp sở hữu như sandbox Python từ xa vẫn là các công cụ riêng. Xem Thực thi mã.
Thuật ngữ
Chế độ mã là chế độ runtime OpenClaw ẩn các công cụ mô hình thông thường và
chỉ hiển thị exec và wait.
Runtime khách là VM JavaScript QuickJS-WASI đánh giá mã mô hình.
Cầu nối host là bề mặt callback tương thích JSON hẹp từ mã khách quay lại OpenClaw.
Danh mục là danh sách công cụ hiệu dụng theo phạm vi lần chạy sau chính sách công cụ thông thường, Plugin, MCP, và phân giải công cụ client.
Lệnh gọi công cụ lồng nhau là một lệnh gọi công cụ được thực hiện từ mã khách thông qua cầu nối host.
Snapshot là trạng thái VM QuickJS-WASI đã tuần tự hóa được lưu để wait có thể tiếp tục một
lần chạy chế độ mã đã tạm dừng.
Cấu hình
tools.codeMode.enabled là cổng kích hoạt. Việc đặt các trường chế độ mã khác
không bật tính năng.
Các trường được hỗ trợ:
enabled: boolean. Mặc địnhfalse. Chỉ bật chế độ mã khi làtrue.runtime:"quickjs-wasi". Runtime duy nhất được hỗ trợ.mode:"only". Hiển thịexecvàwait, ẩn các công cụ mô hình thông thường.languages: mảng gồm"javascript"và"typescript". Mặc định bao gồm cả hai.timeoutMs: giới hạn thời gian đồng hồ cho mộtexechoặcwait. Mặc định10000. Kẹp runtime:100đến60000.memoryLimitBytes: giới hạn heap QuickJS. Mặc định67108864. Kẹp runtime:1048576đến1073741824.maxOutputBytes: giới hạn cho văn bản, JSON, và log trả về. Mặc định65536. Kẹp runtime:1024đến10485760.maxSnapshotBytes: giới hạn cho snapshot VM đã tuần tự hóa. Mặc định10485760. Kẹp runtime:1024đến268435456.maxPendingToolCalls: giới hạn cho các lệnh gọi công cụ lồng nhau đồng thời. Mặc định16. Kẹp runtime:1đến128.snapshotTtlSeconds: thời gian một VM bị tạm dừng có thể được tiếp tục. Mặc định900. Kẹp runtime:1đến86400.searchDefaultLimit: số lượng kết quả tìm kiếm danh mục ẩn mặc định. Mặc định8. Runtime kẹp giá trị này theomaxSearchLimit.maxSearchLimit: số lượng kết quả tìm kiếm danh mục ẩn tối đa. Mặc định50. Kẹp runtime:1đến50.
Nếu chế độ mã được bật nhưng QuickJS-WASI không thể tải, OpenClaw thất bại đóng cho lần chạy đó. Nó không âm thầm hiển thị công cụ thông thường làm fallback.
Kích hoạt
Chế độ mã được đánh giá sau khi chính sách công cụ hiệu dụng đã biết và trước khi yêu cầu mô hình cuối cùng được lắp ráp.
Thứ tự kích hoạt:
- Phân giải agent, mô hình, nhà cung cấp, sandbox, kênh, người gửi, và chính sách lần chạy.
- Xây dựng danh sách công cụ OpenClaw hiệu dụng.
- Thêm các công cụ Plugin, MCP, và client đủ điều kiện.
- Áp dụng chính sách cho phép và từ chối.
- Nếu
tools.codeMode.enabledlà false, tiếp tục với hiển thị công cụ thông thường. - Nếu đã bật và công cụ đang hoạt động cho lần chạy, đăng ký các công cụ hiệu dụng trong danh mục chế độ mã.
- Xóa mọi công cụ thông thường khỏi danh sách công cụ mà mô hình thấy.
- Thêm
execvàwaitcủa chế độ mã.
Các lần chạy cố ý không có công cụ, như lệnh gọi mô hình thô, disableTools,
hoặc allowlist rỗng, không kích hoạt bề mặt chế độ mã ngay cả khi cấu hình
chứa tools.codeMode.enabled: true.
Danh mục chế độ mã có phạm vi theo lần chạy. Nó không được rò rỉ công cụ từ agent, phiên, người gửi, hoặc lần chạy khác.
Công cụ mà mô hình thấy
Khi chế độ mã đang hoạt động, mô hình thấy chính xác các công cụ cấp cao nhất này:
execwait
Mọi công cụ đã bật khác được ẩn khỏi danh sách công cụ hướng tới mô hình và được đăng ký trong danh mục chế độ mã.
Mô hình nên dùng exec để điều phối công cụ, nối dữ liệu, vòng lặp,
các lệnh gọi lồng nhau song song, và các biến đổi có cấu trúc. Mô hình chỉ nên dùng
wait khi exec trả về kết quả waiting có thể tiếp tục.
exec
exec khởi động một ô chế độ mã và trả về một kết quả. Mã đầu vào do mô hình
tạo và phải được xem là thù địch.
Đầu vào:
type CodeModeExecInput = { code?: string; command?: string; language?: "javascript" | "typescript";};Quy tắc đầu vào:
- Một trong
codehoặccommandphải không rỗng. codelà trường hướng tới mô hình được ghi trong tài liệu.commandđược chấp nhận như một bí danh tương thích exec cho chính sách hook và các lần viết lại đáng tin cậy; khi cả hai có mặt, các giá trị phải khớp.- Sự kiện hook
execchế độ mã bên ngoài bao gồmtoolKind: "code_mode_exec"và bao gồmtoolInputKind: "javascript" | "typescript"khi ngôn ngữ đầu vào được biết, để chính sách có thể phân biệt ô chế độ mã với các lệnh gọiexeckiểu shell có cùng tên công cụ. languagemặc định là"javascript".- Nếu
languagelà"typescript", OpenClaw chuyển dịch trước khi đánh giá. exectừ chốiimport,require, import động, và các mẫu module-loader trong v1.execkhông hiển thị đệ quy triển khaiexecshell thông thường.
Kết quả:
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 trả về waiting khi VM QuickJS tạm dừng với trạng thái có thể tiếp tục mà
vẫn cần một bước tiếp tục hiển thị với mô hình. Kết quả bao gồm runId cho
wait. Các lệnh gọi cầu nối namespace, bao gồm lệnh gọi namespace MCP, được tự động xả
bên trong cùng lệnh gọi exec/wait khi chúng sẵn sàng, vì vậy một khối mã gọn
có thể kiểm tra $api() và gọi một công cụ MCP mà không buộc phải có một lệnh gọi công cụ mô hình cho mỗi
lần await namespace.
exec chỉ trả về completed khi VM khách không còn công việc đang chờ xử lý và
giá trị cuối cùng tương thích JSON sau khi bộ điều hợp đầu ra của OpenClaw chạy.
wait
wait tiếp tục một VM chế độ mã đang bị tạm dừng.
Đầu vào:
type CodeModeWaitInput = { runId: string;};Đầu ra là cùng hợp CodeModeResult mà exec trả về.
wait tồn tại vì các công cụ OpenClaw lồng nhau có thể chậm, tương tác, bị chặn
bởi phê duyệt, hoặc phát trực tuyến các cập nhật từng phần. Mô hình không cần
giữ một lệnh gọi exec dài đang mở trong khi máy chủ chờ công việc bên ngoài.
Ảnh chụp và khôi phục QuickJS-WASI là cơ chế tiếp tục v1:
execđánh giá mã cho đến khi hoàn tất, thất bại, hoặc tạm dừng.- Khi tạm dừng, OpenClaw chụp ảnh VM QuickJS và ghi lại công việc máy chủ đang chờ xử lý.
- Khi công việc đang chờ ổn định,
waitkhôi phục ảnh chụp VM. - OpenClaw đăng ký lại các callback máy chủ bằng tên ổn định.
- OpenClaw chuyển kết quả công cụ lồng nhau vào VM đã khôi phục.
- OpenClaw xả các tác vụ QuickJS đang chờ.
waittrả về kết quảcompleted,failed, hoặc một kết quảwaitingkhác.
Ảnh chụp là trạng thái runtime, không phải tạo tác người dùng. Chúng bị giới hạn kích thước, hết hạn, và được giới hạn trong lượt chạy và phiên đã tạo ra chúng.
wait thất bại khi:
runIdkhông xác định.- ảnh chụp đã hết hạn.
- lượt chạy cha hoặc phiên đã bị hủy.
- bên gọi không ở trong cùng phạm vi lượt chạy/phiên.
- khôi phục QuickJS-WASI thất bại.
- việc khôi phục sẽ vượt quá các giới hạn đã cấu hình.
API runtime khách
Runtime khách cung cấp một API toàn cục nhỏ:
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 là siêu dữ liệu gọn cho danh mục trong phạm vi lượt chạy. Theo mặc
định, nó không chứa đầy đủ schema.
type ToolCatalogEntry = { id: string; name: string; label?: string; description: string; source: "openclaw" | "plugin" | "mcp" | "client"; sourceName?: string;};Schema đầy đủ chỉ được tải theo nhu cầu:
type ToolCatalogEntryWithSchema = ToolCatalogEntry & { parameters: unknown;};Các helper danh mục:
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;};Các hàm công cụ tiện dụng chỉ được cài đặt cho các tên an toàn, không mơ hồ:
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" });Các mục danh mục MCP không thể được gọi qua tools.call(...) hoặc các hàm tiện
dụng trong chế độ mã. Chúng chỉ được cung cấp qua namespace MCP được tạo ra.
Các tệp khai báo kiểu TypeScript có sẵn qua bề mặt tệp ảo chỉ đọc API, để các
agent có thể kiểm tra chữ ký MCP mà không thêm schema MCP vào prompt:
const files = await API.list("mcp");const githubApi = await API.read("mcp/github.d.ts"); const issue = await MCP.github.createIssue({ owner: "openclaw", repo: "openclaw", title: "Investigate gateway logs",}); const snapshot = await MCP.chromeDevtools.takeSnapshot({ output: "markdown" });const resource = await MCP.docs.resources.read({ uri: "memo://one" });const prompt = await MCP.docs.prompts.get({ name: "brief", arguments: { topic: "release" },});API.read("mcp/<server>.d.ts") trả về các khai báo gọn được suy luận từ siêu dữ
liệu công cụ 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>;}Các tệp khai báo là ảo, không phải tệp được ghi dưới workspace hoặc thư mục
trạng thái. Với mỗi lệnh gọi exec ở chế độ mã, OpenClaw xây dựng danh mục công
cụ trong phạm vi lượt chạy, giữ các mục MCP hiển thị, render mcp/index.d.ts
cộng với một khai báo mcp/<server>.d.ts cho mỗi máy chủ hiển thị, rồi tiêm bảng
nhỏ chỉ đọc đó vào worker QuickJS. Mã khách chỉ thấy đối tượng API:
API.list(prefix?) trả về siêu dữ liệu tệp và API.read(path) trả về nội dung
khai báo đã chọn. Các đường dẫn không xác định và các đoạn . / .. bị từ chối.
Điều này giữ các schema MCP lớn nằm ngoài prompt của mô hình. Agent biết rằng API
ảo tồn tại từ mô tả công cụ exec, chỉ đọc tệp khai báo cần thiết, rồi gọi
MCP.<server>.<tool>() với một đối số đối tượng. MCP.<server>.$api() vẫn có
sẵn như một phương án dự phòng nội tuyến khi agent cần phản hồi schema cho một
công cụ duy nhất bên trong chương trình.
Runtime khách không được để lộ trực tiếp các đối tượng máy chủ. Đầu vào và đầu ra đi qua cầu nối dưới dạng các giá trị tương thích JSON với giới hạn kích thước rõ ràng.
Namespace nội bộ
Namespace nội bộ cung cấp cho chế độ mã một API miền ngắn gọn mà không thêm nhiều
công cụ hiển thị với mô hình hơn. Một tích hợp do loader sở hữu có thể đăng ký
một namespace như Issues, Fictions, hoặc Calendar; mã khách sau đó gọi
namespace đó bên trong chương trình QuickJS trong khi OpenClaw vẫn chỉ hiển thị
exec và wait cho mô hình.
Hiện tại namespace là nội bộ. Không có API namespace SDK Plugin công khai: namespace của Plugin bên ngoài cần một hợp đồng do loader sở hữu để danh tính Plugin, manifest đã cài đặt, trạng thái xác thực, và bộ mô tả danh mục đã lưu đệm không bị lệch khỏi các công cụ Plugin hỗ trợ namespace. Chế độ mã lõi chỉ sở hữu sandbox, tuần tự hóa, kiểm soát danh mục, và điều phối cầu nối.
Mã khách sau đó có thể dùng trực tiếp global hoặc bản đồ namespaces:
const open = await Issues.list({ state: "open" });const alsoOpen = await namespaces.Issues.list({ state: "open" });return { count: open.length, alsoCount: alsoOpen.length };Vòng đời registry
Registry namespace là cục bộ theo tiến trình và được khóa theo id namespace. Một lượt chạy điển hình theo đường dẫn này:
- Một loader đáng tin cậy gọi
registerCodeModeNamespaceForPlugin(pluginId, registration). - Chế độ mã tạo
ToolSearchRuntimeẩn cho lượt chạy và đọc danh mục trong phạm vi lượt chạy của nó. createCodeModeNamespaceRuntime(ctx, catalog)chỉ giữ các đăng ký có toàn bộrequiredToolNameshiển thị và do cùngpluginIdsở hữu.- Mỗi namespace hiển thị gọi
createScope(ctx)cho lượt chạy hiện tại. Phạm vi nhận ngữ cảnh lượt chạy nhưagentId,sessionKey,sessionId,runId, cấu hình, và trạng thái hủy. - Dữ liệu phạm vi được tuần tự hóa thành một bộ mô tả thuần và được tiêm vào
QuickJS dưới dạng global trực tiếp và
namespaces.<globalName>. - Các lệnh gọi của khách tạm dừng qua cầu nối worker, phân giải đường dẫn
namespace trên máy chủ, ánh xạ lệnh gọi tới một công cụ danh mục đã khai báo
do Plugin sở hữu, và thực thi công cụ đó qua
ToolSearchRuntime.call. - OpenClaw tự động xả các lệnh gọi cầu nối namespace đã sẵn sàng bên trong lệnh
gọi công cụ
exec/waitđang hoạt động. Nếu công việc namespace vẫn đang chờ khi hết thời gian chờ hoặc khách chủ động nhường quyền,waittiếp tục cùng runtime namespace sau đó. - Rollback hoặc gỡ cài đặt Plugin gọi
clearCodeModeNamespacesForPlugin(pluginId)để các global cũ không tồn tại sau khi tải Plugin thất bại.
Bất biến quan trọng: lệnh gọi namespace là lệnh gọi công cụ danh mục. Chúng dùng
cùng các hook chính sách, phê duyệt, xử lý hủy, telemetry, chiếu bản ghi, và hành
vi tạm dừng/tiếp tục như tools.call(...).
Hình dạng đăng ký
Đăng ký namespace từ tích hợp sở hữu các công cụ nền. Giữ phạm vi nhỏ và chỉ để lộ các động từ miền ánh xạ tới các công cụ danh mục đã khai báo.
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) đánh dấu một thành viên phạm
vi là hàm namespace có thể gọi. inputMapper tùy chọn nhận các đối số từ khách
và trả về đối tượng đầu vào cho công cụ danh mục nền. Khi không có bộ ánh xạ đầu
vào, đối số đầu tiên của khách được dùng, hoặc {} khi bị bỏ qua.
Các hàm máy chủ thô bị từ chối trước khi mã khách chạy:
createScope: () => ({ // Wrong: this bypasses the catalog tool lifecycle and will be rejected. list: async () => githubClient.listIssues(),});Quyền sở hữu và khả năng hiển thị
Quyền sở hữu namespace gắn với pluginId của bên gọi đăng ký.
requiredToolNames vừa là cổng hiển thị vừa là kiểm tra quyền sở hữu:
- mọi công cụ bắt buộc phải tồn tại trong danh mục lượt chạy
- mọi công cụ bắt buộc phải có
sourceName === pluginId - namespace bị ẩn khi bất kỳ công cụ bắt buộc nào vắng mặt hoặc do Plugin khác sở hữu
- mỗi đường dẫn có thể gọi chỉ được nhắm đến một công cụ có tên trong
requiredToolNames
Điều này ngăn Plugin khác để lộ một namespace bằng cách đăng ký một công cụ cùng tên. Nó cũng giữ namespace nhất quán với chính sách agent thông thường: nếu lượt chạy không thấy các công cụ nền, nó không thấy namespace.
Ví dụ, một namespace GitHub nên nằm sau một phần mở rộng do GitHub sở hữu, quản lý xác thực GitHub, client REST hoặc GraphQL, giới hạn tốc độ, phê duyệt ghi, và kiểm thử. Chế độ mã lõi không nên nhúng API đặc thù GitHub, xử lý token, hoặc chính sách provider.
Quy tắc tuần tự hóa phạm vi
createScope(ctx) có thể trả về một đối tượng thuần chứa các giá trị tương thích
JSON, mảng, đối tượng lồng nhau, và các dấu lệnh gọi
createCodeModeNamespaceTool(...). Đối tượng máy chủ không bao giờ đi trực tiếp
vào QuickJS.
Bộ tuần tự hóa từ chối:
- hàm thô
- đồ thị đối tượng vòng
- đoạn đường dẫn không an toàn:
__proto__,constructor,prototype, khóa rỗng, hoặc khóa chứa dấu phân tách đường dẫn nội bộ - giá trị
globalNamekhông phải là định danh JavaScript - xung đột
globalNamevới các global chế độ mã tích hợp sẵn nhưtools,namespaces,text,json,yield_control, hoặc__openclaw*
Các giá trị không thể tuần tự hóa JSON được chuyển thành giá trị dự phòng an toàn JSON trước khi đi qua cầu nối. Dữ liệu nhị phân, handle, socket, client, và thể hiện lớp nên ở sau các công cụ danh mục thông thường.
Prompt
description của namespace và prompt tùy chọn được nối vào schema exec hiển
thị với mô hình chỉ khi namespace hiển thị cho lượt chạy đó. Dùng chúng để dạy bề
mặt hữu ích nhỏ nhất:
{ description: "Fiction production service helpers.", prompt: "Use Fictions.riskAudit(), Fictions.promoteIfReady(id, status), and Fictions.unpaidOver(amount).",}Giữ prompt xoay quanh hợp đồng namespace, không phải thiết lập xác thực, lịch sử triển khai, hoặc hành vi Plugin không liên quan.
Dọn dẹp
Namespace là các đăng ký cục bộ theo tiến trình. Hãy xóa chúng khi plugin sở hữu bị tắt, gỡ cài đặt hoặc rollback:
clearCodeModeNamespacesForPlugin(pluginId);Việc dọn dẹp code-mode thuộc sở hữu của plugin; hãy xóa các đăng ký namespace của plugin
khi vòng đời của nó kết thúc thay vì giữ các handle teardown theo từng namespace. Các bài kiểm thử
có thể gọi clearCodeModeNamespacesForTest() để tránh rò rỉ đăng ký
giữa các trường hợp.
Danh sách kiểm thử
Các thay đổi namespace nên bao phủ ranh giới bảo mật và hành vi của guest:
- văn bản prompt namespace chỉ xuất hiện khi các công cụ hỗ trợ hiển thị
- các công cụ trùng tên từ một
sourceNamekhác không để lộ namespace - các hàm scope thô bị từ chối
- id namespace giả mạo và đường dẫn giả mạo bị từ chối
- các đường dẫn có thể gọi không thể nhắm tới công cụ chưa khai báo
- các đối tượng lồng nhau và tham chiếu dùng chung được tuần tự hóa đúng cách
- các lệnh gọi namespace thực thi thông qua công cụ catalog và trả về chi tiết an toàn với JSON
- lỗi có thể được mã guest bắt
- các lệnh gọi namespace bị tạm dừng tiếp tục thông qua
wait - rollback plugin xóa các đăng ký namespace thuộc sở hữu đó
Namespace bổ sung cho catalog tools.search / tools.call chung. Dùng
catalog cho các công cụ OpenClaw, plugin và client tùy ý đã bật; dùng MCP cho
các công cụ MCP; dùng các namespace khác cho API miền được tài liệu hóa, thuộc sở hữu plugin, nơi
mã ngắn gọn đáng tin cậy hơn việc tra cứu schema lặp lại.
API đầu ra
text(value) thêm đầu ra mà con người có thể đọc vào mảng output.
json(value) thêm một mục đầu ra có cấu trúc sau khi tuần tự hóa tương thích JSON.
Giá trị trả về cuối cùng của mã guest trở thành value trong kết quả completed.
Mục đầu ra:
type CodeModeOutput = { type: "text"; text: string } | { type: "json"; value: unknown };Quy tắc đầu ra:
- thứ tự đầu ra khớp với các lệnh gọi của guest
- đầu ra bị giới hạn bởi
maxOutputBytes - các giá trị không thể tuần tự hóa được chuyển thành chuỗi thuần hoặc lỗi
- giá trị nhị phân không được hỗ trợ trong v1
- hình ảnh và tệp đi qua các công cụ OpenClaw thông thường, không đi qua cầu nối code-mode
Catalog công cụ
Catalog ẩn bao gồm các công cụ sau khi lọc chính sách hiệu lực:
- Công cụ lõi OpenClaw.
- Công cụ plugin được đóng gói kèm.
- Công cụ plugin bên ngoài.
- Công cụ MCP.
- Công cụ do client cung cấp cho lần chạy hiện tại.
Id catalog ổn định trong một lần chạy và có tính xác định trên các tập công cụ tương đương khi có thể.
Dạng id được khuyến nghị:
<source>:<owner>:<tool-name>Ví dụ:
openclaw:core:messageplugin:browser:browser_requestmcp:github:create_issueclient:app:select_fileCatalog bỏ qua các công cụ điều khiển code-mode:
execwaittool_search_codetool_searchtool_describetool_call
Điều này ngăn đệ quy và giữ hợp đồng hướng tới model gọn hẹp.
Các mục MCP vẫn nằm trong catalog theo phạm vi lần chạy để chính sách, phê duyệt, hook,
telemetry, phép chiếu transcript và id công cụ chính xác vẫn được chia sẻ với quá trình
thực thi công cụ bình thường. Các chế độ xem dành cho guest ALL_TOOLS, tools.search(...),
tools.describe(...) và tools.call(...) bỏ qua các mục MCP. Namespace
MCP.<server>.<tool>({ ...input }) được tạo sẽ phân giải trở lại
đúng id catalog rồi điều phối qua cùng đường dẫn executor.
Tương tác Tool Search
Code mode thay thế bề mặt model Tool Search của OpenClaw cho các lần chạy mà nó đang hoạt động.
Khi tools.codeMode.enabled là true và code mode kích hoạt:
- OpenClaw không để lộ
tool_search_code,tool_search,tool_describe, hoặctool_callnhư các công cụ hiển thị với model. - Cùng ý tưởng cataloging chuyển vào bên trong runtime guest.
- Runtime guest nhận metadata
ALL_TOOLSnhỏ gọn và các helper search, describe, và call cho các công cụ không phải MCP. - Các lệnh gọi MCP dùng namespace
MCPđược tạo và header$api()của nó thay vìtools.call(...). - Các lệnh gọi lồng nhau điều phối qua cùng đường dẫn executor OpenClaw mà Tool Search sử dụng.
Trang Tool Search hiện có mô tả cầu nối catalog nhỏ gọn của OpenClaw.
Code mode là lựa chọn thay thế OpenClaw chung cho các lần chạy có thể
dùng exec và wait.
Tên công cụ và xung đột
Công cụ exec hiển thị với model là công cụ code-mode. Nếu công cụ shell exec
bình thường của OpenClaw được bật, nó bị ẩn khỏi model và được đưa vào catalog như bất kỳ
công cụ nào khác.
Bên trong runtime guest:
tools.call("openclaw:core:exec", input)có thể gọi công cụ shell exec nếu chính sách cho phép.tools.exec(...)chỉ được cài đặt nếu mục catalog shell exec có tên an toàn không mơ hồ.- công cụ code-mode
execkhông bao giờ có sẵn đệ quy thông quatools.
Nếu hai công cụ chuẩn hóa thành cùng một tên tiện ích an toàn, OpenClaw bỏ qua
hàm tiện ích và yêu cầu tools.call(id, input).
Thực thi công cụ lồng nhau
Mỗi lệnh gọi công cụ lồng nhau đi qua cầu nối host và vào lại OpenClaw.
Thực thi lồng nhau giữ nguyên:
- id agent đang hoạt động
- id phiên và khóa phiên
- ngữ cảnh người gửi và kênh
- chính sách sandbox
- chính sách phê duyệt
- hook
before_tool_callcủa plugin - tín hiệu abort
- cập nhật streaming khi có
- sự kiện trajectory và audit
Các lệnh gọi lồng nhau được chiếu vào transcript như lệnh gọi công cụ thật để các gói hỗ trợ có thể hiển thị điều đã xảy ra. Phép chiếu xác định lệnh gọi công cụ code-mode cha và id công cụ lồng nhau.
Các lệnh gọi lồng nhau song song được cho phép tới maxPendingToolCalls.
Trạng thái runtime
Mỗi lần chạy code-mode có một máy trạng thái:
running: VM đang thực thi hoặc các lệnh gọi lồng nhau đang diễn ra.waiting: snapshot VM tồn tại và có thể tiếp tục bằngwait.completed: giá trị cuối cùng đã trả về; snapshot đã xóa.failed: lỗi đã trả về; snapshot đã xóa.expired: snapshot hoặc trạng thái pending vượt quá thời gian lưu giữ; không thể tiếp tục.aborted: lần chạy/phiên cha đã hủy; snapshot đã xóa.
Trạng thái được giới hạn theo lần chạy agent, phiên và id lệnh gọi công cụ. Một lệnh gọi wait từ
lần chạy hoặc phiên khác sẽ thất bại.
Lưu trữ snapshot có giới hạn:
- số byte snapshot tối đa cho mỗi lần chạy
- số snapshot live tối đa cho mỗi tiến trình
- TTL snapshot
- dọn dẹp khi kết thúc lần chạy
- dọn dẹp khi Gateway tắt ở nơi không hỗ trợ persistence
Runtime QuickJS-WASI
OpenClaw tải quickjs-wasi như một dependency trực tiếp trong package sở hữu. Runtime
không dựa vào một bản sao bắc cầu được cài đặt cho proxy, PAC hoặc các dependency
không liên quan khác.
Trách nhiệm của runtime:
- biên dịch hoặc tải module WebAssembly QuickJS-WASI
- tạo một VM cô lập cho mỗi lần chạy hoặc tiếp tục code-mode
- đăng ký callback host bằng tên ổn định
- đặt giới hạn bộ nhớ và interrupt
- đánh giá JavaScript
- rút cạn các job đang chờ
- snapshot trạng thái VM bị tạm dừng
- khôi phục snapshot cho
wait - dispose các handle VM và snapshot sau các trạng thái kết thúc
Runtime thực thi bên ngoài vòng lặp sự kiện chính của OpenClaw trong một worker. Một vòng lặp vô hạn của guest không được chặn tiến trình Gateway vô thời hạn.
TypeScript
Hỗ trợ TypeScript chỉ là một phép biến đổi nguồn:
- đầu vào được chấp nhận: một chuỗi mã TypeScript
- đầu ra: chuỗi JavaScript được QuickJS-WASI đánh giá
- không typechecking
- không phân giải module
- không
importhoặcrequiretrong v1 - diagnostics được trả về dưới dạng kết quả
failed
Trình biên dịch TypeScript được tải lười chỉ cho các ô TypeScript. Các ô JavaScript thuần và code mode bị tắt không tải trình biên dịch.
Phép biến đổi nên giữ lại số dòng hữu ích khi khả thi.
Ranh giới bảo mật
Mã model là thù địch. Runtime dùng phòng thủ nhiều lớp:
- chạy QuickJS-WASI bên ngoài vòng lặp sự kiện chính
- tải
quickjs-wasinhư một dependency trực tiếp, không thông qua Codex hoặc package bắc cầu - không có hệ thống tệp, mạng, subprocess, import module, biến môi trường hoặc đối tượng global host trong guest
- dùng giới hạn bộ nhớ và interrupt của QuickJS
- thực thi timeout wall-clock của tiến trình cha
- thực thi giới hạn đầu ra, snapshot, log và lệnh gọi pending
- tuần tự hóa giá trị cầu nối host qua adapter JSON hẹp
- chuyển lỗi host thành lỗi guest thuần, không bao giờ là đối tượng realm host
- bỏ snapshot khi timeout, abort, kết thúc phiên hoặc hết hạn
- từ chối truy cập đệ quy tới
exec,waitvà các công cụ điều khiển Tool Search - ngăn xung đột tên tiện ích che khuất helper catalog
Sandbox là một lớp bảo mật. Operator vẫn có thể cần gia cố cấp OS cho các triển khai rủi ro cao.
Mã lỗi
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";Lỗi trả về cho guest là dữ liệu thuần. Các instance Error của host, đối tượng stack,
prototype và hàm host không đi vào QuickJS.
Telemetry
Code mode báo cáo:
- tên công cụ hiển thị được gửi tới model
- kích thước catalog ẩn và phân tách theo nguồn
- số lượng
execvàwait - số lượng search, describe và call lồng nhau
- id công cụ lồng nhau đã gọi
- lỗi timeout, bộ nhớ, snapshot và giới hạn đầu ra
- sự kiện vòng đời snapshot
Telemetry không được bao gồm secrets, giá trị môi trường thô hoặc đầu vào công cụ chưa redact vượt ngoài chính sách trajectory hiện có của OpenClaw.
Gỡ lỗi
Dùng logging truyền tải model có mục tiêu khi code mode hoạt động khác với một lần chạy công cụ bình thường:
OPENCLAW_DEBUG_CODE_MODE=1 \OPENCLAW_DEBUG_MODEL_TRANSPORT=1 \OPENCLAW_DEBUG_MODEL_PAYLOAD=tools \OPENCLAW_DEBUG_SSE=events \openclaw gatewayĐể gỡ lỗi hình dạng payload, dùng OPENCLAW_DEBUG_MODEL_PAYLOAD=full-redacted.
Điều này ghi log một snapshot JSON bị redact, có giới hạn của yêu cầu model; chỉ nên
dùng trong khi gỡ lỗi vì prompt và văn bản tin nhắn vẫn có thể xuất hiện.
Để gỡ lỗi stream, dùng OPENCLAW_DEBUG_SSE=peek để ghi log năm sự kiện SSE đầu tiên
đã redact. Code mode cũng fail closed nếu payload provider cuối cùng
không chứa đúng exec và wait sau khi bề mặt code-mode đã
kích hoạt.
Bố cục triển khai
Các đơn vị triển khai:
- hợp đồng cấu hình:
tools.codeMode - trình dựng catalog: công cụ hiệu lực thành mục nhỏ gọn và map id
- adapter bề mặt model: thay thế công cụ hiển thị bằng
execvàwait - adapter runtime QuickJS-WASI: load, eval, snapshot, restore, dispose
- supervisor worker: timeout, abort, cô lập crash
- adapter cầu nối: callback host an toàn với JSON và phân phối kết quả
- adapter biến đổi TypeScript
- kho snapshot: TTL, giới hạn kích thước, phạm vi lần chạy/phiên
- phép chiếu trajectory cho lệnh gọi công cụ lồng nhau
- bộ đếm telemetry và diagnostics
Triển khai tái sử dụng các khái niệm catalog và executor từ Tool Search, nhưng
không dùng child node:vm làm sandbox.
Danh sách kiểm chứng
Phạm vi code mode nên chứng minh:
- cấu hình bị tắt giữ nguyên việc hiển thị công cụ hiện có
- cấu hình dạng đối tượng không có
enabled: truegiữ chế độ code ở trạng thái tắt - cấu hình được bật chỉ hiển thị
execvàwaitcho mô hình khi các công cụ đang hoạt động cho lần chạy - các lần chạy thô không dùng công cụ,
disableTools, và danh sách cho phép rỗng không kích hoạt việc thực thi payload chế độ code - tất cả công cụ không phải MCP có hiệu lực đều xuất hiện trong
ALL_TOOLS - các công cụ bị từ chối không xuất hiện trong
ALL_TOOLS tools.search,tools.describe, vàtools.callhoạt động với các công cụ OpenClawAPI.list("mcp")vàAPI.read("mcp/<server>.d.ts")hiển thị các khai báo MCP kiểu TypeScript mà không cần bridge/lệnh gọi công cụ- không gian tên MCP
$api()vẫn khả dụng như một phương án dự phòng nội tuyến cho schema - các lệnh gọi không gian tên MCP hoạt động với công cụ MCP hiển thị có một đầu vào đối tượng, trong khi
các mục danh mục MCP trực tiếp không có trong
tools.* - các công cụ điều khiển Tìm kiếm công cụ bị ẩn khỏi cả bề mặt mô hình và danh mục ẩn
- các lệnh gọi lồng nhau giữ nguyên hành vi phê duyệt và hook
- shell
execbị ẩn khỏi mô hình nhưng có thể gọi bằng id danh mục khi được cho phép execvàwaitchế độ code đệ quy không thể được gọi từ code khách- đầu vào TypeScript được chuyển đổi và đánh giá mà không tải TypeScript trên các đường dẫn bị tắt hoặc chỉ dùng JavaScript
import,require, quyền truy cập hệ thống tệp, mạng và môi trường đều thất bại- vòng lặp vô hạn hết thời gian chờ và không thể chặn Gateway
- lỗi giới hạn bộ nhớ sẽ chấm dứt VM khách
- giới hạn đầu ra và snapshot được thực thi cho các lệnh gọi đã hoàn tất và bị tạm dừng
waittiếp tục một snapshot bị tạm dừng và trả về giá trị cuối cùng- các giá trị
runIdhết hạn, bị hủy, sai phiên và không xác định đều thất bại - phát lại transcript và lưu bền vững giữ nguyên các lệnh gọi điều khiển chế độ code
- transcript và telemetry hiển thị rõ ràng các lệnh gọi công cụ lồng nhau
Kế hoạch kiểm thử E2E
Chạy các kiểm thử này dưới dạng kiểm thử tích hợp hoặc đầu cuối khi thay đổi runtime:
- Khởi động Gateway với
tools.codeMode.enabled: false. - Gửi một lượt agent với một tập công cụ trực tiếp nhỏ.
- Xác nhận các công cụ hiển thị với mô hình không thay đổi.
- Khởi động lại với
tools.codeMode.enabled: true. - Gửi một lượt agent với các công cụ kiểm thử OpenClaw, Plugin, MCP và client.
- Xác nhận danh sách công cụ hiển thị với mô hình chính xác là
exec,wait. - Trong
exec, đọcALL_TOOLSvà xác nhận các công cụ kiểm thử có hiệu lực có mặt. - Trong
exec, gọi các công cụ OpenClaw/Plugin/client thông quatools.search,tools.describe, vàtools.call. - Trong
exec, gọiAPI.list("mcp")vàAPI.read("mcp/<server>.d.ts")và xác nhận các tệp khai báo mô tả các công cụ MCP hiển thị. - Trong
exec, gọi các công cụ MCP thông quaMCP.<server>.<tool>({ ...input })và xác nhận các mục danh mục MCP trực tiếp không có trongALL_TOOLSvàtools.*. - Xác nhận các công cụ bị từ chối không có mặt và không thể được gọi bằng id đoán trước.
- Bắt đầu một lệnh gọi công cụ lồng nhau phân giải sau khi
exectrả vềwaiting. - Gọi
waitvà xác nhận VM đã khôi phục nhận được kết quả công cụ. - Xác nhận câu trả lời cuối cùng chứa đầu ra được tạo sau khi khôi phục.
- Xác nhận hết thời gian chờ, hủy bỏ và hết hạn snapshot dọn dẹp trạng thái runtime.
- Xuất trajectory và xác nhận các lệnh gọi lồng nhau hiển thị dưới lệnh gọi chế độ code cha.
Các thay đổi chỉ liên quan đến tài liệu trên trang này vẫn nên chạy pnpm check:docs.