Documentation Index
Fetch the complete documentation index at: https://docs.wednesdayai.dev/llms.txt
Use this file to discover all available pages before exploring further.
Write your first plugin
WednesdayAI’s core is intentionally small. Features that are specific to a use case, platform, or workflow belong in plugins — not in core. This keeps the core stable and the system extensible without requiring a fork. A plugin is a Node.js package that registers one or more of the following via the plugin SDK:- Agent tools — actions the AI can invoke during a conversation
- Hooks — lifecycle callbacks (transform inputs, capture outputs, react to events)
- Channel adapters — new chat platform integrations
- HTTP routes — custom endpoints on the gateway
Prerequisites
- Node.js ≥ 22.12.0
- A running WednesdayAI instance for testing
- TypeScript familiarity — the plugin SDK is fully typed
Extension points overview
Before writing code, understand where plugins touch the system:| Extension point | What it owns | SDK type |
|---|---|---|
| Agent tool | An action the AI can call (search, fetch, compute) | AnyAgentTool |
| Hook | A lifecycle callback (before/after LLM call, context collection) | PluginHook* |
| Channel adapter | A new chat platform | ChannelPlugin |
| HTTP route | A custom endpoint on the gateway | GatewayRequestHandler |
api.register*() method on the OpenClawPluginApi object passed to your register function.
Step 1: Scaffold the plugin
Create a directory for your plugin. The directory name must match the pluginid exactly.
"type": "module" to package.json — the plugin SDK uses ESM:
tsconfig.json:
Step 2: Write the manifest
Createopenclaw.plugin.json at the plugin root. This file is required — the runtime will not load the plugin without it.
The manifest is plain JSON (not JSON5):
idmust match the directory name exactly.configSchemais required. If your plugin has no config, use{ "type": "object", "additionalProperties": false }.additionalProperties: falseensures typos in user config are caught, not silently ignored.- The manifest is plain JSON — do not add comments or trailing commas.
- Declaring a field in
requiredmeans the runtime rejects the plugin config at load time if the field is absent. If you also guard for a missing value insideexecute(), that guard is belt-and-suspenders for deployments where config validation may be bypassed (e.g. direct API calls). Both are fine to have together.
Step 3: Write the plugin entry point
The plugin’s entry exports a defaultregister function. This function is called by the runtime when the plugin is loaded.
Create src/index.ts:
- Import from
openclaw/plugin-sdk, not from relative paths into core. Relative core imports (../../src/...) work in bundled extensions but break in installed plugins. - Tool names are not deduplicated at registration time. If two tools share a name, both are registered and runtime resolution order determines which is called. Use a unique, namespaced name (e.g.
my-plugin_my_tool) to avoid conflicts.
Async safety
Theregister function may be synchronous or async. Use async if you need to perform startup I/O (reading a config file, pinging an API). The key constraint is: don’t block indefinitely.
Tool execute() functions are always async and run when the AI decides to call the tool. A slow execute() does not block the gateway — but it does block the user’s reply until it completes.
Do not do this:
description field.
Step 4: Register as optional
By default, registered tools are available to all agents. If your tool is not universally useful (makes outbound network requests, uses a paid API, has side effects), register it as optional:tools.allow key in their WednesdayAI config:
Step 5: Access plugin config in execute
If your manifest declares aconfigSchema, users set values under the plugin’s id in their WednesdayAI config. The config is available on the api object passed to register. Capture it in a closure so execute() can access it:
Step 6: Build and install locally
openclaw plugins list:
Step 7: Test it
Send a message to your WednesdayAI bot that should invoke the tool. If you registered it as optional, first add"my_tool" to tools.allow in your WednesdayAI config (see Step 4).
To watch tool calls in the logs on Linux:
What’s next
- Plugin manifest reference — all manifest fields and their effects
- Plugin SDK reference — full exported surface with types
- Writing a hook — lifecycle callbacks for context, LLM input/output, and model call events
- Writing a channel adapter — add a new chat platform
- Publishing a plugin — how the managed plugin lifecycle works