exec와 wait만 봅니다.
이 페이지는 OpenClaw 코드 모드를 문서화합니다. Codex Code mode가 아닙니다.
두 기능은 이름을 공유하지만 서로 다른 런타임으로 구현되며 서로 다른
exec 계약을 노출합니다.
- Codex Code Mode는 제한적인 도구 정책이 네이티브 코드 모드를 비활성화하지
않는 한 Codex 앱 서버 스레드에서 활성화됩니다. 이는 Codex 코딩 하네스에서
실행되며, 모델은
exec.command계약을 통해 셸 명령을 작성합니다. - OpenClaw 코드 모드는
tools.codeMode.enabled: true가 구성되지 않는 한 비활성화됩니다. 이는 OpenClaw 범용 에이전트 런타임에서 실행되며, 모델은exec.code계약을 통해 JavaScript 또는 TypeScript 프로그램을 작성합니다.
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 정책, 승인, 훅, 세션 컨텍스트, 감사 경로를 거칩니다.
- 명확한 실패 모드: 코드 모드가 명시적으로 활성화되었지만 런타임을 사용할 수 없으면 OpenClaw는 광범위한 직접 도구 노출로 폴백하는 대신 닫힌 상태로 실패합니다.
활성화 방법
에이전트 또는 런타임 구성에tools.codeMode.enabled: true를 추가합니다.
tools.codeMode가 생략되었거나, false이거나, enabled: true가 없는 객체인
경우 코드 모드는 계속 꺼져 있습니다.
구성된 MCP 서버가 있는 샌드박스 에이전트를 사용할 때는 샌드박스 도구 정책이
번들 MCP Plugin도 허용하는지 확인하세요. 예를 들면
tools.sandbox.tools.alsoAllow: ["bundle-mcp"]를 사용할 수 있습니다.
구성 - 도구 및 사용자 지정 공급자를
참조하세요.
더 엄격한 경계가 필요하면 명시적인 제한을 사용하세요.
exec와
wait이어야 합니다. 수정된 공급자 페이로드가 필요하면 짧은 디버깅 세션 동안
OPENCLAW_DEBUG_MODEL_PAYLOAD=full-redacted를 추가하세요.
기술 둘러보기
이 페이지의 나머지 부분은 런타임 계약과 구현 세부 정보를 설명합니다. 유지관리자, 도구 노출을 디버깅하는 Plugin 작성자, 고위험 배포를 검증하는 운영자를 대상으로 합니다.런타임 상태
- 런타임:
quickjs-wasi. - 기본 상태: 비활성화됨.
- 안정성: 실험적인 OpenClaw 표면입니다. Codex Code mode는 별도의 안정적인 Codex 하네스 표면입니다.
- 대상 표면: 범용 OpenClaw 에이전트 실행.
- 보안 태세: 모델 코드는 적대적입니다.
- 사용자 대상 약속: 코드 모드를 활성화해도 광범위한 직접 도구 노출로 조용히 폴백하지 않습니다.
범위
코드 모드는 준비된 실행의 모델 대상 오케스트레이션 형태를 소유합니다. 모델 선택, 채널 동작, 인증, 도구 정책 또는 도구 구현은 소유하지 않습니다. 범위에 포함:- 모델에 표시되는
exec및wait도구 정의 - 숨겨진 도구 카탈로그 구성
- JavaScript 및 TypeScript 게스트 실행
- QuickJS-WASI 워커 런타임
- 카탈로그 검색, 스키마 설명, 도구 호출을 위한 호스트 콜백
- 일시 중단된 게스트 프로그램을 위한 재개 가능한 상태
- 출력, 시간 초과, 메모리, 대기 중 호출, 스냅샷 제한
- 중첩 도구 호출에 대한 텔레메트리 및 궤적 투영
- 공급자 네이티브 원격 코드 실행
- 셸 실행 의미 체계
- 기존 도구 권한 부여 변경
- 지속적인 사용자 작성 스크립트
- 게스트 코드의 패키지 관리자, 파일, 네트워크 또는 모듈 접근
- Codex Code mode 내부 구현의 직접 재사용
용어
코드 모드는 일반 모델 도구를 숨기고exec와 wait만 노출하는 OpenClaw
런타임 모드입니다.
게스트 런타임은 모델 코드를 평가하는 QuickJS-WASI JavaScript VM입니다.
호스트 브리지는 게스트 코드에서 OpenClaw로 돌아오는 좁은 JSON 호환 콜백
표면입니다.
카탈로그는 일반 도구 정책, Plugin, MCP, 클라이언트 도구 해결 이후의
실행 범위 유효 도구 목록입니다.
중첩 도구 호출은 호스트 브리지를 통해 게스트 코드에서 수행되는 도구
호출입니다.
스냅샷은 wait가 일시 중단된 코드 모드 실행을 계속할 수 있도록 저장된
직렬화된 QuickJS-WASI VM 상태입니다.
구성
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.
활성화
코드 모드는 유효 도구 정책이 알려진 뒤, 최종 모델 요청이 조립되기 전에 평가됩니다. 활성화 순서:- 에이전트, 모델, 공급자, 샌드박스, 채널, 발신자, 실행 정책을 해결합니다.
- 유효 OpenClaw 도구 목록을 빌드합니다.
- 적격 Plugin, MCP, 클라이언트 도구를 추가합니다.
- 허용 및 거부 정책을 적용합니다.
tools.codeMode.enabled가 false이면 일반 도구 노출로 계속합니다.- 활성화되어 있고 실행에 도구가 활성 상태이면 유효 도구를 코드 모드 카탈로그에 등록합니다.
- 모델에 표시되는 도구 목록에서 모든 일반 도구를 제거합니다.
- 코드 모드
exec와wait를 추가합니다.
disableTools, 빈 허용 목록처럼 의도적으로 도구가 없는 실행은
구성에 tools.codeMode.enabled: true가 포함되어 있어도 코드 모드 표면을
활성화하지 않습니다.
코드 모드 카탈로그는 실행 범위입니다. 다른 에이전트, 세션, 발신자 또는
실행의 도구가 누출되어서는 안 됩니다.
모델에 표시되는 도구
코드 모드가 활성화되면 모델은 정확히 다음 최상위 도구를 봅니다.execwait
exec를 사용해야 합니다. 모델은 exec가 재개 가능한 waiting 결과를
반환할 때만 wait를 사용해야 합니다.
exec
exec는 코드 모드 셀을 시작하고 하나의 결과를 반환합니다. 입력 코드는 모델이
생성하며 적대적인 것으로 취급해야 합니다.
입력:
code또는command중 하나는 비어 있지 않아야 합니다.code는 문서화된 모델 대상 필드입니다.command는 훅 정책 및 신뢰할 수 있는 재작성에 대해 exec 호환 별칭으로 허용됩니다. 둘 다 있으면 값이 일치해야 합니다.- 외부 코드 모드
exec훅 이벤트에는toolKind: "code_mode_exec"가 포함되며, 입력 언어를 알 수 있을 때toolInputKind: "javascript" | "typescript"가 포함됩니다. 따라서 정책은 같은 도구 이름을 공유하는 셸 스타일exec호출과 코드 모드 셀을 구분할 수 있습니다. language의 기본값은"javascript"입니다.language가"typescript"이면 OpenClaw는 평가 전에 트랜스파일합니다.exec는 v1에서import,require, 동적 import, 모듈 로더 패턴을 거부합니다.exec는 일반 셸exec구현을 재귀적으로 노출하지 않습니다.
exec는 QuickJS VM이 재개 가능한 상태로 일시 중단되고, 모델에 표시되는 계속
작업이 아직 필요할 때 waiting을 반환합니다. 결과에는 wait를 위한 runId가
포함됩니다. MCP 네임스페이스 호출을 포함한 네임스페이스 브리지 호출은 준비되어
있는 동안 동일한 exec/wait 호출 내부에서 자동으로 소진되므로, 간결한 코드
블록이 네임스페이스 await마다 모델 도구 호출 하나를 강제하지 않고도 $api()를
검사하고 MCP 도구를 호출할 수 있습니다.
exec는 게스트 VM에 보류 중인 작업이 없고 OpenClaw의 출력 어댑터가 실행된 뒤
최종 값이 JSON 호환일 때만 completed를 반환합니다.
wait
wait는 일시 중단된 코드 모드 VM을 계속 실행합니다.
입력:
exec가 반환하는 것과 같은 CodeModeResult 유니언입니다.
wait가 존재하는 이유는 중첩된 OpenClaw 도구가 느리거나, 대화형이거나, 승인
게이트가 있거나, 부분 업데이트를 스트리밍할 수 있기 때문입니다. 모델은 호스트가
외부 작업을 기다리는 동안 하나의 긴 exec 호출을 계속 열어 둘 필요가 없어야
합니다.
QuickJS-WASI 스냅샷 및 복원은 v1 재개 메커니즘입니다.
exec는 완료, 실패 또는 일시 중단될 때까지 코드를 평가합니다.- 일시 중단 시 OpenClaw는 QuickJS VM의 스냅샷을 만들고 보류 중인 호스트 작업을 기록합니다.
- 보류 중인 작업이 안정되면
wait가 VM 스냅샷을 복원합니다. - OpenClaw는 안정적인 이름으로 호스트 콜백을 다시 등록합니다.
- OpenClaw는 중첩된 도구 결과를 복원된 VM으로 전달합니다.
- OpenClaw는 QuickJS 보류 작업을 비웁니다.
wait는completed,failed또는 또 다른waiting결과를 반환합니다.
wait는 다음 경우 실패합니다.
runId를 알 수 없습니다.- 스냅샷이 만료되었습니다.
- 상위 실행 또는 세션이 중단되었습니다.
- 호출자가 같은 실행/세션 범위에 없습니다.
- QuickJS-WASI 복원이 실패합니다.
- 복원하면 구성된 제한을 초과합니다.
게스트 런타임 API
게스트 런타임은 작은 전역 API를 노출합니다.ALL_TOOLS는 실행 범위 카탈로그의 간결한 메타데이터입니다. 기본적으로 전체
스키마를 포함하지 않습니다.
tools.call(...) 또는 편의 함수로 호출할 수
없습니다. 생성된 MCP 네임스페이스를 통해서만 노출됩니다. TypeScript 스타일
선언 파일은 읽기 전용 API 가상 파일 표면을 통해 사용할 수 있으므로, 에이전트는
프롬프트에 MCP 스키마를 추가하지 않고도 MCP 시그니처를 검사할 수 있습니다.
API.read("mcp/<server>.d.ts")는 MCP 도구 메타데이터에서 추론한 간결한 선언을
반환합니다.
exec 호출마다 OpenClaw는 실행 범위 도구 카탈로그를
만들고, 표시되는 MCP 항목을 유지하며, 표시되는 서버마다 mcp/index.d.ts와
mcp/<server>.d.ts 선언 하나를 렌더링한 뒤, 그 작은 읽기 전용 테이블을 QuickJS
워커에 주입합니다. 게스트 코드는 API 객체만 봅니다. API.list(prefix?)는 파일
메타데이터를 반환하고 API.read(path)는 선택한 선언 콘텐츠를 반환합니다. 알 수
없는 경로와 . / .. 세그먼트는 거부됩니다.
이 방식은 큰 MCP 스키마를 모델 프롬프트 밖에 둡니다. 에이전트는 exec 도구
설명에서 가상 API가 있음을 학습하고, 필요한 선언 파일만 읽은 다음,
MCP.<server>.<tool>()을 하나의 객체 인수로 호출합니다. 프로그램 안에서
에이전트가 단일 도구 스키마 응답이 필요할 때는 MCP.<server>.$api()를 인라인
대체 경로로 계속 사용할 수 있습니다.
게스트 런타임은 호스트 객체를 직접 노출해서는 안 됩니다. 입력과 출력은 명시적
크기 제한이 있는 JSON 호환 값으로 브리지를 건넙니다.
내부 네임스페이스
내부 네임스페이스는 모델에 표시되는 도구를 더 추가하지 않고 코드 모드에 간결한 도메인 API를 제공합니다. 로더가 소유한 통합은Issues, Fictions 또는
Calendar 같은 네임스페이스를 등록할 수 있습니다. 그러면 게스트 코드는 QuickJS
프로그램 안에서 해당 네임스페이스를 호출하고, OpenClaw는 모델에 여전히 exec와
wait만 표시합니다.
네임스페이스는 현재 내부용입니다. 공개 Plugin SDK 네임스페이스 API는 없습니다.
외부 Plugin 네임스페이스에는 로더가 소유한 계약이 필요합니다. 그래야 Plugin
ID, 설치된 매니페스트, 인증 상태, 캐시된 카탈로그 설명자가 네임스페이스를
뒷받침하는 Plugin 도구와 어긋나지 않습니다. 코어 코드 모드는 샌드박스, 직렬화,
카탈로그 게이팅, 브리지 디스패치만 소유합니다.
게스트 코드는 직접 전역 또는 namespaces 맵을 사용할 수 있습니다.
레지스트리 수명 주기
네임스페이스 레지스트리는 프로세스 로컬이며 네임스페이스 ID로 키가 지정됩니다. 일반적인 실행은 다음 경로를 따릅니다.- 신뢰할 수 있는 로더가
registerCodeModeNamespaceForPlugin(pluginId, registration)을 호출합니다. - 코드 모드는 실행을 위한 숨겨진
ToolSearchRuntime을 만들고 실행 범위 카탈로그를 읽습니다. createCodeModeNamespaceRuntime(ctx, catalog)는requiredToolNames가 모두 표시되고 같은pluginId가 소유한 등록만 유지합니다.- 표시되는 각 네임스페이스는 현재 실행에 대해
createScope(ctx)를 호출합니다. 스코프는agentId,sessionKey,sessionId,runId, 구성, 중단 상태 같은 실행 컨텍스트를 받습니다. - 스코프 데이터는 일반 설명자로 직렬화되어 직접 전역 및
namespaces.<globalName>으로 QuickJS에 주입됩니다. - 게스트 호출은 워커 브리지를 통해 일시 중단되고, 호스트에서 네임스페이스
경로를 확인하며, 호출을 선언된 Plugin 소유 카탈로그 도구로 매핑하고,
ToolSearchRuntime.call을 통해 해당 도구를 실행합니다. - OpenClaw는 활성
exec/wait도구 호출 안에서 준비된 네임스페이스 브리지 호출을 자동으로 비웁니다. 제한 시간에 네임스페이스 작업이 아직 보류 중이거나 게스트가 명시적으로 양보하면,wait가 나중에 같은 네임스페이스 런타임을 재개합니다. - Plugin 롤백 또는 제거는
clearCodeModeNamespacesForPlugin(pluginId)를 호출하여 오래된 전역이 실패한 Plugin 로드 뒤에도 남지 않게 합니다.
tools.call(...)과 같은 정책 훅, 승인, 중단 처리, 텔레메트리, 트랜스크립트
투영, 일시 중단/재개 동작을 사용합니다.
등록 형태
뒷받침하는 도구를 소유한 통합에서 네임스페이스를 등록하세요. 스코프를 작게 유지하고 선언된 카탈로그 도구에 매핑되는 도메인 동사만 노출하세요.createCodeModeNamespaceTool(toolName, inputMapper)는 스코프 멤버를 호출 가능한
네임스페이스 함수로 표시합니다. 선택적 inputMapper는 게스트 인수를 받고
뒷받침하는 카탈로그 도구의 입력 객체를 반환합니다. 입력 매퍼가 없으면 첫 번째
게스트 인수가 사용되며, 생략된 경우 {}가 사용됩니다.
원시 호스트 함수는 게스트 코드가 실행되기 전에 거부됩니다.
소유권 및 가시성
네임스페이스 소유권은 등록 호출자의pluginId에 바인딩됩니다.
requiredToolNames는 가시성 게이트이자 소유권 검사입니다.
- 모든 필수 도구는 실행 카탈로그에 있어야 합니다.
- 모든 필수 도구는
sourceName === pluginId여야 합니다. - 필수 도구가 없거나 다른 Plugin이 소유하면 네임스페이스는 숨겨집니다.
- 각 호출 가능한 경로는
requiredToolNames에 이름이 있는 도구만 대상으로 할 수 있습니다.
스코프 직렬화 규칙
createScope(ctx)는 JSON 호환 값, 배열, 중첩 객체, 그리고
createCodeModeNamespaceTool(...) 호출 마커를 포함하는 일반 객체를 반환할 수
있습니다. 호스트 객체는 QuickJS에 직접 들어가지 않습니다.
직렬화기는 다음을 거부합니다.
- 원시 함수
- 순환 객체 그래프
- 안전하지 않은 경로 세그먼트:
__proto__,constructor,prototype, 빈 키 또는 내부 경로 구분자를 포함하는 키 - JavaScript 식별자가 아닌
globalName값 tools,namespaces,text,json,yield_control또는__openclaw*같은 기본 제공 코드 모드 전역과 충돌하는globalName
프롬프트
네임스페이스description과 선택적 prompt는 해당 실행에서 네임스페이스가
표시될 때만 모델에 표시되는 exec 스키마에 추가됩니다. 이를 사용해 가장 작은
유용한 표면을 학습시키세요.
정리
네임스페이스는 프로세스 로컬 등록입니다. 소유 Plugin이 비활성화, 제거 또는 롤백될 때 제거하세요.clearCodeModeNamespacesForTest()를 호출할 수 있습니다.
테스트 체크리스트
네임스페이스 변경은 보안 경계와 게스트 동작을 포함해야 합니다.- 지원 도구가 표시될 때만 네임스페이스 프롬프트 텍스트가 나타남
- 다른
sourceName의 같은 이름 도구가 네임스페이스를 노출하지 않음 - 원시 범위 함수가 거부됨
- 위조된 네임스페이스 id와 위조된 경로가 거부됨
- 호출 가능한 경로가 선언되지 않은 도구를 대상으로 할 수 없음
- 중첩 객체와 공유 참조가 올바르게 직렬화됨
- 네임스페이스 호출이 카탈로그 도구를 통해 실행되고 JSON 안전 세부 정보를 반환함
- 실패를 게스트 코드에서 잡을 수 있음
- 일시 중단된 네임스페이스 호출이
wait를 통해 재개됨 - Plugin 롤백이 소유 네임스페이스 등록을 지움
tools.search / tools.call 카탈로그를 보완합니다. 임의로 활성화된 OpenClaw, Plugin, 클라이언트 도구에는 카탈로그를 사용하고, MCP 도구에는 MCP를 사용하며, 반복적인 스키마 조회보다 간결한 코드가 더 안정적인 Plugin 소유의 문서화된 도메인 API에는 다른 네임스페이스를 사용하세요.
출력 API
text(value)는 사람이 읽을 수 있는 출력을 output 배열에 추가합니다.
json(value)는 JSON 호환 직렬화 후 구조화된 출력 항목을 추가합니다.
게스트 코드가 최종적으로 반환한 값은 completed 결과의 value가 됩니다.
출력 항목:
- 출력 순서는 게스트 호출과 일치함
- 출력은
maxOutputBytes로 제한됨 - 직렬화할 수 없는 값은 일반 문자열이나 오류로 변환됨
- 바이너리 값은 v1에서 지원되지 않음
- 이미지와 파일은 코드 모드 브리지를 통하지 않고 일반 OpenClaw 도구를 통해 이동함
도구 카탈로그
숨겨진 카탈로그에는 유효 정책 필터링 후의 도구가 포함됩니다.- OpenClaw 코어 도구.
- 번들 Plugin 도구.
- 외부 Plugin 도구.
- MCP 도구.
- 현재 실행을 위해 클라이언트가 제공한 도구.
execwaittool_search_codetool_searchtool_describetool_call
ALL_TOOLS, tools.search(...), tools.describe(...), tools.call(...) 뷰는 MCP 항목을 생략합니다. 생성된 MCP.<server>.<tool>({ ...input }) 네임스페이스는 정확한 카탈로그 id로 다시 해석된 뒤 동일한 실행기 경로를 통해 디스패치됩니다.
도구 검색 상호작용
코드 모드는 활성화된 실행에서 OpenClaw 도구 검색 모델 표면을 대체합니다.tools.codeMode.enabled가 true이고 코드 모드가 활성화되면:
- OpenClaw는
tool_search_code,tool_search,tool_describe,tool_call을 모델에 표시되는 도구로 노출하지 않습니다. - 동일한 카탈로그화 개념이 게스트 런타임 내부로 이동합니다.
- 게스트 런타임은 비 MCP 도구에 대한 압축된
ALL_TOOLS메타데이터와 검색, 설명, 호출 헬퍼를 받습니다. - MCP 호출은
tools.call(...)대신 생성된MCP네임스페이스와 그$api()헤더를 사용합니다. - 중첩 호출은 도구 검색이 사용하는 것과 동일한 OpenClaw 실행기 경로를 통해 디스패치됩니다.
exec와 wait를 사용할 수 있는 실행을 위한 일반 OpenClaw 대안입니다.
도구 이름과 충돌
모델에 표시되는exec 도구는 코드 모드 도구입니다. 일반 OpenClaw 셸 exec 도구가 활성화된 경우 모델에서는 숨겨지고 다른 도구처럼 카탈로그화됩니다.
게스트 런타임 내부:
- 정책이 허용하면
tools.call("openclaw:core:exec", input)이 셸 exec 도구를 호출할 수 있습니다. tools.exec(...)는 셸 exec 카탈로그 항목에 모호하지 않은 안전한 이름이 있을 때만 설치됩니다.- 코드 모드
exec도구는tools를 통해 재귀적으로 사용할 수 없습니다.
tools.call(id, input)을 요구합니다.
중첩 도구 실행
모든 중첩 도구 호출은 호스트 브리지를 건너 OpenClaw에 다시 진입합니다. 중첩 실행은 다음을 보존합니다.- 활성 에이전트 id
- 세션 id와 세션 키
- 발신자 및 채널 컨텍스트
- 샌드박스 정책
- 승인 정책
- Plugin
before_tool_call훅 - abort 신호
- 사용 가능한 경우 스트리밍 업데이트
- 궤적 및 감사 이벤트
maxPendingToolCalls까지 허용됩니다.
런타임 상태
각 코드 모드 실행에는 상태 머신이 있습니다.running: VM이 실행 중이거나 중첩 호출이 진행 중입니다.waiting: VM 스냅샷이 존재하며wait로 재개할 수 있습니다.completed: 최종 값이 반환되었고 스냅샷이 삭제되었습니다.failed: 오류가 반환되었고 스냅샷이 삭제되었습니다.expired: 스냅샷 또는 보류 상태가 보존 기간을 초과했으며 재개할 수 없습니다.aborted: 부모 실행/세션이 취소되었고 스냅샷이 삭제되었습니다.
wait 호출은 실패합니다.
스냅샷 저장소는 제한됩니다.
- 실행당 최대 스냅샷 바이트
- 프로세스당 최대 라이브 스냅샷 수
- 스냅샷 TTL
- 실행 종료 시 정리
- 지속성이 지원되지 않는 경우 Gateway 종료 시 정리
QuickJS-WASI 런타임
OpenClaw는 소유 패키지에서 직접 의존성으로quickjs-wasi를 로드합니다. 런타임은 프록시, PAC 또는 관련 없는 다른 의존성을 위해 설치된 전이 복사본에 의존하지 않습니다.
런타임 책임:
- QuickJS-WASI WebAssembly 모듈 컴파일 또는 로드
- 코드 모드 실행 또는 재개마다 격리된 VM 하나 생성
- 안정적인 이름으로 호스트 콜백 등록
- 메모리 및 인터럽트 제한 설정
- JavaScript 평가
- 보류 중인 작업 비우기
- 일시 중단된 VM 상태 스냅샷 생성
wait를 위한 스냅샷 복원- 터미널 상태 이후 VM 핸들과 스냅샷 폐기
TypeScript
TypeScript 지원은 소스 변환만 수행합니다.- 허용되는 입력: TypeScript 코드 문자열 하나
- 출력: QuickJS-WASI가 평가하는 JavaScript 문자열
- 타입 검사 없음
- 모듈 해석 없음
- v1에서
import또는require없음 - 진단은
failed결과로 반환됨
보안 경계
모델 코드는 적대적입니다. 런타임은 심층 방어를 사용합니다.- 메인 이벤트 루프 밖에서 QuickJS-WASI 실행
- Codex나 전이 패키지를 통하지 않고 직접 의존성으로
quickjs-wasi로드 - 게스트에 파일 시스템, 네트워크, 하위 프로세스, 모듈 import, 환경 변수 또는 호스트 전역 객체 없음
- QuickJS 메모리 및 인터럽트 제한 사용
- 부모 프로세스 벽시계 시간 제한 강제
- 출력, 스냅샷, 로그, 보류 호출 상한 강제
- 좁은 JSON 어댑터를 통해 호스트 브리지 값 직렬화
- 호스트 오류를 일반 게스트 오류로 변환하고 호스트 realm 객체는 절대 전달하지 않음
- 시간 초과, abort, 세션 종료 또는 만료 시 스냅샷 삭제
exec,wait, 도구 검색 제어 도구에 대한 재귀 접근 거부- 편의 이름 충돌이 카탈로그 헬퍼를 가리지 못하게 방지
오류 코드
Error 인스턴스, 스택 객체, 프로토타입, 호스트 함수는 QuickJS로 넘어가지 않습니다.
텔레메트리
코드 모드는 다음을 보고합니다.- 모델에 전송된 표시 도구 이름
- 숨겨진 카탈로그 크기와 소스별 분류
exec및wait횟수- 중첩 검색, 설명, 호출 횟수
- 호출된 중첩 도구 id
- 시간 초과, 메모리, 스냅샷, 출력 상한 실패
- 스냅샷 수명 주기 이벤트
디버깅
코드 모드가 일반 도구 실행과 다르게 동작할 때는 대상 모델 전송 로깅을 사용하세요.OPENCLAW_DEBUG_MODEL_PAYLOAD=full-redacted를 사용하세요. 이는 모델 요청의 제한되고 수정된 JSON 스냅샷을 기록합니다. 프롬프트와 메시지 텍스트가 여전히 나타날 수 있으므로 디버깅 중에만 사용해야 합니다.
스트림 디버깅에는 OPENCLAW_DEBUG_SSE=peek를 사용하여 처음 다섯 개의 수정된 SSE 이벤트를 기록하세요. 코드 모드 표면이 활성화된 후 최종 제공자 페이로드에 정확히 exec와 wait가 포함되어 있지 않으면 코드 모드는 실패로 닫힙니다.
구현 레이아웃
구현 단위:- config 계약:
tools.codeMode - 카탈로그 빌더: 유효 도구를 압축 항목과 id 맵으로 변환
- 모델 표면 어댑터: 표시 도구를
exec와wait로 교체 - QuickJS-WASI 런타임 어댑터: 로드, 평가, 스냅샷, 복원, 폐기
- 워커 감독자: 시간 초과, abort, 충돌 격리
- 브리지 어댑터: JSON 안전 호스트 콜백과 결과 전달
- TypeScript 변환 어댑터
- 스냅샷 저장소: TTL, 크기 상한, 실행/세션 범위 지정
- 중첩 도구 호출의 궤적 프로젝션
- 텔레메트리 카운터와 진단
node:vm 자식을 사용하지 않습니다.
검증 체크리스트
코드 모드 커버리지는 다음을 증명해야 합니다.- 비활성화된 구성은 기존 도구 노출을 변경하지 않습니다
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")는 브리지/도구 호출 없이 TypeScript 스타일 MCP 선언을 노출합니다- MCP 네임스페이스
$api()는 스키마용 인라인 대체 경로로 계속 사용할 수 있습니다 - MCP 네임스페이스 호출은 하나의 객체 입력을 받는 표시 가능한 MCP 도구에서 작동하지만,
직접 MCP 카탈로그 항목은
tools.*에 없습니다 - Tool Search 제어 도구는 모델 표면과 숨겨진 카탈로그 모두에서 숨겨집니다
- 중첩 호출은 승인 및 훅 동작을 보존합니다
- 셸
exec는 모델에서 숨겨지지만 허용된 경우 카탈로그 id로 호출할 수 있습니다 - 재귀 코드 모드
exec와wait는 게스트 코드에서 호출할 수 없습니다 - TypeScript 입력은 비활성화된 경로 또는 JavaScript 전용 경로에서 TypeScript를 로드하지 않고 변환 및 평가됩니다
import,require, 파일 시스템, 네트워크, 환경 접근은 실패합니다- 무한 루프는 시간 초과되며 Gateway를 차단할 수 없습니다
- 메모리 한도 실패는 게스트 VM을 종료합니다
- 완료된 호출과 일시 중단된 호출에 대해 출력 및 스냅샷 한도가 적용됩니다
wait는 일시 중단된 스냅샷을 재개하고 최종 값을 반환합니다- 만료됨, 중단됨, 잘못된 세션, 알 수 없는
runId값은 실패합니다 - 트랜스크립트 재생 및 지속성은 코드 모드 제어 호출을 보존합니다
- 트랜스크립트와 텔레메트리는 중첩 도구 호출을 명확히 표시합니다
E2E 테스트 계획
런타임을 변경할 때 다음을 통합 테스트 또는 엔드투엔드 테스트로 실행하세요.tools.codeMode.enabled: false로 Gateway를 시작합니다.- 작은 직접 도구 세트로 에이전트 턴을 보냅니다.
- 모델에 표시되는 도구가 변경되지 않았는지 확인합니다.
tools.codeMode.enabled: true로 다시 시작합니다.- OpenClaw, Plugin, MCP, 클라이언트 테스트 도구로 에이전트 턴을 보냅니다.
- 모델에 표시되는 도구 목록이 정확히
exec,wait인지 확인합니다. exec에서ALL_TOOLS를 읽고 유효한 테스트 도구가 있는지 확인합니다.exec에서tools.search,tools.describe,tools.call을 통해 OpenClaw/Plugin/클라이언트 도구를 호출합니다.exec에서API.list("mcp")와API.read("mcp/<server>.d.ts")를 호출하고 선언 파일이 표시 가능한 MCP 도구를 설명하는지 확인합니다.exec에서MCP.<server>.<tool>({ ...input })을 통해 MCP 도구를 호출하고 직접 MCP 카탈로그 항목이ALL_TOOLS와tools.*에 없는지 확인합니다.- 거부된 도구가 없고 추측한 id로 호출할 수 없는지 확인합니다.
exec가waiting을 반환한 뒤 해결되는 중첩 도구 호출을 시작합니다.wait를 호출하고 복원된 VM이 도구 결과를 받는지 확인합니다.- 최종 답변에 복원 후 생성된 출력이 포함되어 있는지 확인합니다.
- 시간 초과, 중단, 스냅샷 만료가 런타임 상태를 정리하는지 확인합니다.
- trajectory를 내보내고 중첩 호출이 상위 코드 모드 호출 아래에 표시되는지 확인합니다.
pnpm check:docs를 실행해야 합니다.