[OpenClaw] Practical Guide to Channel Plugin Development

From Zero to One: Develop Your First OpenClaw Message Channel Plugin
GitHub: github.com/chungeplus/yeizi-openclaw-plugin
Overview
What Is OpenClaw?
OpenClaw is an open-source AI agent framework that supports extending message channels through plugins. Developers can write Channel Plugins to integrate with various messaging platforms (such as Feishu, WeChat, Slack, etc.), enabling the AI agent to receive and reply to messages.
What a Channel Plugin Does
A Channel Plugin is an extension module of OpenClaw responsible for:
- Establishing connections with external messaging platforms
- Receiving user messages
- Passing messages to OpenClaw for AI processing
- Sending AI replies back to users
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ User │ ───► │ Channel │ ───► │ OpenClaw │
│ (Feishu/ │ │ Plugin │ │ AI │
│ WeChat) │ │ │ │ │
└─────────────┘ └─────────────┘ └─────────────┘
▲ │
│ ▼
└──────────────────────────────────────────┘
(AI Reply)
Plugin Types
OpenClaw supports multiple plugin types:
| Type | Description |
|---|---|
| Channel Plugin | Integrates with messaging platforms and receives/sends messages |
| Skill Plugin | Extends AI skills |
| Tool Plugin | Adds AI tools |
This guide mainly explains the development of Channel Plugins.
System Architecture
Overall Architecture Diagram
┌────────────────────────────────────────────────────────────────┐
│ User Browser │
├────────────────────────────────────────────────────────────────┤
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Web Frontend (Chat Page) │ │
│ │ • User inputs messages │ │
│ │ • Displays AI replies │ │
│ │ • Real-time WebSocket communication │ │
│ │ • Plugin configuration display │ │
│ └──────────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────┘
▲ │
│ │ WebSocket
AI Reply │ User Message
│ ▼
└────────────────────────────────────────────────►
│
▼
┌────────────────────────────────────────────────────────────────┐
│ Web Backend Service │
├────────────────────────────────────────────────────────────────┤
│ • Authentication service (AppKey + AppSecret) │
│ • WebSocket service │
│ • Message routing │
│ • Configuration query API (/api/config) │
└────────────────────────────────────────────────────────────────┘
▲ │
│ │ WebSocket
AI Reply │ Message Forwarding
│ ▼
└────────────────────────────────────────────────►
│
▼
┌────────────────────────────────────────────────────────────────┐
│ OpenClaw Plugin │
├────────────────────────────────────────────────────────────────┤
│ • WebSocket client (receives/sends messages) │
│ • dispatchReplyWithBufferedBlockDispatcher │
│ • ChannelDock configuration │
│ • YeiziDock defines plugin capabilities │
└────────────────────────────────────────────────────────────────┘
│
AI Reply
(OpenClaw API)
Message Flow
Message Sending Flow (User → OpenClaw)
- The user enters a message
- The frontend sends the message to the backend through WebSocket
- The backend forwards the message to the OpenClaw plugin
- The plugin constructs ctxPayload
- It calls finalizeInboundContext
- It calls dispatchReplyWithBufferedBlockDispatcher to trigger AI processing
Message Reply Flow (OpenClaw → User)
- OpenClaw AI processing completes
- The deliver callback of dispatchReplyWithBufferedBlockDispatcher is triggered
- The plugin sends the reply to the backend through WebSocket
- The backend pushes it to the frontend through WebSocket
- The frontend displays the AI reply
Core Concepts
Channel
A Channel in OpenClaw represents a specific message source or destination. Each Channel Plugin implements one Channel.
ChannelDock
ChannelDock defines a Channel’s capabilities and metadata:
export const yeiziDock: ChannelDock = {
id: "yeizi",
capabilities: {
chatTypes: ["direct"], // Supports private chat
blockStreaming: true, // Supports streaming responses
},
};
ChannelPlugin
ChannelPlugin is the core implementation of the plugin and includes:
- meta: plugin metadata (name, description, documentation link)
- capabilities: capability configuration (supported chat types, media support, etc.)
- config: account management configuration
- security: security policy
- status: status management
- outbound: outbound message handling
- gateway: gateway configuration (starting accounts, handling messages)
Runtime
Runtime is the runtime environment provided by OpenClaw. The plugin interacts with the OpenClaw core through Runtime:
import { getRuntime } from './runtime';
const runtime = getRuntime();
// Use runtime for message processing
runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher({...});
Account
One Channel can be configured with multiple accounts, and each account represents an independent connection:
interface ResolvedAccount {
accountId: string; // Account ID
enabled: boolean; // Whether enabled
configured: boolean; // Whether configured
name?: string; // Account name
config: AccountConfig; // Account configuration
}
Development Environment Setup
Requirements
- Node.js: >= 18.0.0
- npm or pnpm
- OpenClaw: >= 2026.3.12
- Code editor (VS Code recommended)
Create a Plugin Project
# Create the project directory
mkdir my-channel-plugin
cd my-channel-plugin
# Initialize an npm project
npm init -y
# Install TypeScript
npm install typescript @types/node --save-dev
You can then initialize the TypeScript configuration and continue building the project.
Plugin Project Structure
A standard Channel Plugin project structure:
my-channel-plugin/
├── src/
│ ├── channel.ts # Core implementation
│ ├── accounts.ts # Account management
│ ├── config-schema.ts # Configuration validation
│ ├── runtime.ts # Runtime
│ ├── types.ts # Type definitions
│ └── websocket-client.ts # WebSocket
├── scripts/
│ └── setup.mjs # Installation script
├── index.ts # Entry point
└── package.json
A more complete Yeizi project structure example:
yeizi/
├── web-channel/ # Web project
│ ├── frontend/ # Frontend project (Vue 3 + TypeScript)
│ │ ├── src/
│ │ │ ├── components/ # Vue components
│ │ │ ├── stores/ # Chat state management
│ │ │ └── App.vue # Main app component
│ │ └── package.json
│ ├── backend/ # Backend project (Express.js)
│ │ ├── src/
│ │ │ ├── routes/
│ │ │ │ ├── auth.ts # Auth routes
│ │ │ │ └── config.ts # Config query routes
│ │ │ ├── services/
│ │ │ │ ├── auth.ts # Auth service
│ │ │ │ ├── config.ts # Config service
│ │ │ │ └── websocket.ts # WebSocket management
│ │ │ └── index.ts # Service entry
│ │ ├── .env # Environment variables
│ │ └── package.json
│ └── package.json
│
└── yeizi-plugin/ # OpenClaw plugin project
├── src/
│ ├── accounts.ts # Account management utilities
│ ├── channel.ts # Channel Plugin implementation
│ ├── config-schema.ts
│ ├── runtime.ts
│ ├── types.ts
│ └── websocket-client.ts
├── scripts/
├── index.ts
└── package.json
Build and Install
# Build the plugin
npm run build
# Install the plugin
node scripts/setup.mjs your-app-key your-app-secret http://localhost:3000
# Restart OpenClaw
openclaw restart
Debugging and Testing
Logging
Use the log object provided by OpenClaw for logging:
log?.info(`[MyChannel] Message received`);
log?.warn(`[MyChannel] Warning message`);
log?.error(`[MyChannel] Error: ${error.message}`);
Common Troubleshooting
Issue 1: deliver callback is not triggered
Possible causes:
- OpenClaw version < 2026.3.12
- The AI model is not configured correctly
- blockStreaming configuration issue
Solutions:
- Ensure the OpenClaw version is >= 2026.3.12
- Check whether the AI model configuration is correct
- Ensure blockStreaming: true
Issue 2: WebSocket connection fails
Checklist:
- Is the backend service running?
- Are AppKey / AppSecret correct?
- Is the network connection working properly?
Issue 3: The AI does not reply
Checklist:
- Is the AI model API key correct?
- Is the model supported?
- Can the network access the AI service?
Testing Recommendations
- Test the backend service locally first
- Start with simple message tests
- Gradually add more complex features
- Use logs to trace issues
Practical Example: The Yeizi Plugin
Yeizi is a Web Channel plugin used to connect a Web frontend and OpenClaw through WebSocket.
Key Implementation Points
The core of the Yeizi plugin is:
- Receive frontend messages through WebSocket
- Build ctxPayload and call dispatchReplyWithBufferedBlockDispatcher
- Send AI replies inside the deliver callback
Web Backend
The Yeizi plugin requires a Web backend service that provides:
- /api/auth/token - authentication endpoint
- /api/config - configuration query endpoint
- /ws/plugin - plugin WebSocket endpoint
- /ws - frontend WebSocket endpoint
Frequently Asked Questions
Q1: How should I choose a Channel ID?
A Channel ID should:
- Uniquely identify the plugin
- Use lowercase letters and numbers
- Avoid conflicts with existing plugins
- Be short and easy to remember
Q2: How do I support multiple accounts?
Add multiple account configurations in the config. Each account can represent a separate connection instance, and the plugin can choose the appropriate account based on the runtime context.
Q5: How do I publish the plugin?
# 1. Log in to NPM
npm login
# 2. Publish
npm publish --access public
Conclusion
Developing an OpenClaw Channel Plugin requires understanding its core concepts and architecture. Through this guide, you should now be able to:
- Understand OpenClaw’s plugin system
- Master the development workflow of a Channel Plugin
- Implement a complete message channel plugin
- Debug and publish the plugin
Happy coding!
API Endpoints
Backend API
| Endpoint | Method | Description |
|---|---|---|
/api/config | GET | Get plugin configuration information |
/api/auth/token | POST | Plugin authentication to obtain a token |
/health | GET | Health check |
/ws | WebSocket | Frontend connection endpoint |
/ws/plugin | WebSocket | Plugin connection endpoint |
Related Resources
- Example plugin: Feishu plugin
- Yeizi plugin source code

