# Adding a new capability

> The sequence, file checklist, and contract-test pattern for adding a capability to the plugin system

- 网址：https://funcoding.ai/agents/openclaw/plugins/architecture-internals/new-capability/
- 来源：OpenClaw 官方文档原文（英文），MIT 许可，同步于 2026-10-11
- 官方原文：https://docs.openclaw.ai/zh-CN/plugins/architecture-internals/new-capability

---
The recommended sequence for adding a capability the plugin API does not have
yet, plus the file checklist and contract-test pattern. Part of the [Plugin
architecture internals](https://funcoding.ai/agents/openclaw/plugins/architecture-internals/) guide.

## Adding a new capability

When a plugin needs behavior that does not fit the current API, do not bypass
the plugin system with a private reach-in. Add the missing capability.

Recommended sequence:

1. **Define the core contract.** Decide what shared behavior core should own:
   policy, fallback, config merge, lifecycle, channel-facing semantics, and
   runtime helper shape.
2. **Add typed plugin registration/runtime surfaces.** Extend
   `OpenClawPluginApi` and/or `api.runtime` with the smallest useful typed
   capability surface.
3. **Wire core + channel/feature consumers.** Channels and feature plugins
   should consume the new capability through core, not by importing a vendor
   implementation directly.
4. **Register vendor implementations.** Vendor plugins then register their
   backends against the capability.
5. **Add contract coverage.** Add tests so ownership and registration shape
   stay explicit over time.

This is how OpenClaw stays opinionated without becoming hardcoded to one
provider's worldview. See [Adding capabilities](https://funcoding.ai/agents/openclaw/plugins/adding-capabilities/)
for a concrete file checklist and worked example.

### Capability checklist

When you add a new capability, the implementation should usually touch these
surfaces together:

- core contract types in `src/<capability>/types.ts`
- core runner/runtime helper in `src/<capability>/runtime.ts`
- plugin API registration surface in `src/plugins/types.ts`
- plugin registry wiring in `src/plugins/registry.ts`
- plugin runtime exposure in `src/plugins/runtime/*` when feature/channel
  plugins need to consume it
- capture/test helpers in `src/test-utils/plugin-registration.ts`
- ownership/contract assertions in `src/plugins/contracts/registry.ts`
- operator/plugin docs in `docs/`

If one of those surfaces is missing, that is usually a sign the capability is
not fully integrated yet.

### Capability template

Minimal pattern:

```ts
// core contract
export type VideoGenerationProviderPlugin = {
  id: string;
  label: string;
  generateVideo: (req: VideoGenerationRequest) => Promise<VideoGenerationResult>;
};

// plugin API
api.registerVideoGenerationProvider({
  id: "xai",
  label: "xAI",
  async generateVideo(req) {
    // generateXaiVideo is a placeholder for your own vendor call.
    return await generateXaiVideo(req);
  },
});

// shared runtime helper for feature/channel plugins
const clip = await api.runtime.videoGeneration.generate({
  prompt: "Show the robot walking through the lab.",
  cfg,
});
```

Contract test pattern (`src/plugins/contracts/registry.ts` exposes ownership
lookups such as `providerContractPluginIds`; tests assert a plugin's
`contracts.videoGenerationProviders` list matches what it actually registers):

```ts
expect(pluginManifest.contracts?.videoGenerationProviders).toEqual(["xai"]);
```

That keeps the rule simple:

- core owns the capability contract + orchestration
- vendor plugins own vendor implementations
- feature/channel plugins consume runtime helpers
- contract tests keep ownership explicit
