Plugin Runtime Helpers
Plugin Runtime Helpers
Section titled “Plugin Runtime Helpers”Reference for the api.runtime object injected into every plugin during
registration. Use these helpers instead of importing host internals directly.
register(api) { const runtime = api.runtime;}Runtime namespaces
Section titled “Runtime namespaces”api.runtime.agent
Section titled “api.runtime.agent”Agent identity, directories, and session management.
// Resolve the agent's working directoryconst agentDir = api.runtime.agent.resolveAgentDir(cfg);
// Resolve agent workspaceconst workspaceDir = api.runtime.agent.resolveAgentWorkspaceDir(cfg);
// Get agent identityconst identity = api.runtime.agent.resolveAgentIdentity(cfg);
// Get default thinking levelconst thinking = api.runtime.agent.resolveThinkingDefault(cfg, provider, model);
// Get agent timeoutconst timeoutMs = api.runtime.agent.resolveAgentTimeoutMs(cfg);
// Ensure workspace existsawait api.runtime.agent.ensureAgentWorkspace(cfg);
// Run an embedded Pi agentconst agentDir = api.runtime.agent.resolveAgentDir(cfg);const result = await api.runtime.agent.runEmbeddedPiAgent({ sessionId: "my-plugin:task-1", runId: crypto.randomUUID(), sessionFile: path.join(agentDir, "sessions", "my-plugin-task-1.jsonl"), workspaceDir: api.runtime.agent.resolveAgentWorkspaceDir(cfg), prompt: "Summarize the latest changes", timeoutMs: api.runtime.agent.resolveAgentTimeoutMs(cfg),});Session store helpers are under api.runtime.agent.session:
const storePath = api.runtime.agent.session.resolveStorePath(cfg);const store = api.runtime.agent.session.loadSessionStore(cfg);await api.runtime.agent.session.saveSessionStore(cfg, store);const filePath = api.runtime.agent.session.resolveSessionFilePath(cfg, sessionId);api.runtime.agent.defaults
Section titled “api.runtime.agent.defaults”Default model and provider constants:
const model = api.runtime.agent.defaults.model; // e.g. "anthropic/claude-sonnet-4-6"const provider = api.runtime.agent.defaults.provider; // e.g. "anthropic"api.runtime.subagent
Section titled “api.runtime.subagent”Launch and manage background subagent runs.
// Start a subagent runconst { runId } = await api.runtime.subagent.run({ sessionKey: "agent:main:subagent:search-helper", message: "Expand this query into focused follow-up searches.", provider: "openai", // optional override model: "gpt-4.1-mini", // optional override deliver: false,});
// Wait for completionconst result = await api.runtime.subagent.waitForRun({ runId, timeoutMs: 30000 });
// Read session messagesconst { messages } = await api.runtime.subagent.getSessionMessages({ sessionKey: "agent:main:subagent:search-helper", limit: 10,});
// Delete a sessionawait api.runtime.subagent.deleteSession({ sessionKey: "agent:main:subagent:search-helper",});api.runtime.taskFlow
Section titled “api.runtime.taskFlow”Bind a Task Flow runtime to an existing OpenClaw session key or trusted tool context, then create and manage Task Flows without passing an owner on every call.
const taskFlow = api.runtime.taskFlow.fromToolContext(ctx);
const created = taskFlow.createManaged({ controllerId: "my-plugin/review-batch", goal: "Review new pull requests",});
const child = taskFlow.runTask({ flowId: created.flowId, runtime: "acp", childSessionKey: "agent:main:subagent:reviewer", task: "Review PR #123", status: "running", startedAt: Date.now(),});
const waiting = taskFlow.setWaiting({ flowId: created.flowId, expectedRevision: created.revision, currentStep: "await-human-reply", waitJson: { kind: "reply", channel: "telegram" },});Use bindSession({ sessionKey, requesterOrigin }) when you already have a
trusted OpenClaw session key from your own binding layer. Do not bind from raw
user input.
api.runtime.tts
Section titled “api.runtime.tts”Text-to-speech synthesis.
// Standard TTSconst clip = await api.runtime.tts.textToSpeech({ text: "Hello from OpenClaw", cfg: api.config,});
// Telephony-optimized TTSconst telephonyClip = await api.runtime.tts.textToSpeechTelephony({ text: "Hello from OpenClaw", cfg: api.config,});
// List available voicesconst voices = await api.runtime.tts.listVoices({ provider: "elevenlabs", cfg: api.config,});Uses core messages.tts configuration and provider selection. Returns PCM audio
buffer + sample rate.
api.runtime.mediaUnderstanding
Section titled “api.runtime.mediaUnderstanding”Image, audio, and video analysis.
// Describe an imageconst image = await api.runtime.mediaUnderstanding.describeImageFile({ filePath: "/tmp/inbound-photo.jpg", cfg: api.config, agentDir: "/tmp/agent",});
// Transcribe audioconst { text } = await api.runtime.mediaUnderstanding.transcribeAudioFile({ filePath: "/tmp/inbound-audio.ogg", cfg: api.config, mime: "audio/ogg", // optional, for when MIME cannot be inferred});
// Describe a videoconst video = await api.runtime.mediaUnderstanding.describeVideoFile({ filePath: "/tmp/inbound-video.mp4", cfg: api.config,});
// Generic file analysisconst result = await api.runtime.mediaUnderstanding.runFile({ filePath: "/tmp/inbound-file.pdf", cfg: api.config,});Returns { text: undefined } when no output is produced (e.g. skipped input).
api.runtime.imageGeneration
Section titled “api.runtime.imageGeneration”Image generation.
const result = await api.runtime.imageGeneration.generate({ prompt: "A robot painting a sunset", cfg: api.config,});
const providers = api.runtime.imageGeneration.listProviders({ cfg: api.config });api.runtime.webSearch
Section titled “api.runtime.webSearch”Web search.
const providers = api.runtime.webSearch.listProviders({ config: api.config });
const result = await api.runtime.webSearch.search({ config: api.config, args: { query: "OpenClaw plugin SDK", count: 5 },});api.runtime.media
Section titled “api.runtime.media”Low-level media utilities.
const webMedia = await api.runtime.media.loadWebMedia(url);const mime = await api.runtime.media.detectMime(buffer);const kind = api.runtime.media.mediaKindFromMime("image/jpeg"); // "image"const isVoice = api.runtime.media.isVoiceCompatibleAudio(filePath);const metadata = await api.runtime.media.getImageMetadata(filePath);const resized = await api.runtime.media.resizeToJpeg(buffer, { maxWidth: 800 });api.runtime.config
Section titled “api.runtime.config”Config load and write.
const cfg = await api.runtime.config.loadConfig();await api.runtime.config.writeConfigFile(cfg);api.runtime.system
Section titled “api.runtime.system”System-level utilities.
await api.runtime.system.enqueueSystemEvent(event);api.runtime.system.requestHeartbeatNow();const output = await api.runtime.system.runCommandWithTimeout(cmd, args, opts);const hint = api.runtime.system.formatNativeDependencyHint(pkg);api.runtime.events
Section titled “api.runtime.events”Event subscriptions.
api.runtime.events.onAgentEvent((event) => { /* ... */});api.runtime.events.onSessionTranscriptUpdate((update) => { /* ... */});api.runtime.logging
Section titled “api.runtime.logging”Logging.
const verbose = api.runtime.logging.shouldLogVerbose();const childLogger = api.runtime.logging.getChildLogger({ plugin: "my-plugin" }, { level: "debug" });api.runtime.modelAuth
Section titled “api.runtime.modelAuth”Model and provider auth resolution.
const auth = await api.runtime.modelAuth.getApiKeyForModel({ model, cfg });const providerAuth = await api.runtime.modelAuth.resolveApiKeyForProvider({ provider: "openai", cfg,});api.runtime.state
Section titled “api.runtime.state”State directory resolution.
const stateDir = api.runtime.state.resolveStateDir();api.runtime.tools
Section titled “api.runtime.tools”Memory tool factories and CLI.
const getTool = api.runtime.tools.createMemoryGetTool(/* ... */);const searchTool = api.runtime.tools.createMemorySearchTool(/* ... */);api.runtime.tools.registerMemoryCli(/* ... */);api.runtime.channel
Section titled “api.runtime.channel”Channel-specific runtime helpers (available when a channel plugin is loaded).
Storing runtime references
Section titled “Storing runtime references”Use createPluginRuntimeStore to store the runtime reference for use outside
the register callback:
import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";import type { PluginRuntime } from "openclaw/plugin-sdk/runtime-store";
const store = createPluginRuntimeStore<PluginRuntime>("my-plugin runtime not initialized");
// In your entry pointexport default defineChannelPluginEntry({ id: "my-plugin", name: "My Plugin", description: "Example", plugin: myPlugin, setRuntime: store.setRuntime,});
// In other filesexport function getRuntime() { return store.getRuntime(); // throws if not initialized}
export function tryGetRuntime() { return store.tryGetRuntime(); // returns null if not initialized}Other top-level api fields
Section titled “Other top-level api fields”Beyond api.runtime, the API object also provides:
| Field | Type | Description |
|---|---|---|
api.id | string | Plugin id |
api.name | string | Plugin display name |
api.config | OpenClawConfig | Current config snapshot |
api.pluginConfig | Record<string, unknown> | Plugin-specific config from plugins.entries.<id>.config |
api.logger | PluginLogger | Scoped logger (debug, info, warn, error) |
api.registrationMode | PluginRegistrationMode | "full", "setup-only", "setup-runtime", or "cli-metadata" |
api.resolvePath(input) | (string) => string | Resolve a path relative to the plugin root |
Related
Section titled “Related”- SDK Overview — subpath reference
- SDK Entry Points —
definePluginEntryoptions - Plugin Internals — capability model and registry