Adding Capabilities to OpenClaw: Contributor Guide

Learn when and how to add a new shared capability to the OpenClaw plugin system. This guide is for core contributors, covering the standard sequence and key principles.

Read this when

  • 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

Note

This guide is aimed at contributors working on OpenClaw's core. For external plugin development, refer to Building plugins. A deeper look at the architecture, covering the capability model, ownership, loading, and runtime helpers, is in Plugin internals.

Turn to this when OpenClaw requires a fresh shared domain, for instance embeddings, image generation, video generation, or another vendor-backed feature area down the road.

The guiding principle:

  • plugin = where ownership ends
  • capability = the shared contract at the core

Avoid hooking a vendor straight into a channel or tool. Lay down the capability first.

When to create a capability

Only introduce a new capability when every condition below holds:

  1. At least two vendors could realistically offer an implementation.
  2. Channels, tools, or feature plugins should use it without knowing the vendor.
  3. Core must handle fallback, policy, configuration, or delivery.

If the task is vendor-only and no shared contract exists yet, write the contract before anything else.

The standard sequence

  1. Define the typed contract at the core.
  2. Set up plugin registration for that contract.
  3. Provide a shared runtime helper.
  4. Connect one actual vendor plugin to prove the approach.
  5. Shift feature and channel consumers onto the runtime helper.
  6. Add contract tests.
  7. Document the operator-facing config and ownership model.

What goes where

LayerOwns
CoreRequest and 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 pluginVendor API calls, vendor auth handling, vendor-specific request normalization, and registration of the capability implementation.
Feature/channel pluginCalls api.runtime.* or the matching plugin-sdk/*-runtime helper. Never calls a vendor implementation directly.

Provider and harness seams

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

Choose agent harness hooks when the behavior belongs to the runtime 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 decide on retries.

Keep both seams narrow:

  • Core owns the retry and fallback policy.
  • Provider plugins own provider-specific request, auth, and 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 or tools.

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

  • agents.defaults.imageModel analyzes images.
  • agents.defaults.mediaModels.image 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 were removed after their August 2026 migration window. Use registerEmbeddingProvider and embeddingProviders for every embedding provider.

Review checklist

Before shipping a new capability, verify:

  • No channel or 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 or config key.
  • Plugin docs explain the ownership boundary.

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

734 words · updated Aug 17, 2026