Capability Cookbook
Use this when OpenClaw needs a new domain such as image generation, video generation, or some future vendor-backed feature area. The rule:- plugin = ownership boundary
- capability = shared core contract
When to create a capability
Create a new capability when all of these are true:- more than one vendor could plausibly implement it
- channels, tools, or feature plugins should consume it without caring about the vendor
- core needs to own fallback, policy, config, or delivery behavior
The standard sequence
- Define the typed core contract.
- Add plugin registration for that contract.
- Add a shared runtime helper.
- Wire one real vendor plugin as proof.
- Move feature/channel consumers onto the runtime helper.
- Add contract tests.
- Document the operator-facing config and ownership model.
What goes where
Core:- request/response types
- provider registry + resolution
- fallback behavior
- config schema and labels/help
- runtime helper surface
- vendor API calls
- vendor auth handling
- vendor-specific request normalization
- registration of the capability implementation
- calls
api.runtime.*or the matchingplugin-sdk/*-runtimehelper - never calls a vendor implementation directly
File checklist
For a new capability, expect to touch these areas:src/<capability>/types.tssrc/<capability>/...registry/runtime.tssrc/plugins/types.tssrc/plugins/registry.tssrc/plugins/captured-registration.tssrc/plugins/contracts/registry.tssrc/plugins/runtime/types-core.tssrc/plugins/runtime/index.tssrc/plugin-sdk/<capability>.tssrc/plugin-sdk/<capability>-runtime.ts- one or more
extensions/<vendor>/... - config/docs/tests
Example: image generation
Image generation follows the standard shape:- core defines
ImageGenerationProvider - core exposes
registerImageGenerationProvider(...) - core exposes
runtime.imageGeneration.generate(...) - the
openaiandgoogleplugins register vendor-backed implementations - future vendors can register the same contract without changing channels/tools
agents.defaults.imageModel= analyze imagesagents.defaults.imageGenerationModel= generate images
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