On this page

On this page

Get started

Runtime execution profiles

OpenClaw distinguishes the code compiled into a host from code supplied after that host was built. The runtime profile owns that distinction. It is selected from the standalone artifact's immutable bootstrap facts, with a manifest fallback for hosts without those facts. A user setting, filename suffix, operating system, or trial call to eval does not select the profile.

Profiles

Host Profile Host execution contract
Node or Bun installation, source checkout dynamic-execution Source plugins and intentional host JavaScript execution are available.
JIT or bytecode standalone dynamic-execution Source plugins and intentional host JavaScript execution use the existing standalone loading contract.
AOT standalone (manifest.json has mode: "aot") embedded-aot Host code must already be embedded. Source plugin loading and host JavaScript evaluation fail with a next step.

The selection is process-stable. Workers make the same selection from the same artifact. Replacing an artifact requires restarting its processes; changing the manifest under a running Gateway does not change its execution profile.

An execution profile is a compatibility contract, not a sandbox or a new grant of authority. Tool permissions, approval checks, plugin trust, cancellation, and lifecycle ownership still apply in both profiles.

Features that execute code

The default Node Code Mode executor runs JavaScript in node:vm in a worker thread. A worker thread shares the host's runtime restrictions. In an embedded AOT host it reports runtime_unavailable before creating that worker. Run the Gateway with a Node/Bun installation or a JIT/bytecode standalone to use it. The existing QuickJS executor is a separate guest runtime; it is not silently selected instead. An embedded QuickJS deployment still needs its own WASM and worker qualification. See Code Mode executors.

QA scenario expressions and lambdas also execute host JavaScript. Embedded AOT reports a profile error before compiling them. Run those scenarios in a dynamic-execution host. Declarative values and actions that do not evaluate JavaScript keep their normal behavior.

Browser JavaScript executes in the browser. A host-side syntax check or callback serializer must use parsing or static source, not compile the expression locally. External MCP servers and separately launched runtimes have their own execution profile. Starting a worker thread, or relaunching the same AOT executable, does not create a dynamic-execution host.

Plugins fetched after the build

A successful installation does not make a plugin part of an AOT executable. The embedded host admits compiled image modules; a plugin's JavaScript or TypeScript downloaded later requires a dynamic-execution host. This applies to pretranspiled JavaScript too. Metadata discovery and configuration validation must remain available without running plugin code.

Plugin authors should use the documented SDK runtime capability assertion before intentional host evaluation and propagate its actionable error. Do not catch it and fall back to another host evaluator. Keep fixed programs as normal source functions or build-time generated modules. Runtime schemas require a codegen-free validator; runtime syntax checks require a parser. Workers need explicit embedded entries. Dependencies follow the same rules, including transitive imports.

An embedded-compatible declaration or lint result is not a proof that an arbitrary downloaded module can run in the image. Shipping another plugin in an AOT host requires rebuilding the complete artifact with that plugin. A separate dynamic host can instead run it using the existing Gateway/MCP/tool protocol; this profile does not invent an automatic plugin sidecar or serialize live SDK objects across processes.

String-codegen hardening

AOT compilation alone does not forbid eval, Function, or VM source. Those paths can still invoke Bun's interpreter. The profile gates intentional host execution at its owners; it does not monkey-patch JavaScript globals.

The experimental compiler's ordinary --disallow-code-generation-from-strings flag rejects eval and Function constructors but still permits node:vm. Its strict variant also restricts VM and disk-loaded code. Build-time hardening needs the fixed validator, browser, codec, worker, and plugin paths to be compatible first. Selecting embedded-aot is not a claim that the whole executable contains no interpreter, and this change does not enable a process-wide strict flag by default.

Qualification should compile a small probe of the actual boundary and compare behavior with and without the profile gate. Do not use the experimental interpreter crash flag as an all-clear signal: it has allowed interpreted runtime source in compiled positive controls. Whole-artifact builds and runtime campaigns remain necessary before shipping an AOT desktop release.

Was this useful?