mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-23 16:01:17 +00:00
5.1 KiB
5.1 KiB
title, sidebarTitle, summary, read_when
| title | sidebarTitle | summary | read_when | |||
|---|---|---|---|---|---|---|
| Plugin Runtime | Runtime | How `api.runtime` works, when to use it, and how to manage plugin runtime state safely |
|
Plugin Runtime
Native OpenClaw plugins receive a trusted runtime through api.runtime.
Use it for host-owned operations that should stay inside OpenClaw’s runtime:
- reading and writing config
- agent/session helpers
- system commands with OpenClaw timeouts
- media, speech, image-generation, and web-search runtime calls
- channel-owned helpers for bundled channel plugins
When to use runtime vs focused SDK helpers
- Use focused SDK helpers when a public subpath already models the job.
- Use
api.runtime.*when the host owns the operation or state. - Prefer hooks for loose integrations that do not need tight in-process access.
Runtime namespaces
| Namespace | What it covers |
|---|---|
api.runtime.config |
Load and persist OpenClaw config |
api.runtime.agent |
Agent workspace, identity, timeouts, session store |
api.runtime.system |
System events, heartbeats, command execution |
api.runtime.media |
File/media loading and transforms |
api.runtime.tts |
Speech synthesis and voice listing |
api.runtime.mediaUnderstanding |
Image/audio/video understanding |
api.runtime.imageGeneration |
Image generation providers |
api.runtime.webSearch |
Runtime web-search execution |
api.runtime.modelAuth |
Resolve model/provider credentials |
api.runtime.subagent |
Spawn, wait, inspect, and delete subagent sessions |
api.runtime.channel |
Channel-heavy helpers for native channel plugins |
Example: read and persist config
import { definePluginEntry, type OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry";
export default definePluginEntry({
id: "talk-settings",
name: "Talk Settings",
description: "Example runtime config write",
register(api: OpenClawPluginApi) {
api.registerCommand({
name: "talk-mode",
description: "Enable talk mode",
handler: async () => {
const cfg = api.runtime.config.loadConfig();
const nextConfig = {
...cfg,
talk: {
...cfg.talk,
enabled: true,
},
};
await api.runtime.config.writeConfigFile(nextConfig);
return { text: "talk mode enabled" };
},
});
},
});
Example: use a runtime service owned by OpenClaw
const cfg = api.runtime.config.loadConfig();
const voices = await api.runtime.tts.listVoices({
provider: "openai",
cfg,
});
return {
text: voices.map((voice) => `${voice.name ?? voice.id}: ${voice.id}`).join("\n"),
};
createPluginRuntimeStore(...)
Plugin modules often need a small mutable slot for runtime-backed helpers. Use
plugin-sdk/runtime-store instead of an unguarded let runtime.
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core";
import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
import { channelPlugin } from "./src/channel.js";
const runtimeStore = createPluginRuntimeStore<{
logger: { info(message: string): void };
}>("Example Channel runtime not initialized");
export function setExampleRuntime(runtime: { logger: { info(message: string): void } }) {
runtimeStore.setRuntime(runtime);
}
export function getExampleRuntime() {
return runtimeStore.getRuntime();
}
export default defineChannelPluginEntry({
id: "example-channel",
name: "Example Channel",
description: "Example runtime store usage",
plugin: channelPlugin,
setRuntime: setExampleRuntime,
});
createPluginRuntimeStore(...) gives you:
setRuntime(next)clearRuntime()tryGetRuntime()getRuntime()
getRuntime() throws with your custom message if the runtime was never set.
Channel runtime note
api.runtime.channel.* is the heaviest namespace. It exists for native channel
plugins that need tight coupling with the OpenClaw messaging stack.
Prefer narrower subpaths such as:
plugin-sdk/channel-pairingplugin-sdk/channel-actionsplugin-sdk/channel-feedbackplugin-sdk/channel-lifecycle
Use api.runtime.channel.* when the operation is clearly host-owned and there
is no smaller public seam.
Runtime safety guidelines
- Do not cache config snapshots longer than needed.
- Prefer
createPluginRuntimeStore(...)for shared module state. - Keep runtime-backed code behind small local helpers.
- Avoid reaching into runtime namespaces you do not need.