docs/book/src/developing/first-party-extensions.md
Use this page when adding or changing a built-in ZeroClaw provider, channel, tool, memory backend, or hardware/peripheral integration.
This page is not for out-of-process plugins. If the extension can live outside the core binary, start with Plugin protocol or MCP before adding a first-party implementation.
Keep the core binary lean by choosing the narrowest durable home for each capability before adding or removing code. An external integration is not, by itself, a reason to delete a first-party tool; the boundary depends on the contract ZeroClaw must preserve for operators, agents, and existing configs.
| Surface | Use when | Avoid when |
|---|---|---|
| Baseline built-in capability | The capability is part of the agent's baseline operating contract, needs tight autonomy/receipt integration, or must work before plugins, skills, or MCP servers are configured. | The behavior is just a wrapper around one vendor API, product, SaaS, or optional local program. |
| Feature-gated first-party implementation | The implementation is first-party, security-sensitive, or needs Rust trait integration, but the dependency, platform, or binary-size cost should not affect minimal builds. New crates still need the architecture map, RFC, and stability-tier checks. | The feature flag would become a hidden compatibility trap or a second source of truth for config/state. |
| WASM plugin | The capability should be installed, upgraded, permissioned, or distributed independently while still using ZeroClaw's plugin ABI and manifest permissions. | The current plugin ABI cannot express the needed security, lifecycle, or data contract. |
| Skill package | The value is mostly instructions, prompts, repeatable workflows, scripts, or CLI recipes that can run through existing tools. | The capability needs a new trusted runtime primitive, long-lived service, or direct config/schema ownership. |
| MCP server | A local or remote service already exposes an appropriate Model Context Protocol surface, or the integration should remain outside the ZeroClaw process. | The project needs a stable first-party guarantee, offline default behavior, or a ZeroClaw-specific security model the server cannot provide. |
| CLI-backed integration | A mature external CLI already owns authentication, API drift, and platform behavior, and ZeroClaw only needs to call it through existing shell/tool policy. | The CLI output is too unstable, requires broad ambient permissions, or would hide side effects from tool receipts and approval policy. |
Use this as a decision checklist: document the required contract first, then choose a small migration candidate if code proof is needed. Do not start by removing tools or integrations until compatibility, config, security policy, operator visibility, and rollback are explicit.
Before writing code, decide which extension surface owns the behavior.
| Work | First stop | Usually do not change |
|---|---|---|
| OpenAI-compatible model endpoint | Custom providers | zeroclaw-runtime |
| New model wire format or provider family | crates/zeroclaw-api/src/model_provider.rs, crates/zeroclaw-providers/, crates/zeroclaw-config/ | Channels, tools |
| New messaging platform | crates/zeroclaw-api/src/channel.rs, crates/zeroclaw-channels/, crates/zeroclaw-config/ | Provider routing |
| New agent-callable capability | crates/zeroclaw-api/src/tool.rs, crates/zeroclaw-tools/, risk policy docs | Channel adapters |
| New memory backend | crates/zeroclaw-api/src/memory_traits.rs, crates/zeroclaw-memory/ | Provider or channel code |
| New hardware/peripheral surface | crates/zeroclaw-api/src/peripherals_traits.rs, crates/zeroclaw-hardware/ | Runtime agent loop |
If the change needs new config, security policy, generated docs, or runtime routing, it is more than a local adapter. Check the architecture map and RFC process before implementation.
Do not duplicate state across config, runtime handles, generated docs, and UI state. Before adding a field or cache, name the source of truth.
| Data | Source of truth |
|---|---|
| Provider family slots, aliases, endpoint defaults, auth fields | crates/zeroclaw-config/src/providers.rs and the typed provider config structs |
| Channel aliases, secrets, allowed peers, channel-local config | crates/zeroclaw-config/src/schema.rs and peer-group/IAM config |
| Tool specs and model-visible descriptions | The Tool implementation's spec(), description(), and schema; Fluent catalogues such as crates/zeroclaw-runtime/locales/en/tools.ftl own localised tool text where the tool is wired through that path |
| Gateway API schema consumed by the dashboard | zeroclaw_gateway::openapi::build_spec() |
| Generated config docs | The config schema generator; do not edit generated output by hand |
| Provider, channel, tool, memory, and peripheral trait contracts | crates/zeroclaw-api/src/model_provider.rs, channel.rs, tool.rs, memory_traits.rs, and peripherals_traits.rs |
| Attribution and logging contracts | crates/zeroclaw-api/src/attribution.rs and Logging architecture |
| Runtime turn execution | crates/zeroclaw-runtime/src/agent/turn/ |
Valid patterns resolve from the source when needed: pass &Config, resolve through a factory, use a closure over the live config handle, or build a per-call materialized view. Avoid storing long-lived snapshots such as allowed_users: Vec<String> inside a channel handle when the canonical data lives in config.
Use this checklist when adding a new first-party extension or materially expanding an existing one.
zeroclaw-api trait. Do not patch the runtime loop just to special-case one integration.Prefer the custom slot or an existing OpenAI-compatible family when the endpoint speaks a supported wire protocol. Add a first-party provider only when the endpoint needs a new family, auth model, capability declaration, or wire translation.
A provider PR usually touches:
crates/zeroclaw-config/src/providers.rs and typed config structs;crates/zeroclaw-providers/src/;Channels are user-visible trust boundaries. Keep platform decoding, deduplication, reply-target construction, sender authorization, and any channel-specific pairing at the channel edge. Do not let unauthenticated or unauthorized events reach the runtime and then rely on the runtime to sort them out.
A channel PR usually touches:
crates/zeroclaw-api/src/channel.rs only when the shared channel contract really changes;crates/zeroclaw-channels/src/;Tools are agent actions, so they must fit the autonomy model. A tool PR should define the tool's risk, arguments, result shape, receipt behavior, and user-facing description.
A tool PR usually touches:
crates/zeroclaw-tools/src/;crates/zeroclaw-runtime/locales/en/tools.ftl;Memory backends must preserve agent/session scoping. Do not bypass the agent-scoped wrapper or store unscoped data because it is easier for one backend.
A memory PR usually touches:
crates/zeroclaw-memory/;Hardware integrations are platform-sensitive and can expose real devices. Keep unsafe calls, permissions, device discovery, and platform gates near the hardware crate. Document required OS packages, udev or permission steps, and failure behavior. If a peripheral is exposed through an agent-callable tool, it also follows the Tool and attribution contracts unless the team deliberately adds a new attribution role.
The RFC process is the canonical source for whether a change is RFC-shaped. For first-party extensions, stop and check it especially when the extension: