Plugins
Funciones auxiliares de tiempo de ejecución de Plugin
Referencia del objeto api.runtime inyectado en cada plugin durante el registro. Usa estos helpers en lugar de importar directamente elementos internos del host.
Guía paso a paso que usa estos helpers en contexto para plugins de canal.
Guía paso a paso que usa estos helpers en contexto para plugins de proveedor.
register(api) {
const runtime = api.runtime;
}
Carga y escritura de configuración
Prefiere la configuración que ya se pasó a la ruta de llamada activa, por ejemplo api.config durante el registro o un argumento cfg en callbacks de canal/proveedor. Esto mantiene una instantánea de proceso fluyendo por el trabajo en lugar de volver a analizar la configuración en rutas críticas.
Usa api.runtime.config.current() solo cuando un manejador de larga duración necesite la instantánea actual del proceso y no se haya pasado ninguna configuración a esa función. El valor devuelto es de solo lectura; clónalo o usa un helper de mutación antes de editarlo.
Las fábricas de herramientas reciben ctx.runtimeConfig más ctx.getRuntimeConfig(). Usa el getter dentro del callback execute de una herramienta de larga duración cuando la configuración pueda cambiar después de crear la definición de la herramienta.
Persiste los cambios con api.runtime.config.mutateConfigFile(...) o api.runtime.config.replaceConfigFile(...). Cada escritura debe elegir una política afterWrite explícita:
afterWrite: { mode: "auto" }deja que el planificador de recarga del Gateway decida.afterWrite: { mode: "restart", reason: "..." }fuerza un reinicio limpio cuando el escritor sabe que la recarga en caliente no es segura.afterWrite: { mode: "none", reason: "..." }suprime la recarga/reinicio automático solo cuando el llamador se hace cargo del seguimiento.
Los helpers de mutación devuelven afterWrite más un resumen tipado followUp para que los llamadores puedan registrar o probar si solicitaron un reinicio. El Gateway sigue siendo quien decide cuándo ocurre realmente ese reinicio.
api.runtime.config.loadConfig() y api.runtime.config.writeConfigFile(...) son helpers de compatibilidad obsoletos bajo runtime-config-load-write. Avisan una vez en tiempo de ejecución y siguen disponibles para plugins externos antiguos durante la ventana de migración. Los plugins incluidos no deben usarlos; las protecciones del límite de configuración fallan si el código del plugin los llama o importa esos helpers desde subrutas del SDK de plugins.
Para importaciones directas del SDK, usa las subrutas de configuración enfocadas en lugar del barrel de compatibilidad amplio
openclaw/plugin-sdk/config-runtime: config-types para
tipos, plugin-config-runtime para aserciones de configuración ya cargada y búsqueda de
entradas de plugin, runtime-config-snapshot para instantáneas actuales del proceso, y
config-mutation para escrituras. Las pruebas de plugins incluidos deben simular estas subrutas enfocadas
directamente en lugar de simular el barrel de compatibilidad amplio.
El código interno de runtime de OpenClaw sigue la misma dirección: carga la configuración una vez en el límite de la CLI, el Gateway o el proceso, y luego pasa ese valor por la ruta. Las escrituras de mutación correctas actualizan la instantánea de runtime del proceso y avanzan su revisión interna; las cachés de larga duración deben basarse en la clave de caché propiedad del runtime en lugar de serializar la configuración localmente. Los módulos de runtime de larga duración tienen un escáner de tolerancia cero para llamadas ambientales a loadConfig(); usa un cfg pasado, un context.getRuntimeConfig() de solicitud o getRuntimeConfig() en un límite de proceso explícito.
Las rutas de ejecución de proveedores y canales deben usar la instantánea de configuración de runtime activa, no una instantánea de archivo devuelta para lectura o edición de configuración. Las instantáneas de archivo conservan valores de origen como marcadores SecretRef para la UI y escrituras; los callbacks de proveedores necesitan la vista de runtime resuelta. Cuando un helper pueda llamarse con la instantánea de origen activa o la instantánea de runtime activa, enruta a través de selectApplicableRuntimeConfig() antes de leer credenciales.
Espacios de nombres de runtime
api.runtime.agent
Identidad del agente, directorios y gestión de sesiones.
// Resolve the agent's working directory
const agentDir = api.runtime.agent.resolveAgentDir(cfg);
// Resolve agent workspace
const workspaceDir = api.runtime.agent.resolveAgentWorkspaceDir(cfg);
// Get agent identity
const identity = api.runtime.agent.resolveAgentIdentity(cfg);
// Get default thinking level
const thinking = api.runtime.agent.resolveThinkingDefault({
cfg,
provider,
model,
});
// Validate a user-provided thinking level against the active provider profile
const policy = api.runtime.agent.resolveThinkingPolicy({ provider, model });
const level = api.runtime.agent.normalizeThinkingLevel("extra high");
if (level && policy.levels.some((entry) => entry.id === level)) {
// pass level to an embedded run
}
// Get agent timeout
const timeoutMs = api.runtime.agent.resolveAgentTimeoutMs(cfg);
// Ensure workspace exists
await api.runtime.agent.ensureAgentWorkspace(cfg);
// Run an embedded agent turn
const agentDir = api.runtime.agent.resolveAgentDir(cfg);
const result = await api.runtime.agent.runEmbeddedAgent({
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),
});
runEmbeddedAgent(...) es el helper neutral para iniciar un turno normal de agente de OpenClaw desde código de plugin. Usa la misma resolución de proveedor/modelo y selección de arnés de agente que las respuestas activadas por canales.
runEmbeddedPiAgent(...) se mantiene como alias de compatibilidad.
resolveThinkingPolicy(...) devuelve los niveles de razonamiento admitidos por el proveedor/modelo y un valor predeterminado opcional. Los plugins de proveedor son propietarios del perfil específico del modelo mediante sus hooks de razonamiento, así que los plugins de herramientas deben llamar a este helper de runtime en lugar de importar o duplicar listas de proveedores.
normalizeThinkingLevel(...) convierte texto de usuario como on, x-high o extra high al nivel almacenado canónico antes de comprobarlo contra la política resuelta.
Los helpers del almacén de sesiones están bajo api.runtime.agent.session:
const storePath = api.runtime.agent.session.resolveStorePath(cfg);
const store = api.runtime.agent.session.loadSessionStore(storePath);
await api.runtime.agent.session.updateSessionStore(storePath, (nextStore) => {
// Patch one entry without replacing the whole file from stale state.
nextStore[sessionKey] = { ...nextStore[sessionKey], thinkingLevel: "high" };
});
const filePath = api.runtime.agent.session.resolveSessionFilePath(cfg, sessionId);
Prefiere updateSessionStore(...) o updateSessionStoreEntry(...) para escrituras de runtime. Enrutan a través del escritor del almacén de sesiones propiedad del Gateway, conservan actualizaciones concurrentes y reutilizan la caché en caliente. saveSessionStore(...) sigue disponible por compatibilidad y para reescrituras de mantenimiento sin conexión.
api.runtime.agent.defaults
Constantes predeterminadas de modelo y proveedor:
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
Lanza y gestiona ejecuciones de subagentes en segundo plano.
// Start a subagent run
const { 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 completion
const result = await api.runtime.subagent.waitForRun({ runId, timeoutMs: 30000 });
// Read session messages
const { messages } = await api.runtime.subagent.getSessionMessages({
sessionKey: "agent:main:subagent:search-helper",
limit: 10,
});
// Delete a session
await api.runtime.subagent.deleteSession({
sessionKey: "agent:main:subagent:search-helper",
});
deleteSession(...) puede eliminar sesiones creadas por el mismo plugin mediante api.runtime.subagent.run(...). Eliminar sesiones arbitrarias de usuario u operador aún requiere una solicitud de Gateway con alcance de administrador.
api.runtime.nodes
Lista nodos conectados e invoca un comando alojado en un nodo desde código de plugin cargado por el Gateway o desde comandos de CLI de plugin. Usa esto cuando un plugin sea propietario de trabajo local en un dispositivo emparejado, por ejemplo un puente de navegador o audio en otro Mac.
const { nodes } = await api.runtime.nodes.list({ connected: true });
const result = await api.runtime.nodes.invoke({
nodeId: "mac-studio",
command: "my-plugin.command",
params: { action: "start" },
timeoutMs: 30000,
});
Dentro del Gateway, este runtime está en proceso. En comandos de CLI de plugin, llama al Gateway configurado por RPC, así que comandos como openclaw googlemeet recover-tab pueden inspeccionar nodos emparejados desde la terminal. Los comandos de Node siguen pasando por el emparejamiento normal de nodos del Gateway, listas de comandos permitidos, políticas de invocación de nodos de plugins y manejo de comandos local del nodo.
Los plugins que expongan comandos peligrosos alojados en nodos deben registrar una política de invocación de nodos con api.registerNodeInvokePolicy(...). La política se ejecuta en el Gateway después de las comprobaciones de listas de comandos permitidos y antes de reenviar el comando al nodo, así que las llamadas directas a node.invoke y las herramientas de plugin de nivel superior comparten la misma ruta de cumplimiento.
api.runtime.tasks.managedFlows
Vincula un runtime de TaskFlow a una clave de sesión existente de OpenClaw o a un contexto de herramienta confiable, y luego crea y gestiona TaskFlows sin pasar un propietario en cada llamada.
const taskFlow = api.runtime.tasks.managedFlows.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" },
});
Usa bindSession({ sessionKey, requesterOrigin }) cuando ya tengas una clave de sesión confiable de OpenClaw desde tu propia capa de vinculación. No vincules desde entrada de usuario sin procesar.
api.runtime.tts
Síntesis de texto a voz.
// Standard TTS
const clip = await api.runtime.tts.textToSpeech({
text: "Hello from OpenClaw",
cfg: api.config,
});
// Telephony-optimized TTS
const telephonyClip = await api.runtime.tts.textToSpeechTelephony({
text: "Hello from OpenClaw",
cfg: api.config,
});
// List available voices
const voices = await api.runtime.tts.listVoices({
provider: "elevenlabs",
cfg: api.config,
});
Usa la configuración central messages.tts y la selección de proveedor. Devuelve búfer de audio PCM + frecuencia de muestreo.
api.runtime.mediaUnderstanding
Análisis de imágenes, audio y video.
// Describe an image
const image = await api.runtime.mediaUnderstanding.describeImageFile({
filePath: "/tmp/inbound-photo.jpg",
cfg: api.config,
agentDir: "/tmp/agent",
});
// Transcribe audio
const { 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 video
const video = await api.runtime.mediaUnderstanding.describeVideoFile({
filePath: "/tmp/inbound-video.mp4",
cfg: api.config,
});
// Generic file analysis
const result = await api.runtime.mediaUnderstanding.runFile({
filePath: "/tmp/inbound-file.pdf",
cfg: api.config,
});
Devuelve { text: undefined } cuando no se produce ninguna salida (por ejemplo, entrada omitida).
api.runtime.imageGeneration
Generación de imágenes.
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
Búsqueda web.
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
Utilidades multimedia de bajo nivel.
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 });
const terminalQr = await api.runtime.media.renderQrTerminal("https://openclaw.ai");
const pngQr = await api.runtime.media.renderQrPngBase64("https://openclaw.ai", {
scale: 6, // 1-12
marginModules: 4, // 0-16
});
const pngQrDataUrl = await api.runtime.media.renderQrPngDataUrl("https://openclaw.ai");
const tmpRoot = resolvePreferredOpenClawTmpDir();
const pngQrFile = await api.runtime.media.writeQrPngTempFile("https://openclaw.ai", {
tmpRoot,
dirPrefix: "my-plugin-qr-",
fileName: "qr.png",
});
api.runtime.config
Instantánea de la configuración actual del runtime y escrituras transaccionales de configuración. Prefiere
la configuración que ya se pasó a la ruta de llamada activa; usa
current() solo cuando el manejador necesite directamente la instantánea del proceso.
const cfg = api.runtime.config.current();
await api.runtime.config.mutateConfigFile({
afterWrite: { mode: "auto" },
mutate(draft) {
draft.plugins ??= {};
},
});
mutateConfigFile(...) y replaceConfigFile(...) devuelven un valor followUp,
por ejemplo { mode: "restart", requiresRestart: true, reason },
que registra la intención del escritor sin quitarle al Gateway el control del reinicio.
api.runtime.system
Utilidades de nivel de sistema.
await api.runtime.system.enqueueSystemEvent(event);
api.runtime.system.requestHeartbeat({
source: "other",
intent: "event",
reason: "plugin-event",
});
api.runtime.system.requestHeartbeatNow({ reason: "plugin-event" }); // Deprecated compatibility alias.
const output = await api.runtime.system.runCommandWithTimeout(cmd, args, opts);
const hint = api.runtime.system.formatNativeDependencyHint(pkg);
api.runtime.events
Suscripciones a eventos.
api.runtime.events.onAgentEvent((event) => {
/* ... */
});
api.runtime.events.onSessionTranscriptUpdate((update) => {
/* ... */
});
api.runtime.logging
Registro.
const verbose = api.runtime.logging.shouldLogVerbose();
const childLogger = api.runtime.logging.getChildLogger({ plugin: "my-plugin" }, { level: "debug" });
api.runtime.modelAuth
Resolución de autenticación de modelos y proveedores.
const auth = await api.runtime.modelAuth.getApiKeyForModel({ model, cfg });
const providerAuth = await api.runtime.modelAuth.resolveApiKeyForProvider({
provider: "openai",
cfg,
});
api.runtime.state
Resolución del directorio de estado y almacenamiento con claves respaldado por SQLite.
const stateDir = api.runtime.state.resolveStateDir(process.env);
const store = api.runtime.state.openKeyedStore<MyRecord>({
namespace: "my-feature",
maxEntries: 200,
defaultTtlMs: 15 * 60_000,
});
await store.register("key-1", { value: "hello" });
const claimed = await store.registerIfAbsent("dedupe-key", { value: "first" });
const value = await store.lookup("key-1");
await store.consume("key-1");
await store.clear();
Los almacenes con claves sobreviven a los reinicios y se aíslan mediante el id de plugin vinculado al runtime. Usa registerIfAbsent(...) para reclamaciones atómicas de deduplicación: devuelve true cuando la clave faltaba o había expirado y se registró, o false cuando ya existe un valor activo sin sobrescribir su valor, hora de creación ni TTL. Límites: maxEntries por espacio de nombres, 1,000 filas activas por plugin, valores JSON de menos de 64 KB y expiración TTL opcional.
api.runtime.tools
Fábricas de herramientas de memoria y CLI.
const getTool = api.runtime.tools.createMemoryGetTool(/* ... */);
const searchTool = api.runtime.tools.createMemorySearchTool(/* ... */);
api.runtime.tools.registerMemoryCli(/* ... */);
api.runtime.channel
Ayudantes de runtime específicos del canal (disponibles cuando se carga un plugin de canal).
api.runtime.channel.mentions es la superficie compartida de política de menciones entrantes para plugins de canal incluidos que usan inyección de runtime:
const mentionMatch = api.runtime.channel.mentions.matchesMentionWithExplicit(text, {
mentionRegexes,
mentionPatterns,
});
const decision = api.runtime.channel.mentions.resolveInboundMentionDecision({
facts: {
canDetectMention: true,
wasMentioned: mentionMatch.matched,
implicitMentionKinds: api.runtime.channel.mentions.implicitMentionKindWhen(
"reply_to_bot",
isReplyToBot,
),
},
policy: {
isGroup,
requireMention,
allowTextCommands,
hasControlCommand,
commandAuthorized,
},
});
Ayudantes de menciones disponibles:
buildMentionRegexesmatchesMentionPatternsmatchesMentionWithExplicitimplicitMentionKindWhenresolveInboundMentionDecision
api.runtime.channel.mentions no expone intencionalmente los ayudantes de compatibilidad antiguos resolveMentionGating*. Prefiere la ruta normalizada { facts, policy }.
Almacenar referencias de runtime
Usa createPluginRuntimeStore para almacenar la referencia de runtime y utilizarla fuera del callback register:
Crear el almacén
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",
});
Conectar al punto de entrada
export default defineChannelPluginEntry({
id: "my-plugin",
name: "My Plugin",
description: "Example",
plugin: myPlugin,
setRuntime: store.setRuntime,
});
Acceder desde otros archivos
export function getRuntime() {
return store.getRuntime(); // throws if not initialized
}
export function tryGetRuntime() {
return store.tryGetRuntime(); // returns null if not initialized
}
Otros campos api de nivel superior
Más allá de api.runtime, el objeto de API también proporciona:
api.idstringId del plugin.
api.namestringNombre visible del plugin.
api.configOpenClawConfigInstantánea de configuración actual (instantánea activa del runtime en memoria cuando está disponible).
OPENCLAW_DOCS_MARKER:paramOpen:IHBhdGg9ImFwaS5wbHVnaW5Db25maWciIHR5cGU9IlJlY29yZDxzdHJpbmcsIHVua25vd24
">
Configuración específica del plugin desde plugins.entries.<id>.config.
api.loggerPluginLoggerLogger con ámbito (debug, info, warn, error).
api.registrationModePluginRegistrationModeModo de carga actual; "setup-runtime" es la ventana ligera de inicio/configuración previa a la entrada completa.
api.resolvePath(input)(string) =,�������Qz˞�����ޕ�b���j��u�i��Relacionado
- Aspectos internos del plugin — modelo de capacidades y registro
- Puntos de entrada del SDK — opciones de
definePluginEntry - Descripción general del SDK — referencia de subrutas