openclaw/docs/plugins/sdk-runtime.md
Peter Steinberger 54a986072f
docs(plugins): remove obsolete Gateway restart guidance (#146516)
* docs(plugins): remove obsolete Gateway restart guidance

* docs(plugins): simplify apply hints and update Session Share guidance
2026-09-12 16:48:13 -07:00

16 KiB

summary title sidebarTitle read_when
api.runtime -- the injected runtime helpers available to plugins Plugin runtime helpers Runtime helpers
You need to call core helpers from a plugin (TTS, STT, image gen, web search, Gateway, subagent, nodes)
You want to understand what api.runtime exposes
You are accessing config, agent, or media helpers from plugin code
You are implementing model-picker persistence in a channel plugin

Reference for the live api.runtime object available during "full", "discovery", "tool-discovery", and "setup-runtime" registration. During "cli-metadata" and "setup-only" registration, runtime capabilities are intentionally unavailable: accessing one throws an error naming the plugin and mode. Defer runtime access out of register() or, for root CLI commands, declare cliCommands in the plugin manifest. Use runtime helpers instead of importing host internals directly.

Step-by-step guide that uses these helpers in context for channel plugins. Step-by-step guide that uses these helpers in context for provider plugins.
register(api) {
  const runtime = api.runtime;
}

api.runtime.version is the current OpenClaw product version, sourced from the shared version resolver so plugins see the same value the CLI reports.

What each page covers

  • Config and utilities — runtime config reads and writes, plus the shared process, error, and model-picker utilities.
  • Agent and sessions — agent identity, directories, session store, transcripts, and sandbox authority.
  • Model helpers — host-owned completions, model-selection policy, and provider auth resolution.
  • Background work — hook agent turns, subagent runs, and Task Flow record binding.
  • Gateway and nodes — in-process Gateway requests, paired node invocation, and Gateway service events.
  • Media helpers — speech, media understanding, image/video/music generation, web search, and media utilities.
  • State and system — config snapshot, SQLite-backed plugin state, system utilities, events, and logging.
  • Channel helpers — channel-specific runtime helper groups for chunking, routing, pairing, media, and mentions.

Runtime namespaces

Every api.runtime namespace and the page that documents it.

Namespace Page
api.runtime.agent Agent and sessions
api.runtime.agent.defaults Agent and sessions
api.runtime.llm Model helpers
api.runtime.gateway Gateway and nodes
api.runtime.hooks Background work
api.runtime.subagent Background work
api.runtime.sandbox Agent and sessions
api.runtime.nodes Gateway and nodes
api.runtime.tasks Background work
api.runtime.tts Media helpers
api.runtime.mediaUnderstanding Media helpers
api.runtime.imageGeneration Media helpers
api.runtime.videoGeneration Media helpers
api.runtime.musicGeneration Media helpers
api.runtime.webSearch Media helpers
api.runtime.media Media helpers
api.runtime.config State and system
api.runtime.system State and system
api.runtime.events State and system
api.runtime.logging State and system
api.runtime.modelConfig Model helpers
api.runtime.modelAuth Model helpers
api.runtime.state State and system
api.runtime.channel Channel helpers

Storing runtime references

Use createPluginRuntimeStore to store the runtime reference for use outside the register callback:

```typescript import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store"; import type { PluginRuntime } from "openclaw/plugin-sdk/runtime-store";
const store = createPluginRuntimeStore<PluginRuntime>({
  pluginId: "my-plugin",
  errorMessage: "my-plugin runtime not initialized",
});
```
```typescript import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
// `myPlugin` is your own `ChannelPlugin` object and `store` is the store
// created in the previous step; neither is an SDK export.
export default defineChannelPluginEntry({
  id: "my-plugin",
  name: "My Plugin",
  description: "Example",
  plugin: myPlugin,
  setRuntime: store.setRuntime,
});
```
```typescript export function getRuntime() { return store.getRuntime(); // throws if not initialized }
export function tryGetRuntime() {
  return store.tryGetRuntime(); // returns null if not initialized
}
```
Prefer `pluginId` for the runtime-store identity. The lower-level `key` form is for uncommon cases where one plugin intentionally needs more than one runtime slot.

Plugin lifecycle and cleanup

A managed plugin instance owns its registered callables, runtime-store slots, and loaded source generation. Retiring the instance stops new calls through its managed handles. Already admitted calls and streams have a bounded chance to finish before disposal; retaining an old function does not make it a current runtime handle.

Context engines selected by an admitted turn remain owned through that turn's commit and engine disposal. Reload can report their cleanup as deferred; starting engine disposal closes normal engine callbacks while cleanup finishes.

Managed instances expose api.lifecycle.signal and api.lifecycle.onDispose(cleanup). The signal aborts when disposal reaches explicit cleanup. onDispose accepts a synchronous or asynchronous callback and returns a function that unregisters it. Callbacks run once, in reverse registration order, within a shared cleanup budget. A throwing or unfinished callback is recorded as a cleanup failure while the remaining cleanup is attempted. These fields are optional in the SDK type because an API host without a managed instance may omit them; feature-detect them before relying on instance cleanup. The existing api.lifecycle.registerRuntimeLifecycle(...) contract remains available for plugin-owned host state.

Cleanup is best effort. Plugins must explicitly release their own timers, listeners, sockets, watchers, and child processes in onDispose or their service's stop() method. OpenClaw does not intercept those native resources or prove that they have stopped when managed retirement completes. Native plugins remain trusted, in-process code. Plain data and native byte buffers retain their normal identities; lifecycle fencing applies to the managed callable surfaces, not every object a plugin can retain.

Opaque values returned by a plugin can be passed back directly or in data-only records and arrays. Caller-owned objects with methods or accessors are passed unchanged, including any handles inside them.

createPluginRuntimeStore resolves its slot from the invoking managed instance. Preparing another instance does not overwrite that instance's runtime. Calls outside managed instance scope retain the store's existing standalone behavior.

SDK helpers that return bare results retain their resources until the owning host closes. Callers do not need to dispose those results; see Prepared simple completions.

Memory runtime replacement

Memory runtimes may implement prepareReload({ retireRuntime, retiringEmbeddingProviders }) and return drain() and resume(). Preparation synchronously fences affected manager acquisition, including lazy and fallback work. Match the exact acquired adapter objects rather than provider IDs. Drain removes affected managers from reuse before attempting to close them. It may return { errors } to report cleanup failures. Resume reopens admission after cancellation, or after publication when the runtime is retained, even if old cleanup remains unfinished. Retiring managers must not publish late results into a replacement manager's caches.

Preparing an unused runtime must leave its manager engine unloaded. For runtimes without this hook, OpenClaw calls the existing closeAllMemorySearchManagers method, when provided, if the runtime or an embedding adapter retires. This closes all of that runtime's managers as best-effort cleanup; it cannot identify dependent managers or prevent concurrent manager acquisition.

Other top-level api fields

Beyond api.runtime, the API object also provides:

Plugin id. Plugin display name. Config snapshot supplied when this instance registers. With the default hybrid reload mode, changes to this plugin's `plugins.entries.` replace its instance by default and rerun registration. A retained instance keeps its snapshot across unrelated config changes. In long-lived callbacks, prefer the supplied `cfg`, or use `api.runtime.config.current()` when no config is passed. Plugin-specific config from `plugins.entries..config`, captured at registration. Ordinary edits to this config automatically replace the instance in hybrid mode, unless a narrower plugin reload policy applies. Source or manifest edits still need [plugin Reload](/cli/plugins#reload). Scoped logger (`debug`, `info`, `warn`, `error`). Current load mode: `"full"` (live activation), `"discovery"` / `"tool-discovery"` (read-only capability discovery), `"setup-only"` (lightweight setup entry), `"setup-runtime"` (setup flow that also needs the runtime channel entry), or `"cli-metadata"` (CLI command metadata collection). Resolve a path relative to the plugin root.

Where each section moved

Every section heading and namespace anchor from the previous single-page version keeps its anchor here, so an existing link such as /plugins/sdk-runtime#api-runtime-subagent still resolves. Each entry points at the page that now holds the content.