Files
adolf/docs/plugins/adding-capabilities.md
alvis bedb527145
Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Vendor OpenClaw source as Adolf fork baseline
Adolf is a fork/vendored clone of github.com/openclaw/openclaw (v2026.6.11),
free to diverge. Tree copied sans upstream .git; upstream remote added for
future syncs. Node pinned to 24 (.nvmrc); engines already require >=22.19.
Preserves docs/ARCHITECTURE.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LeqyaxJF2nbRXJtae2kNB2
2026-07-05 09:36:54 +00:00

6.5 KiB

summary, read_when, title, sidebarTitle
summary read_when title sidebarTitle
Contributor guide for adding a new shared capability to the OpenClaw plugin system
Adding a new core capability and plugin registration surface
Deciding whether code belongs in core, a vendor plugin, or a feature plugin
Wiring a new runtime helper for channels or tools
Adding capabilities (contributor guide) Adding capabilities
This is a **contributor guide** for OpenClaw core developers. If you are building an external plugin, see [Building plugins](/plugins/building-plugins) instead. For the deep architecture reference (capability model, ownership, load pipeline, runtime helpers), see [Plugin internals](/plugins/architecture).

Use this when OpenClaw needs a new shared domain such as embeddings, image generation, video generation, or some future vendor-backed feature area.

The rule:

  • plugin = ownership boundary
  • capability = shared core contract

Do not wire a vendor directly into a channel or a tool. Define the capability first.

When to create a capability

Create a new capability only when all of these are true:

  1. More than one vendor could plausibly implement it.
  2. Channels, tools, or feature plugins should consume it without caring about the vendor.
  3. Core needs to own fallback, policy, config, or delivery behavior.

If the work is vendor-only and no shared contract exists yet, define the contract first.

The standard sequence

  1. Define the typed core contract.
  2. Add plugin registration for that contract.
  3. Add a shared runtime helper.
  4. Wire one real vendor plugin as proof.
  5. Move feature/channel consumers onto the runtime helper.
  6. Add contract tests.
  7. Document the operator-facing config and ownership model.

What goes where

Layer Owns
Core Request/response types; provider registry and resolution; fallback behavior; config schema with propagated title/description docs metadata on nested object, wildcard, array-item, and composition nodes; runtime helper surface.
Vendor plugin Vendor API calls, vendor auth handling, vendor-specific request normalization, and registration of the capability implementation.
Feature/channel plugin Calls api.runtime.* or the matching plugin-sdk/*-runtime helper. Never calls a vendor implementation directly.

Provider and harness seams

Use provider hooks when the behavior belongs to the model provider contract rather than the generic agent loop. Examples include provider-specific request params after transport selection, auth-profile preference, prompt overlays, and follow-up fallback routing after model/profile failover.

Use agent harness hooks when the behavior belongs to the runtime that is executing a turn. Harnesses can classify explicit protocol outcomes such as empty output, reasoning without visible output, or a structured plan without a final answer so the outer model fallback policy can make the retry decision.

Keep both seams narrow:

  • Core owns the retry/fallback policy.
  • Provider plugins own provider-specific request/auth/routing hints.
  • Harness plugins own runtime-specific attempt classification.
  • Third-party plugins return hints, not direct mutations of core state.

File checklist

For a new capability, expect to touch these areas:

  • src/<capability>/types.ts
  • src/<capability>/...registry/runtime.ts
  • src/plugins/types.ts
  • src/plugins/registry.ts
  • src/plugins/captured-registration.ts
  • src/plugins/contracts/registry.ts
  • src/plugins/runtime/types-core.ts
  • src/plugins/runtime/index.ts
  • src/plugin-sdk/<capability>.ts
  • src/plugin-sdk/<capability>-runtime.ts
  • One or more bundled plugin packages.
  • Config, docs, tests.

Worked example: image generation

Image generation follows the standard shape:

  1. Core defines ImageGenerationProvider.
  2. Core exposes registerImageGenerationProvider(...).
  3. Core exposes api.runtime.imageGeneration.generate(...) and .listProviders(...).
  4. Vendor plugins (comfy, deepinfra, fal, google, litellm, microsoft-foundry, minimax, openai, openrouter, vydra, xai) register vendor-backed implementations.
  5. Future vendors register the same contract without changing channels/tools.

The config key is intentionally separate from vision-analysis routing:

  • agents.defaults.imageModel analyzes images.
  • agents.defaults.imageGenerationModel generates images.

Keep those separate so fallback and policy remain explicit.

Embedding providers

Use registerEmbeddingProvider(...) / contract embeddingProviders for reusable vector embedding providers. This contract is intentionally broader than memory: tools, search, retrieval, importers, or future feature plugins can consume embeddings without depending on the memory engine. Memory search also consumes generic embeddingProviders.

The older memory-specific registration API and memoryEmbeddingProviders contract are deprecated. Use registerEmbeddingProvider and embeddingProviders for all new embedding providers.

Review checklist

Before shipping a new capability, verify:

  • No channel/tool imports vendor code directly.
  • The runtime helper is the shared path.
  • At least one contract test asserts bundled ownership.
  • Config docs name the new model/config key.
  • Plugin docs explain the ownership boundary.

If a PR skips the capability layer and hardcodes vendor behavior into a channel/tool, send it back and define the contract first.