Plugin Compatibility Contracts and Migration

Learn how OpenClaw maintains older plugin contracts through compatibility adapters and a registry. Essential for plugin maintainers and SDK developers.

Read this when

  • You maintain an OpenClaw plugin
  • You see a plugin compatibility warning
  • You are planning a plugin SDK or manifest migration

OpenClaw maintains older plugin contracts through named compatibility adapters prior to their eventual removal. This approach safeguards both bundled and third-party plugins while the SDK, manifest, setup, config, and agent runtime contracts continue to evolve.

Compatibility registry

The core registry at src/plugins/compat/registry.ts tracks plugin compatibility contracts. Each entry contains:

  • a stable compatibility code
  • status: active, deprecated, removal-pending, or removed
  • owner: sdk, config, setup, channel, provider, plugin-execution, agent-runtime, or core
  • introduction and deprecation dates where applicable
  • an exact removeAfter date or named removalGate once approved by the owning maintainer; a record lacking both stays ineligible for removal
  • replacement guidance
  • docs, diagnostics, and tests covering both the old and new behavior

Maintainers use this registry as their planning source, and future plugin inspector checks will rely on it too. Whenever a plugin-facing behavior shifts, the compatibility record must be added or updated in the same change that introduces the adapter.

Doctor repair and migration compatibility get tracked separately at src/commands/doctor/shared/deprecation-compat.ts. These entries cover old config shapes, install-ledger layouts, and repair shims that might need to remain available after the runtime compatibility path is gone.

Every doctor compatibility record declares introduced and removeAfter. The pnpm check:doctor-deprecation-registry guard triggers a failure when a record is still deprecated on or after removeAfter; maintainers must either remove it after supported-upgrade proof or shift it to removal-pending with a documented blocker. removal-pending records escape the date guard failure but stay in the explicit review queue until their upgrade conditions are satisfied.

Release sweeps should inspect both registries. A doctor migration should not be deleted just because the matching runtime or config compatibility record has expired; first confirm no supported upgrade path still depends on the repair. During release planning, revalidate each replacement annotation as well, since plugin ownership and config footprint can shift when providers and channels leave core.

Deprecation policy

OpenClaw must not remove a documented plugin contract in the same release that brings in its replacement. The migration sequence:

  1. Introduce the new contract.
  2. Keep the old behavior connected through a named compatibility adapter.
  3. Emit diagnostics or warnings where plugin authors can take action.
  4. Document the replacement and its timeline.
  5. Test both the old and new paths.
  6. Wait through the announced migration window.
  7. Remove only with explicit breaking-release approval.

Deprecated records need a warning start date, replacement, docs link, and either a final removal date no later than three months after the warning begins or an explicit version boundary such as next-plugin-sdk-major. A deprecated compatibility path with an open-ended removal window is not allowed unless maintainers explicitly designate it as permanent compatibility and label it active instead.

Current compatibility areas

The July 2026 sweep removed the expired root SDK, manifest, provider, runtime, registry-flag, and plugin-owned web-config aliases. Doctor migrations remain separately tracked so supported upgrade paths can still repair old config.

The remaining dated compatibility areas are:

  • the September SDK subpath window described in the migration guide
  • the beta.5 session-store bridge
  • the shipped agent-harness SDK aliases, whose removal awaits a new externally documented migration decision
  • the October 2026 SDK annotation families listed below

Active, undated registry records cover supported behavior rather than removal debt, including activation hints, plugin capture, bundled plugin enablement, and the generated channel-config fallback.

The annotation-only compatibility audit added these dated records. Their removeAfter date marks the earliest review date, not authorization to remove a surface while its stated reader or migration condition remains unmet.

Compatibility codeRemoval conditionremoveAfter
plugin-sdk-channel-setup-input-fieldsRepeat the published-plugin artifact sweep and remove only fields with no reader.2026-10-01
plugin-sdk-broad-runtime-barrelsMove bundled and indexed external consumers to focused SDK subpaths.2026-10-01
plugin-sdk-provider-owned-helper-shimsMove each deprecated provider helper to its provider-local API and prove no published reader remains.2026-10-01
message-presentation-legacy-bridgesMove reply producers and official channel packages to MessagePresentation.2026-10-01
plugin-sdk-focused-compat-aliasesProve every enumerated alias has no bundled or published reader.2026-10-01
agent-harness-terminal-result-aliasesMove harnesses to terminal and visibleReplies, then prove the legacy result fields are unread.2026-10-01
official-plugin-export-aliasesMove users of Google Meet testing, channel presentation, and Discord timeout exports to canonical APIs.2026-10-01
memory-host-compatibility-aliasesUse canonical memory tables and prepared runtime config everywhere.2026-10-01
plugin-runtime-api-compat-aliasesMove flat plugin registration/runtime calls to their namespaced or focused replacements.2026-10-01
plugin-provider-manifest-compat-aliasesMove kind/setup/catalog ownership to manifests and model-catalog registration.2026-10-01
deprecated-session-store-beta5-apiEnd the v2026.7.x whole-store upgrade window, including package-root aliases.2026-10-12

pnpm plugins:boundary-report reports removal-pending records separately from deprecated records. A due removal-pending record remains blocked until its reported migration condition is satisfied and its reader references are cleared; the existing --fail-on-eligible-compat gate continues to apply only to dated deprecated records. Reader references are surface-token matches for triage; use the published-artifact sweep before authorizing removal.

Auth profile cooldown classifications

AuthProfileStore.usageStats[*].cooldownReason remains the closed canonical AuthProfileFailureReason union. Host policy records WHAM HTTP 401 as auth and HTTP 403 as auth_permanent.

cooldownClassification is an optional additive host diagnostic. Its current values are wham_token_expired and wham_account_dead. Plugins that display this field must keep a default or fallback for future optional classifications. Canonical failover uses resolveProfilesUnavailableReason; the diagnostic is presentation state only and must never be used as authorization.

Channel prompt-context identifier aliases

New channel plugins are expected to adopt MsgContext.ChannelPromptContext, MsgContext.ChannelStructuredContext, ChannelStructuredContextEntry, and SupplementalContextFacts.channelStructuredContext. The legacy UntrustedContext, UntrustedStructuredContext, UntrustedStructuredContextEntry, and supplementary untrustedContext designations persist as deprecated SDK aliases through 2026-09-08 (registry entry sdk-untrusted-context-identifier-aliases). During inbound finalization, those outdated fields get merged into the channel-named equivalents, and the original keys disappear from runtime context.

On the same timeline, the security runtime exposes buildChannelMetadata, with the deprecated buildUntrustedChannelMetadata alias still accessible.

WhatsApp inbound callback retirement

The WhatsApp callback compatibility window from August 2026 has ended. Runtime callbacks exclusively accept WebInboundCallbackMessage now: nested event, payload, quote, group, and platform contexts, along with the mandatory public admission envelope. Flat callback fields and top-level admission aliases are rejected outright.

From inbound provider payloads, payload.channelStructuredContext gets pulled out. Before relying on its payload as definitive, plugins need to examine label, source, and type.

Plugin inspector package

Position the plugin inspector as a standalone package or repository outside the core OpenClaw repo, grounded in the versioned compatibility and manifest contracts. The initial CLI should look like:

openclaw-plugin-inspector ./my-plugin

It needs to produce manifest and schema validation, the contract compatibility version under review, install and source metadata checks, cold-path import checks, and deprecation or compatibility warnings. For stable machine-readable output in CI annotations, rely on --json. OpenClaw core should supply contracts and fixtures for the inspector to consume, but the main openclaw package should not ship the inspector binary.

Maintainer acceptance lane

When validating the external inspector against OpenClaw plugin packages, employ Crabbox-backed Blacksmith Testbox for the installable-package acceptance lane. Execute it from a pristine OpenClaw checkout once the package is built:

pnpm crabbox:run -- --provider blacksmith-testbox --timing-json --shell -- "pnpm install && pnpm build && npm exec --yes @openclaw/plugin-inspector@0.1.0 -- ./extensions/telegram --json"
pnpm crabbox:run -- --provider blacksmith-testbox --timing-json --shell -- "npm exec --yes @openclaw/plugin-inspector@0.1.0 -- ./extensions/discord --json"
pnpm crabbox:run -- --provider blacksmith-testbox --timing-json --shell -- "npm exec --yes @openclaw/plugin-inspector@0.1.0 -- <clawhub-plugin-dir> --json"

Maintainers should treat this lane as opt-in, given that it pulls in an external npm package and might examine plugin packages cloned beyond the repo. The local repo guards handle the SDK export map, compatibility registry metadata, deprecated SDK-import burn-down, and bundled extension import boundaries; the Testbox inspector proof covers the package as external plugin authors experience it.

Release notes

Release notes ought to list upcoming plugin deprecations, complete with target dates and migration doc links, prior to any compatibility path shifting to removal-pending or removed.

1,324 words · updated Aug 25, 2026