* fix(plugins): preserve authored config through runtime load plans * feat(judgments): add typed provider runtime and plugin SDK * feat(plugins): add per-agent decision models Add an opt-in decisionModel role for typed choices, scores, and boolean probabilities, with global defaults and per-agent inheritance or disablement. Keep provider lifecycle and prepared credentials host-owned, and expose manifest-only decision choices separately from conversational model catalogs. Adapt the provider foundation from #152237 to the decisions contract. Existing configurations keep decision calls disabled until a model is selected. Co-authored-by: Josh Lehman <550978+jalehman@users.noreply.github.com> * fix(plugins): complete decision inspection and preserve authored config Expose optional decision-provider health through the Gateway wire schema and generated native DTOs. Preserve the landed SecretRef prerequisite’s identity behavior for unchanged activation plans. Move model mocks into one private sibling factory without expanding the public helper surface. Validation: 51 handler/protocol tests, 18 post-extraction tests, 52 runtime and integration tests, generated protocol checks, and clean P0-P2 review. The SDK surface-budget increase remains pending maintainer approval. Co-authored-by: Josh Lehman <550978+jalehman@users.noreply.github.com> * perf(plugins): reduce decision overhead and unnecessary reloads Keep one full provider input snapshot and an independent question rubric. Recognize decision-only catalog providers with the existing normalization policy, and reload plugins only for decision-model changes while preserving roster actions. Apply the approved SDK surface increment and behavior-neutral cleanup. Validation: 58 runtime/config/loader tests, 610 Gateway regression/sibling tests plus 15 final catalog cases, full core typechecks, scoped lint and clean managed review. A 143155-attempt synthetic stress run settles all 18104 provider calls at max concurrency four. * fix(plugins): preserve reload boundaries and decision test contracts Materialize only present decision-selector leaves so Telegram account creation/removal retains its parent lifecycle action. Select UI controls by model role, preserve independent chat and decision catalogs in tests, remove an unused probe, and rebalance existing typecheck shards without raising their limits. Validation: 588 reload tests, 58 shard/loader tests, 38 UI catalog tests, 9 browser tests, affected typechecks, unused-file scans, and clean managed review. * test(ui): address model pickers by role in gateway flows Disambiguate Primary from the new Decision picker in the real-Gateway catalog test, alias browser test, and Agents view assertions. Preserve draft and publication checks. Unit/browser/typecheck proof and managed review pass; real-Gateway execution follows on the integrated build. * test(plugins): isolate runtime metadata and preserve shard headroom Move the existing lazy-runtime metadata contract intact into its own focused module. Group CLI program tests with commands so newer main tests keep every typecheck shard within existing limits. No production changes or limit increases. Validation: 57 tests, four typecheck graphs, canonical line guards against the CI main snapshot, targeted lint and clean managed review. --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> Co-authored-by: Josh Lehman <550978+jalehman@users.noreply.github.com>
19 KiB
| summary | title | sidebarTitle | read_when | ||||
|---|---|---|---|---|---|---|---|
| api.runtime -- the injected runtime helpers available to plugins | Plugin runtime helpers | Runtime helpers |
|
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.
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:
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. Replacing an enabled plugin waits for those consumers to close before registering its successor. Disabling or removing a plugin can report their cleanup as deferred; starting engine disposal closes normal engine callbacks while cleanup finishes.
Replacement validates metadata and configuration first, then stops services and
channels, drains admitted work, runs gateway_stop, and disposes the old instance
before invoking the new registration. Pre-publication failure triggers automatic
recovery by registering the captured previous code with its previous config;
a stopped instance is not assumed to be restartable. A plugin cannot synchronously
replace itself from its own active call: the operation rejects before shutdown
and can be retried after that call finishes. Cleanup that cannot finish within
its budget can prevent safe replacement or recovery. Unaffected instances remain
active, and the Gateway process stays running.
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.
Release the stored handle as well as canceling a timer. On Node, a canceled timer object can still retain the async context in which it was created:
clearInterval(timer);
timer = undefined;
This matters for module-level state in native ESM plugins: Node can retain an evaluated module after replacement. Removing the captured files and closing its managed callbacks does not unload that native module or clear its variables. Drop references to stopped resources and other disposable state in cleanup.
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.
Worker provider allocation authority
The Gateway supplies assertCurrent() in the options passed to worker providers'
provision and prepareProvision methods. This required runtime callback binds
the operation to the live environment owner and any requesting run. Invoke it
after awaited preparation and immediately before an allocation, checkpoint fork,
or adoption. A non-aborted signal does not prove that the caller still has
authority. Providers with project preparation must compose this callback with
project.assertCurrent() so both owners remain current.
The callback belongs to the provision attempt. Carry it into a returned prepared allocation closure, but never serialize it or retain it in a durable or reusable preparation record. After the attempt closes, the callback rejects retained work. Teardown keeps its existing cleanup authority and must still settle an owned lease when the requesting run has ended.
The legacy optional parameter shape remains source-compatible until the next declared breaking Plugin SDK revision. It is not a capability-free runtime path: current hosts supply this assertion, and bundled providers reject missing allocation authority before performing work. An older host must be updated to use these providers.
Other top-level api fields
Beyond api.runtime, the API object also provides:
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.
- Config loading and writes
- Reusable runtime utilities
- Stage timing diagnostics
- Plugin command runtime helpers
- Gateway service events
api.runtime.agentapi.runtime.agent.defaultsapi.runtime.llmapi.runtime.gatewayapi.runtime.hooksapi.runtime.subagentapi.runtime.sandboxapi.runtime.nodesapi.runtime.tasksapi.runtime.ttsapi.runtime.mediaUnderstandingapi.runtime.imageGenerationapi.runtime.videoGenerationapi.runtime.musicGenerationapi.runtime.webSearchapi.runtime.mediaapi.runtime.configapi.runtime.systemapi.runtime.eventsapi.runtime.loggingapi.runtime.modelConfigapi.runtime.modelAuthapi.runtime.stateapi.runtime.channel
Related
- Plugin internals — capability model and registry
- SDK entry points —
definePluginEntryoptions - SDK overview — subpath reference
Decision model runtime
api.runtime.decisions is a closure-bound optional capability for small typed
Choice, ordered Score, and Boolean-probability batches. Retained handles reject
after consumer retirement. See decision models
for provider selection, lifecycle, failure handling, limits, and diagnostics.