3.3 KiB
| summary | read_when | title | |||
|---|---|---|---|---|---|
| Cookbook for adding a new shared capability to OpenClaw |
|
Capability Cookbook |
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
That means you should not start by wiring a vendor directly into a channel or a tool. Start by defining the capability.
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
If the work is vendor-only and no shared contract exists yet, stop and define the contract first.
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 plugin:
- vendor API calls
- vendor auth handling
- vendor-specific request normalization
- registration of the capability implementation
Feature/channel plugin:
- 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
The config key is separate from vision-analysis routing:
agents.defaults.imageModel= analyze imagesagents.defaults.imageGenerationModel= generate images
Keep those separate so fallback and policy remain explicit.
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.