---
summary: "Migrate from the legacy backwards-compatibility layer to the modern plugin SDK"
title: "Plugin SDK migration"
sidebarTitle: "Migrate to SDK"
read_when:
  - You used api.registerEmbeddedExtensionFactory before OpenClaw 2026.4.25
  - You are updating a plugin to the modern plugin architecture
  - You maintain an external OpenClaw plugin
---

OpenClaw replaced a broad backwards-compatibility layer with a modern plugin
architecture built from small, focused imports. If your plugin predates that
change, this guide gets it onto the current contracts.

## What changed

Several wide-open import surfaces used to let plugins reach almost anything
from a single entry point:

- **`openclaw/plugin-sdk`** and **`openclaw/plugin-sdk/compat`** - re-exported
  dozens of helpers while the focused SDK was being built. Both roots are now
  removed. Import a documented subpath instead.
- **`openclaw/plugin-sdk/infra-runtime`** - a broad barrel mixing system
  events, heartbeat state, delivery queues, fetch/proxy helpers, file helpers,
  approval types, and unrelated utilities.
- **`openclaw/plugin-sdk/config-runtime`** - a removed broad config barrel,
  including its deprecated direct `loadConfig` and `writeConfigFile` exports.
- **`openclaw/plugin-sdk/channel-lifecycle`**, **`channel-message`**, and
  **`channel-reply-pipeline`** - removed channel compatibility facades. Use
  the focused outbound and inbound contracts, checking each named export.
- **`openclaw/extension-api`** - a removed bridge that gave plugins direct
  access to host-side helpers like the embedded agent runner.
- **`api.registerEmbeddedExtensionFactory(...)`** - a removed embedded-runner-only
  hook that observed embedded-runner events such as `tool_result`. Use agent
  tool-result middleware instead (see [Migrate embedded tool-result extensions
  to middleware](/plugins/sdk-migration/how-to-migrate#how-to-migrate)).

The root SDK, compat barrel, extension bridge, embedded extension factory, and
five channel/config/infrastructure compatibility facades have been removed.
The latter retirement received explicit SDK-owner approval on September 30,
2026; see the [removal timeline](/plugins/sdk-migration/removal-timeline).

<Warning>
  Plugins importing the removed SDK or extension surfaces no longer
  load. Follow the [import path mappings](/plugins/sdk-migration/import-paths) before upgrading.
</Warning>

OpenClaw does not remove or reinterpret documented plugin behavior in the same
change that introduces a replacement. Breaking contract changes go through a
compatibility adapter, diagnostics, docs, and a deprecation window first. That
applies to SDK imports, manifest fields, setup APIs, hooks, and runtime
registration behavior.

`ChatCommandDefinition.category` retains the `"docks"` value accepted by the
2026.8.1 SDK. Command lists display these legacy definitions under **Tools**.
The category does not enable channel docking or restore retired docking commands.
New definitions should use `"tools"`.

Bundled ACP integrations should await `readAcpSessionEntryAsync` from the local
`openclaw/plugin-sdk/acp-runtime` facade for session metadata reads. This facade
remains a JavaScript compatibility export; its declarations are excluded from
the typed public SDK. File-backed reads run on the SQLite workers and preserve the session lifecycle throughout the
metadata join. File-backed results are detached snapshots, including when
`clone: false` is supplied. The returned `storeReadFailed` flag still distinguishes an
unreadable session store from missing metadata; startup cleanup must keep
bindings when that flag is set. Unbound legacy ACP metadata can still accompany
that flag; it does not certify the session row. Source retirement and worker failures reject
the read and must not be treated as an absent session.

The synchronous `readAcpSessionEntry` and
`getAcpSessionManager().resolveSession()` contracts shipped in `v2026.9.4`
remain available for existing consumers of that compatibility export. They are
deprecated for runtime use. Ordinary ACP manager and Gateway callers use
`readAcpSessionEntryAsync` and `getAcpSessionManager().resolveSessionAsync()`.
Discord and Telegram startup binding cleanup retain their existing synchronous
reader until conditional deletion can validate metadata at the mutation owner.
Their inactive incognito composition accepts a prepared session reader whose
current-source assertion reaches the binding transaction and commit grants.
The preparation retains the original actor revision and ACP metadata publication
fence until cleanup releases it. The local `prepareAcpSessionEntryRead` helper captures an existing private actor
binding and supplies that retained reader; it returns `undefined` without a binding.
Discord and Telegram startup cleanup use it by default. Ordinary production
acquisition stays native until atomic incognito activation; guarded durable
cleanup remains separate work.
`IncognitoSessionEndedError` and `IncognitoSessionSyncAccessError`, exposed through
the local `openclaw/plugin-sdk/acp-runtime` facade, must propagate through cleanup and status
probes. Use `rethrowIncognitoSessionError(error)` before treating other failures
as an absent session or an uncertain probe; it also recognizes nested refusals.
Removing the synchronous contracts
requires a separately announced breaking SDK release. Incognito reads retain
their existing native in-memory owner until that owner's worker migration.

### Session reset freshness

Channel runtime consumers should await
`runtime.channel.session.resolveEntryResetFreshnessAsync(...)` when deciding
whether a session needs reset. File-backed entries and transcript lifecycle
timestamps are read from the same worker snapshot, with the original database
owner retained through validation and cleanup. The synchronous
`resolveEntryResetFreshness(...)` method shipped in `v2026.9.8` remains available
for existing JavaScript consumers and is deprecated for runtime use; removal
requires the next Plugin SDK major and explicit breaking-release approval. Both methods retain the
existing reset policy and process-held incognito behavior.

### Why

- **Slow startup** - importing one helper loaded dozens of unrelated modules.
- **Circular dependencies** - broad re-exports made import cycles easy to
  create.
- **Unclear API surface** - no way to tell stable exports from internal ones.

The typed public SDK is organized into focused subpaths with documented
contracts. Not every SDK build entrypoint is a public plugin API.

Legacy provider convenience seams for bundled channels are gone too -
channel-branded helper shortcuts were private mono-repo conveniences, not
stable plugin contracts. Use narrow generic SDK subpaths instead. Inside the
bundled plugin workspace, keep provider-owned helpers in that plugin's own
`api.ts` or `runtime-api.ts`:

- Anthropic keeps Claude-specific stream helpers in its own `api.ts` /
  `contract-api.ts` seam.
- OpenAI keeps provider builders, default-model helpers, and realtime provider
  builders in its own `api.ts`.
- OpenRouter keeps provider builder and onboarding/config helpers in its own
  `api.ts`.

## Where each topic lives

Every section of the single-page version lives on one of the six pages below.
The anchors from the single-page version still resolve here.

### Migration steps

[How to migrate a plugin](/plugins/sdk-migration/how-to-migrate) — the ordered migration steps.

- [Await personal model-account operations](/plugins/sdk-migration/how-to-migrate#await-personal-model-account-operations)
- [Await session transcript persistence](/plugins/sdk-migration/how-to-migrate#await-session-transcript-persistence)
- [Await extension session changes](/plugins/sdk-migration/how-to-migrate#await-extension-session-changes)
- [Await provider replay metadata](/plugins/sdk-migration/how-to-migrate#await-provider-replay-metadata)
- <a id="how-to-migrate"></a>[How to migrate](/plugins/sdk-migration/how-to-migrate#how-to-migrate)
- <a id="migrate-runtime-config-load%2Fwrite-helpers"></a>[Migrate runtime config load/write helpers](/plugins/sdk-migration/how-to-migrate#migrate-runtime-config-load%2Fwrite-helpers)
- <a id="migrate-embedded-tool-result-extensions-to-middleware"></a>[Migrate embedded tool-result extensions to middleware](/plugins/sdk-migration/how-to-migrate#migrate-embedded-tool-result-extensions-to-middleware)
- <a id="migrate-approval-native-handlers-to-capability-facts"></a>[Migrate approval-native handlers to capability facts](/plugins/sdk-migration/how-to-migrate#migrate-approval-native-handlers-to-capability-facts)
- <a id="audit-windows-wrapper-fallback-behavior"></a>[Audit Windows wrapper fallback behavior](/plugins/sdk-migration/how-to-migrate#audit-windows-wrapper-fallback-behavior)
- <a id="find-deprecated-imports"></a>[Find deprecated imports](/plugins/sdk-migration/how-to-migrate#find-deprecated-imports)
- <a id="replace-with-focused-imports"></a>[Replace with focused imports](/plugins/sdk-migration/how-to-migrate#replace-with-focused-imports)
- <a id="replace-broad-infra-runtime-imports"></a>[Replace broad `infra-runtime` imports](/plugins/sdk-migration/how-to-migrate#replace-broad-infra-runtime-imports)
- <a id="migrate-channel-route-helpers"></a>[Migrate channel route helpers](/plugins/sdk-migration/how-to-migrate#migrate-channel-route-helpers)
- <a id="build-and-test"></a>[Build and test](/plugins/sdk-migration/how-to-migrate#build-and-test)

### Import paths

[Import path reference](/plugins/sdk-migration/import-paths) — which typed-public subpath replaces each legacy import.

- <a id="import-path-reference"></a>[Import path reference](/plugins/sdk-migration/import-paths#import-path-reference)
- <a id="retained-channel-facade-mappings"></a>[Removed channel facade mappings](/plugins/sdk-migration/import-paths#retained-channel-facade-mappings)

### Removed surfaces and replacements

[Removed surfaces and replacements](/plugins/sdk-migration/removed-surfaces) — what was removed, and the replacement for each legacy API.

- <a id="removed-compatibility-surfaces"></a>[Removed compatibility surfaces](/plugins/sdk-migration/removed-surfaces#removed-compatibility-surfaces)
- <a id="process-global-api-provider-publication"></a>[Process-global API-provider publication](/plugins/sdk-migration/removed-surfaces#process-global-api-provider-publication)
- <a id="deactivate-hook-alias"></a>[Deactivate hook alias](/plugins/sdk-migration/removed-surfaces#deactivate-hook-alias)
- <a id="private-testing-barrel"></a>[Private testing barrel](/plugins/sdk-migration/removed-surfaces#private-testing-barrel)
- <a id="migration-reference"></a>[Migration reference](/plugins/sdk-migration/removed-surfaces#migration-reference)
- <a id="command-auth"></a>[`command-auth` help builders -> `command-status`](/plugins/sdk-migration/removed-surfaces#command-auth-help-builders-command-status)
- <a id="mention"></a>[Mention gating helpers -> `resolveInboundMentionDecision`](/plugins/sdk-migration/removed-surfaces#mention-gating-helpers-resolveinboundmentiondecision)
- <a id="channel-runtime-shim-and-channel-actions-helpers"></a>[Channel runtime shim and channel actions helpers](/plugins/sdk-migration/removed-surfaces#channel-runtime-shim-and-channel-actions-helpers)
- <a id="web"></a>[Web search provider `tool()` helper -> `createTool()` on the plugin](/plugins/sdk-migration/removed-surfaces#web-search-provider-tool-helper-createtool-on-the-plugin)
- <a id="plaintext"></a>[Plaintext channel envelopes -> `BodyForAgent`](/plugins/sdk-migration/removed-surfaces#plaintext-channel-envelopes-bodyforagent)
- <a id="subagent-spawning"></a>[`subagent_spawning` hook -> core thread binding](/plugins/sdk-migration/removed-surfaces#subagent-spawning-hook-core-thread-binding)
- <a id="provider"></a>[Provider discovery types -> provider catalog types](/plugins/sdk-migration/removed-surfaces#provider-discovery-types-provider-catalog-types)
- <a id="thinking"></a>[Thinking policy hooks -> `resolveThinkingProfile`](/plugins/sdk-migration/removed-surfaces#thinking-policy-hooks-resolvethinkingprofile)
- <a id="external"></a>[External auth providers -> `contracts.externalAuthProviders`](/plugins/sdk-migration/removed-surfaces#external-auth-providers-contracts-externalauthproviders)
- <a id="provider-1"></a>[Provider env-var lookup -> `setup.providers[].envVars`](/plugins/sdk-migration/removed-surfaces#provider-env-var-lookup-setup-providers-envvars)
- <a id="memory"></a>[Memory plugin registration -> `registerMemoryCapability`](/plugins/sdk-migration/removed-surfaces#memory-plugin-registration-registermemorycapability)
- <a id="memory-embedding-provider-api"></a>[Memory embedding provider API](/plugins/sdk-migration/removed-surfaces#memory-embedding-provider-api)
- <a id="raw"></a>[Raw channel send results -> `OutboundDeliveryResult`](/plugins/sdk-migration/removed-surfaces#raw-channel-send-results-outbounddeliveryresult)
- <a id="subagent-session-messages-types-renamed"></a>[Subagent session messages types renamed](/plugins/sdk-migration/removed-surfaces#subagent-session-messages-types-renamed)
- <a id="removed-session-and-transcript-file-apis"></a>[Removed session and transcript file APIs](/plugins/sdk-migration/removed-surfaces#removed-session-and-transcript-file-apis)
- <a id="agent"></a>[Agent harness attempt params -> V2 host-capability contract](/plugins/sdk-migration/removed-surfaces#agent-harness-attempt-params-v2-host-capability-contract)
- <a id="embedded"></a>[Embedded extension factories -> agent tool-result middleware](/plugins/sdk-migration/removed-surfaces#embedded-extension-factories-agent-tool-result-middleware)
- <a id="openclawschematype"></a>[`OpenClawSchemaType` alias -> `OpenClawConfig`](/plugins/sdk-migration/removed-surfaces#openclawschematype-alias-openclawconfig)

### Talk and voice

[Talk and realtime voice migration](/plugins/sdk-migration/talk) — the unified Talk session API and its method map.

- <a id="talk-and-realtime-voice-migration"></a>[Talk and realtime voice migration](/plugins/sdk-migration/talk#talk-and-realtime-voice-migration)

### Compatibility records

[Compatibility policy and records](/plugins/sdk-migration/compatibility-policy) — what is retained, why, and on what condition it can be removed.

- <a id="compatibility-policy"></a>[Compatibility policy](/plugins/sdk-migration/compatibility-policy#compatibility-policy)
- <a id="retained-helper-contracts"></a>[Retained helper contracts](/plugins/sdk-migration/compatibility-policy#retained-helper-contracts)
- <a id="harness-attempt-result-migration"></a>[Harness attempt result migration](/plugins/sdk-migration/compatibility-policy#harness-attempt-result-migration)
- <a id="model-provider-result-compatibility"></a>[Model-provider result compatibility](/plugins/sdk-migration/compatibility-policy#model-provider-result-compatibility)
- <a id="memory-read-missing-results"></a>[Memory read missing results](/plugins/sdk-migration/compatibility-policy#memory-read-missing-results)
- <a id="config-record-migrations"></a>[Config record migrations](/plugins/sdk-migration/compatibility-policy#config-record-migrations)
- <a id="plugin-state-migration-declarations"></a>[Plugin state migration declarations](/plugins/sdk-migration/compatibility-policy#plugin-state-migration-declarations)
- <a id="authstorage-sqlite-migration"></a>[AuthStorage SQLite migration](/plugins/sdk-migration/compatibility-policy#authstorage-sqlite-migration)
- <a id="published-channel-setup-compatibility"></a>[Published channel setup compatibility](/plugins/sdk-migration/compatibility-policy#published-channel-setup-compatibility)
- <a id="channel-setup-input-field-compatibility"></a>[Channel setup input field compatibility](/plugins/sdk-migration/compatibility-policy#channel-setup-input-field-compatibility)
- <a id="verifying-readers"></a>[Verifying readers](/plugins/sdk-migration/compatibility-policy#verifying-readers)
- <a id="media-legacy-projection"></a>[Media legacy projection](/plugins/sdk-migration/compatibility-policy#media-legacy-projection)

### Timeline

[Removal timeline](/plugins/sdk-migration/removal-timeline) — when deprecated surfaces become eligible for removal.

- <a id="removal-timeline"></a>[Removal timeline](/plugins/sdk-migration/removal-timeline#removal-timeline)

## Related

- [Getting Started](/plugins/building-plugins) - build your first plugin
- [SDK Overview](/plugins/sdk-overview) - full subpath import reference
- [Channel Plugins](/plugins/sdk-channel-plugins) - building channel plugins
- [Provider Plugins](/plugins/sdk-provider-plugins) - building provider plugins
- [Plugin Internals](/plugins/architecture) - architecture deep dive
- [Plugin Manifest](/plugins/manifest) - manifest schema reference
- [Plugin hooks](/plugins/hooks) - typed and custom hook surfaces

<a id="runtime-tasks-flow" />

For the removed Tasks and TaskFlow surfaces, see [Tasks and TaskFlow API removal](/plugins/sdk-migration/removed-surfaces#tasks-and-taskflow-apis-removed).
