openclaw/docs/plugins/sdk-overview.md

30 KiB

title sidebarTitle summary read_when
Plugin SDK Overview SDK Overview Import map, registration API reference, and SDK architecture
You need to know which SDK subpath to import from
You want a reference for all registration methods on OpenClawPluginApi
You are looking up a specific SDK export

Plugin SDK Overview

The plugin SDK is the typed contract between plugins and core. This page is the reference for what to import and what you can register.

**Looking for a how-to guide?** - First plugin? Start with [Getting Started](/plugins/building-plugins) - Channel plugin? See [Channel Plugins](/plugins/sdk-channel-plugins) - Provider plugin? See [Provider Plugins](/plugins/sdk-provider-plugins)

Import convention

Always import from a specific subpath:

import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";

Each subpath is a small, self-contained module. This keeps startup fast and prevents circular dependency issues. For channel-specific entry/build helpers, prefer openclaw/plugin-sdk/channel-core; keep openclaw/plugin-sdk/core for the broader umbrella surface and shared helpers such as buildChannelConfigSchema.

Do not add or depend on provider-named convenience seams such as openclaw/plugin-sdk/slack, openclaw/plugin-sdk/discord, openclaw/plugin-sdk/signal, or openclaw/plugin-sdk/whatsapp. Bundled plugins should compose generic SDK subpaths inside their own api.ts or runtime-api.ts barrels, and core should either use those plugin-local barrels or add a narrow generic SDK contract when the need is truly cross-channel.

The generated export map still contains a small set of bundled-plugin helper seams such as plugin-sdk/feishu, plugin-sdk/feishu-setup, plugin-sdk/zalo, plugin-sdk/zalo-setup, and plugin-sdk/matrix*. Those subpaths exist for bundled-plugin maintenance and compatibility only; they are intentionally omitted from the common table below and are not the recommended import path for new third-party plugins.

Subpath reference

The most commonly used subpaths, grouped by purpose. The generated full list of 200+ subpaths lives in scripts/lib/plugin-sdk-entrypoints.json.

Reserved bundled-plugin helper subpaths still appear in that generated list. Treat those as implementation detail/compatibility surfaces unless a doc page explicitly promotes one as public.

Plugin entry

Subpath Key exports
plugin-sdk/plugin-entry definePluginEntry
plugin-sdk/core defineChannelPluginEntry, createChatChannelPlugin, createChannelPluginBase, defineSetupPluginEntry, buildChannelConfigSchema
plugin-sdk/provider-entry defineSingleProviderPluginEntry
| Subpath | Key exports | | --- | --- | | `plugin-sdk/channel-core` | `defineChannelPluginEntry`, `defineSetupPluginEntry`, `createChatChannelPlugin`, `createChannelPluginBase` | | `plugin-sdk/channel-setup` | `createOptionalChannelSetupSurface` | | `plugin-sdk/setup` | Shared setup wizard helpers, allowlist prompts, setup status builders | | `plugin-sdk/setup-runtime` | Account-scoped setup runtime helpers, delegated setup proxies, setup status builders | | `plugin-sdk/setup-adapter-runtime` | `createEnvPatchedAccountSetupAdapter` | | `plugin-sdk/setup-tools` | Setup CLI/archive/docs helpers | | `plugin-sdk/account-core` | Multi-account config/action-gate helpers, default-account fallback helpers | | `plugin-sdk/account-id` | `DEFAULT_ACCOUNT_ID`, account-id normalization helpers | | `plugin-sdk/account-resolution` | Account lookup + default-fallback helpers | | `plugin-sdk/account-helpers` | Narrow account-list/account-action helpers | | `plugin-sdk/channel-pairing` | `createChannelPairingController` | | `plugin-sdk/channel-reply-pipeline` | `createChannelReplyPipeline` | | `plugin-sdk/channel-config-helpers` | `createHybridChannelConfigAdapter` | | `plugin-sdk/channel-config-schema` | Channel config schema types | | `plugin-sdk/channel-policy` | `resolveChannelGroupRequireMention` | | `plugin-sdk/channel-lifecycle` | `createAccountStatusSink` | | `plugin-sdk/inbound-envelope` | Shared inbound route + envelope builder helpers | | `plugin-sdk/inbound-reply-dispatch` | Shared inbound record-and-dispatch helpers | | `plugin-sdk/messaging-targets` | Target parsing/matching helpers | | `plugin-sdk/outbound-media` | Shared outbound media loading helpers | | `plugin-sdk/outbound-runtime` | Outbound identity/send delegate helpers | | `plugin-sdk/thread-bindings-runtime` | Thread-binding lifecycle and adapter helpers | | `plugin-sdk/agent-media-payload` | Legacy agent media payload builder | | `plugin-sdk/conversation-runtime` | Conversation/thread binding, pairing, and configured-binding helpers | | `plugin-sdk/runtime-config-snapshot` | Runtime config snapshot helper | | `plugin-sdk/runtime-group-policy` | Runtime group-policy resolution helpers | | `plugin-sdk/channel-status` | Shared channel status snapshot/summary helpers | | `plugin-sdk/channel-config-primitives` | Narrow channel config-schema primitives | | `plugin-sdk/channel-config-writes` | Channel config-write authorization helpers | | `plugin-sdk/channel-plugin-common` | Shared channel plugin prelude exports | | `plugin-sdk/allowlist-config-edit` | Allowlist config edit/read helpers | | `plugin-sdk/group-access` | Shared group-access decision helpers | | `plugin-sdk/direct-dm` | Shared direct-DM auth/guard helpers | | `plugin-sdk/interactive-runtime` | Interactive reply payload normalization/reduction helpers | | `plugin-sdk/channel-inbound` | Debounce, mention matching, envelope helpers | | `plugin-sdk/channel-send-result` | Reply result types | | `plugin-sdk/channel-actions` | `createMessageToolButtonsSchema`, `createMessageToolCardSchema` | | `plugin-sdk/channel-targets` | Target parsing/matching helpers | | `plugin-sdk/channel-contract` | Channel contract types | | `plugin-sdk/channel-feedback` | Feedback/reaction wiring | | Subpath | Key exports | | --- | --- | | `plugin-sdk/provider-entry` | `defineSingleProviderPluginEntry` | | `plugin-sdk/provider-setup` | Curated local/self-hosted provider setup helpers | | `plugin-sdk/self-hosted-provider-setup` | Focused OpenAI-compatible self-hosted provider setup helpers | | `plugin-sdk/cli-backend` | CLI backend defaults + watchdog constants | | `plugin-sdk/provider-auth-runtime` | Runtime API-key resolution helpers for provider plugins | | `plugin-sdk/provider-auth-api-key` | API-key onboarding/profile-write helpers | | `plugin-sdk/provider-auth-result` | Standard OAuth auth-result builder | | `plugin-sdk/provider-auth-login` | Shared interactive login helpers for provider plugins | | `plugin-sdk/provider-env-vars` | Provider auth env-var lookup helpers | | `plugin-sdk/provider-auth` | `createProviderApiKeyAuthMethod`, `ensureApiKeyFromOptionEnvOrPrompt`, `upsertAuthProfile` | | `plugin-sdk/provider-model-shared` | `normalizeModelCompat`, `buildProviderReplayFamilyHooks`, `sanitizeGoogleGeminiReplayHistory`, `resolveTaggedReasoningOutputMode` | | `plugin-sdk/provider-catalog-shared` | `findCatalogTemplate`, `buildSingleProviderApiKeyCatalog`, `supportsNativeStreamingUsageCompat`, `applyProviderNativeStreamingUsageCompat` | | `plugin-sdk/provider-http` | Generic provider HTTP/endpoint capability helpers | | `plugin-sdk/provider-web-fetch` | Web-fetch provider registration/cache helpers | | `plugin-sdk/provider-web-search` | Web-search provider registration/cache/config helpers | | `plugin-sdk/provider-tools` | `buildProviderToolCompatFamilyHooks`, Gemini schema helpers | | `plugin-sdk/provider-usage` | `fetchClaudeUsage` and similar | | `plugin-sdk/provider-stream` | `buildProviderStreamFamilyHooks`, stream wrapper types, provider stream wrappers, shared OpenAI/OpenRouter stream-family helpers | | `plugin-sdk/provider-onboard` | Onboarding config patch helpers | | `plugin-sdk/global-singleton` | Process-local singleton/map/cache helpers | | Subpath | Key exports | | --- | --- | | `plugin-sdk/command-auth` | `resolveControlCommandGate`, command registry helpers, sender-authorization helpers | | `plugin-sdk/approval-auth-runtime` | Approver resolution and same-chat action-auth helpers | | `plugin-sdk/approval-client-runtime` | Native exec approval profile/filter helpers | | `plugin-sdk/approval-delivery-runtime` | Native approval capability/delivery adapters | | `plugin-sdk/approval-native-runtime` | Native approval target + account-binding helpers | | `plugin-sdk/approval-reply-runtime` | Exec/plugin approval reply payload helpers | | `plugin-sdk/command-auth-native` | Native command auth + native session-target helpers | | `plugin-sdk/command-detection` | Shared command detection helpers | | `plugin-sdk/command-surface` | Command-body normalization and command-surface helpers | | `plugin-sdk/allow-from` | `formatAllowFromLowercase` | | `plugin-sdk/security-runtime` | Shared trust, DM gating, external-content, and secret-collection helpers | | `plugin-sdk/ssrf-policy` | Host allowlist and private-network SSRF policy helpers | | `plugin-sdk/ssrf-runtime` | Pinned-dispatcher, SSRF-guarded fetch, and SSRF policy helpers | | `plugin-sdk/secret-input` | Secret input parsing helpers | | `plugin-sdk/webhook-ingress` | Webhook request/target helpers | | `plugin-sdk/webhook-request-guards` | Request body size/timeout helpers | | Subpath | Key exports | | --- | --- | | `plugin-sdk/runtime` | Broad runtime/logging/backup/plugin-install helpers | | `plugin-sdk/runtime-env` | Narrow runtime env, logger, timeout, retry, and backoff helpers | | `plugin-sdk/runtime-store` | `createPluginRuntimeStore` | | `plugin-sdk/plugin-runtime` | Shared plugin command/hook/http/interactive helpers | | `plugin-sdk/hook-runtime` | Shared webhook/internal hook pipeline helpers | | `plugin-sdk/process-runtime` | Process exec helpers | | `plugin-sdk/cli-runtime` | CLI formatting, wait, and version helpers | | `plugin-sdk/gateway-runtime` | Gateway client and channel-status patch helpers | | `plugin-sdk/config-runtime` | Config load/write helpers | | `plugin-sdk/approval-runtime` | Exec/plugin approval helpers, approval-capability builders, auth/profile helpers, native routing/runtime helpers | | `plugin-sdk/reply-runtime` | Shared inbound/reply runtime helpers, chunking, dispatch, heartbeat, reply planner | | `plugin-sdk/reply-dispatch-runtime` | Narrow reply dispatch/finalize helpers | | `plugin-sdk/reply-reference` | `createReplyReferencePlanner` | | `plugin-sdk/reply-chunking` | Narrow text/markdown chunking helpers | | `plugin-sdk/session-store-runtime` | Session store path + updated-at helpers | | `plugin-sdk/state-paths` | State/OAuth dir path helpers | | `plugin-sdk/target-resolver-runtime` | Shared target resolver helpers | | `plugin-sdk/string-normalization-runtime` | Slug/string normalization helpers | | `plugin-sdk/request-url` | Extract string URLs from fetch/request-like inputs | | `plugin-sdk/run-command` | Timed command runner with normalized stdout/stderr results | | `plugin-sdk/param-readers` | Common tool/CLI param readers | | `plugin-sdk/tool-send` | Extract canonical send target fields from tool args | | `plugin-sdk/temp-path` | Shared temp-download path helpers | | `plugin-sdk/logging-core` | Subsystem logger and redaction helpers | | `plugin-sdk/markdown-table-runtime` | Markdown table mode helpers | | `plugin-sdk/json-store` | Small JSON state read/write helpers | | `plugin-sdk/file-lock` | Re-entrant file-lock helpers | | `plugin-sdk/persistent-dedupe` | Disk-backed dedupe cache helpers | | `plugin-sdk/acp-runtime` | ACP runtime/session helpers | | `plugin-sdk/agent-config-primitives` | Narrow agent runtime config-schema primitives | | `plugin-sdk/boolean-param` | Loose boolean param reader | | `plugin-sdk/dangerous-name-runtime` | Dangerous-name matching resolution helpers | | `plugin-sdk/device-bootstrap` | Device bootstrap and pairing token helpers | | `plugin-sdk/extension-shared` | Shared passive-channel and status helper primitives | | `plugin-sdk/models-provider-runtime` | `/models` command/provider reply helpers | | `plugin-sdk/skill-commands-runtime` | Skill command listing helpers | | `plugin-sdk/native-command-registry` | Native command registry/build/serialize helpers | | `plugin-sdk/provider-zai-endpoint` | Z.AI endpoint detection helpers | | `plugin-sdk/infra-runtime` | System event/heartbeat helpers | | `plugin-sdk/collection-runtime` | Small bounded cache helpers | | `plugin-sdk/diagnostic-runtime` | Diagnostic flag and event helpers | | `plugin-sdk/error-runtime` | Error graph and formatting helpers | | `plugin-sdk/fetch-runtime` | Wrapped fetch, proxy, and pinned lookup helpers | | `plugin-sdk/host-runtime` | Hostname and SCP host normalization helpers | | `plugin-sdk/retry-runtime` | Retry config and retry runner helpers | | `plugin-sdk/agent-runtime` | Agent dir/identity/workspace helpers | | `plugin-sdk/directory-runtime` | Config-backed directory query/dedup | | `plugin-sdk/keyed-async-queue` | `KeyedAsyncQueue` | | Subpath | Key exports | | --- | --- | | `plugin-sdk/media-runtime` | Shared media fetch/transform/store helpers plus media payload builders | | `plugin-sdk/media-understanding-runtime` | Media-understanding runner facade and typed result helpers | | `plugin-sdk/text-runtime` | Shared text, markdown, logging, and formatting helpers | | `plugin-sdk/text-chunking` | Outbound text chunking helper | | `plugin-sdk/speech-runtime` | Speech-core runtime facade for TTS resolution and synthesis | | `plugin-sdk/speech-core` | Shared speech provider types, registry, directive, and normalization helpers | | `plugin-sdk/realtime-transcription` | Realtime transcription provider types and registry helpers | | `plugin-sdk/realtime-voice` | Realtime voice provider types and registry helpers | | `plugin-sdk/image-generation` | Image generation provider types | | `plugin-sdk/image-generation-core` | Shared image-generation types, failover, auth, and registry helpers | | `plugin-sdk/media-understanding` | Media understanding provider types | | `plugin-sdk/speech` | Speech provider types | | `plugin-sdk/webhook-targets` | Webhook target registry and route-install helpers | | `plugin-sdk/webhook-path` | Webhook path normalization helpers | | `plugin-sdk/web-media` | Shared remote/local media loading helpers | | `plugin-sdk/zod` | Re-exported `zod` for plugin SDK consumers | | `plugin-sdk/testing` | `installCommonResolveTargetErrorCases`, `shouldAckReaction` | | Subpath | Key exports | | --- | --- | | `plugin-sdk/memory-core` | Bundled memory-core helper surface for manager/config/file/CLI helpers | | `plugin-sdk/memory-core-engine-runtime` | Memory index/search runtime facade | | `plugin-sdk/memory-core-host-engine-foundation` | Memory host foundation engine exports | | `plugin-sdk/memory-core-host-engine-embeddings` | Memory host embedding engine exports | | `plugin-sdk/memory-core-host-engine-qmd` | Memory host QMD engine exports | | `plugin-sdk/memory-core-host-engine-storage` | Memory host storage engine exports | | `plugin-sdk/memory-core-host-multimodal` | Memory host multimodal helpers | | `plugin-sdk/memory-core-host-query` | Memory host query helpers | | `plugin-sdk/memory-core-host-secret` | Memory host secret helpers | | `plugin-sdk/memory-core-host-status` | Memory host status helpers | | `plugin-sdk/memory-core-host-runtime-cli` | Memory host CLI runtime helpers | | `plugin-sdk/memory-core-host-runtime-core` | Memory host core runtime helpers | | `plugin-sdk/memory-core-host-runtime-files` | Memory host file/runtime helpers | | `plugin-sdk/memory-lancedb` | Bundled memory-lancedb helper surface | | Family | Current generated subpaths | Intended use | | --- | --- | --- | | Browser | `plugin-sdk/browser`, `plugin-sdk/browser-runtime`, `plugin-sdk/browser-config-support`, `plugin-sdk/browser-support` | Bundled browser plugin maintenance and compatibility | | Matrix | `plugin-sdk/matrix`, `plugin-sdk/matrix-helper`, `plugin-sdk/matrix-runtime-heavy`, `plugin-sdk/matrix-runtime-shared`, `plugin-sdk/matrix-runtime-surface`, `plugin-sdk/matrix-surface`, `plugin-sdk/matrix-thread-bindings` | Bundled Matrix helper/runtime surface | | Line | `plugin-sdk/line`, `plugin-sdk/line-core`, `plugin-sdk/line-runtime`, `plugin-sdk/line-surface` | Bundled LINE helper/runtime surface | | IRC | `plugin-sdk/irc`, `plugin-sdk/irc-surface` | Bundled IRC helper surface | | Channel-specific helpers | `plugin-sdk/googlechat`, `plugin-sdk/zalouser`, `plugin-sdk/bluebubbles`, `plugin-sdk/bluebubbles-policy`, `plugin-sdk/mattermost`, `plugin-sdk/mattermost-policy`, `plugin-sdk/feishu-conversation`, `plugin-sdk/msteams`, `plugin-sdk/nextcloud-talk`, `plugin-sdk/nostr`, `plugin-sdk/tlon`, `plugin-sdk/twitch` | Bundled channel compatibility/helper seams | | Provider-specific helpers | `plugin-sdk/openai`, `plugin-sdk/moonshot`, `plugin-sdk/modelstudio`, `plugin-sdk/modelstudio-definitions`, `plugin-sdk/provider-moonshot`, `plugin-sdk/together`, `plugin-sdk/amazon-bedrock`, `plugin-sdk/anthropic-vertex`, `plugin-sdk/cloudflare-ai-gateway`, `plugin-sdk/byteplus`, `plugin-sdk/chutes`, `plugin-sdk/deepseek`, `plugin-sdk/google`, `plugin-sdk/huggingface`, `plugin-sdk/kimi-coding`, `plugin-sdk/kilocode`, `plugin-sdk/minimax`, `plugin-sdk/mistral`, `plugin-sdk/nvidia`, `plugin-sdk/ollama`, `plugin-sdk/ollama-surface`, `plugin-sdk/opencode`, `plugin-sdk/opencode-go`, `plugin-sdk/qianfan`, `plugin-sdk/sglang`, `plugin-sdk/synthetic`, `plugin-sdk/venice`, `plugin-sdk/vllm`, `plugin-sdk/xai`, `plugin-sdk/volcengine` | Bundled provider-specific helper seams | | Auth/plugin-specific helpers | `plugin-sdk/github-copilot-login`, `plugin-sdk/github-copilot-token`, `plugin-sdk/diagnostics-otel`, `plugin-sdk/diffs`, `plugin-sdk/llm-task`, `plugin-sdk/thread-ownership`, `plugin-sdk/voice-call` | Bundled feature/plugin helper seams |

Registration API

The register(api) callback receives an OpenClawPluginApi object with these methods:

Capability registration

Method What it registers
api.registerProvider(...) Text inference (LLM)
api.registerCliBackend(...) Local CLI inference backend
api.registerChannel(...) Messaging channel
api.registerSpeechProvider(...) Text-to-speech / STT synthesis
api.registerRealtimeTranscriptionProvider(...) Streaming realtime transcription
api.registerRealtimeVoiceProvider(...) Duplex realtime voice sessions
api.registerMediaUnderstandingProvider(...) Image/audio/video analysis
api.registerImageGenerationProvider(...) Image generation
api.registerWebSearchProvider(...) Web search

Tools and commands

Method What it registers
api.registerTool(tool, opts?) Agent tool (required or { optional: true })
api.registerCommand(def) Custom command (bypasses the LLM)

Infrastructure

Method What it registers
api.registerHook(events, handler, opts?) Event hook
api.registerHttpRoute(params) Gateway HTTP endpoint
api.registerGatewayMethod(name, handler) Gateway RPC method
api.registerCli(registrar, opts?) CLI subcommand
api.registerService(service) Background service
api.registerInteractiveHandler(registration) Interactive handler

Reserved core admin namespaces (config.*, exec.approvals.*, wizard.*, update.*) always stay operator.admin, even if a plugin tries to assign a narrower gateway method scope. Prefer plugin-specific prefixes for plugin-owned methods.

CLI registration metadata

api.registerCli(registrar, opts?) accepts two kinds of top-level metadata:

  • commands: explicit command roots owned by the registrar
  • descriptors: parse-time command descriptors used for root CLI help, routing, and lazy plugin CLI registration

If you want a plugin command to stay lazy-loaded in the normal root CLI path, provide descriptors that cover every top-level command root exposed by that registrar.

api.registerCli(
  async ({ program }) => {
    const { registerMatrixCli } = await import("./src/cli.js");
    registerMatrixCli({ program });
  },
  {
    descriptors: [
      {
        name: "matrix",
        description: "Manage Matrix accounts, verification, devices, and profile state",
        hasSubcommands: true,
      },
    ],
  },
);

Use commands by itself only when you do not need lazy root CLI registration. That eager compatibility path remains supported, but it does not install descriptor-backed placeholders for parse-time lazy loading.

CLI backend registration

api.registerCliBackend(...) lets a plugin own the default config for a local AI CLI backend such as claude-cli or codex-cli.

  • The backend id becomes the provider prefix in model refs like claude-cli/opus.
  • The backend config uses the same shape as agents.defaults.cliBackends.<id>.
  • User config still wins. OpenClaw merges agents.defaults.cliBackends.<id> over the plugin default before running the CLI.
  • Use normalizeConfig when a backend needs compatibility rewrites after merge (for example normalizing old flag shapes).

Exclusive slots

Method What it registers
api.registerContextEngine(id, factory) Context engine (one active at a time)
api.registerMemoryPromptSection(builder) Memory prompt section builder
api.registerMemoryFlushPlan(resolver) Memory flush plan resolver
api.registerMemoryRuntime(runtime) Memory runtime adapter

Memory embedding adapters

Method What it registers
api.registerMemoryEmbeddingProvider(adapter) Memory embedding adapter for the active plugin
  • registerMemoryPromptSection, registerMemoryFlushPlan, and registerMemoryRuntime are exclusive to memory plugins.
  • registerMemoryEmbeddingProvider lets the active memory plugin register one or more embedding adapter ids (for example openai, gemini, or a custom plugin-defined id).
  • User config such as agents.defaults.memorySearch.provider and agents.defaults.memorySearch.fallback resolves against those registered adapter ids.

Events and lifecycle

Method What it does
api.on(hookName, handler, opts?) Typed lifecycle hook
api.onConversationBindingResolved(handler) Conversation binding callback

Hook decision semantics

  • before_tool_call: returning { block: true } is terminal. Once any handler sets it, lower-priority handlers are skipped.
  • before_tool_call: returning { block: false } is treated as no decision (same as omitting block), not as an override.
  • before_install: returning { block: true } is terminal. Once any handler sets it, lower-priority handlers are skipped.
  • before_install: returning { block: false } is treated as no decision (same as omitting block), not as an override.
  • message_sending: returning { cancel: true } is terminal. Once any handler sets it, lower-priority handlers are skipped.
  • message_sending: returning { cancel: false } is treated as no decision (same as omitting cancel), not as an override.

API object fields

Field Type Description
api.id string Plugin id
api.name string Display name
api.version string? Plugin version (optional)
api.description string? Plugin description (optional)
api.source string Plugin source path
api.rootDir string? Plugin root directory (optional)
api.config OpenClawConfig Current config snapshot (active in-memory runtime snapshot when available)
api.pluginConfig Record<string, unknown> Plugin-specific config from plugins.entries.<id>.config
api.runtime PluginRuntime Runtime helpers
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 path relative to plugin root

Internal module convention

Within your plugin, use local barrel files for internal imports:

my-plugin/
  api.ts            # Public exports for external consumers
  runtime-api.ts    # Internal-only runtime exports
  index.ts          # Plugin entry point
  setup-entry.ts    # Lightweight setup-only entry (optional)
Never import your own plugin through `openclaw/plugin-sdk/` from production code. Route internal imports through `./api.ts` or `./runtime-api.ts`. The SDK path is the external contract only.

Facade-loaded bundled plugin public surfaces (api.ts, runtime-api.ts, index.ts, setup-entry.ts, and similar public entry files) now prefer the active runtime config snapshot when OpenClaw is already running. If no runtime snapshot exists yet, they fall back to the resolved config file on disk.

Provider plugins can also expose a narrow plugin-local contract barrel when a helper is intentionally provider-specific and does not belong in a generic SDK subpath yet. Current bundled example: the Anthropic provider keeps its Claude stream helpers in its own public api.ts / contract-api.ts seam instead of promoting Anthropic beta-header and service_tier logic into a generic plugin-sdk/* contract.

Other current bundled examples:

  • @openclaw/openai-provider: api.ts exports provider builders, default-model helpers, and realtime provider builders
  • @openclaw/openrouter-provider: api.ts exports the provider builder plus onboarding/config helpers
Extension production code should also avoid `openclaw/plugin-sdk/` imports. If a helper is truly shared, promote it to a neutral SDK subpath such as `openclaw/plugin-sdk/speech`, `.../provider-model-shared`, or another capability-oriented surface instead of coupling two plugins together.