Creating a Custom Protocol
Relevant source files
The following files were used as context for generating this wiki page:
OneBots protocols serve as the export layer for the gateway. They transform internal CommonEvent objects into specific wire formats—such as OneBot v11/v12, Satori, or Milky—and handle inbound API calls from downstream clients.
Sources: README.en.md:12-19, AGENTS.md:10-15
Core Architecture
A Protocol in OneBots acts as the bridge between the internal unified event model and external consumer applications. It resides at the top of the internal data stack, receiving events from the Account layer and passing actions down to the Adapter layer.
System Hierarchy
The following class diagram illustrates the relationship between the main application, adapters, accounts, and the protocol implementation.
Implementation Steps
To create a new protocol, you must implement the Protocol abstract class and register it with the ProtocolRegistry.
1. Define the Package Structure
Create a directory in protocols/ (e.g., protocols/my-protocol/protocol/). The package must include:
package.json: Defining the package name (e.g.,@onebots/protocol-my-protocol).src/index.ts: The entry point for registration.src/protocol.ts: The class implementation inheriting fromProtocol.
Sources: CONTRIBUTING.md:460-470, AGENTS.md:70-90
2. Implement the Protocol Class
You must extend the Protocol base class and provide logic for the lifecycle and data transformation methods.
| Method | Role |
|---|---|
start() | Initializes resources, such as HTTP/WebSocket servers or routes. |
stop() | Cleans up resources, closes connections, and removes listeners. |
dispatch(event) | Converts internal CommonEvent to the protocol's wire format and pushes to clients. |
format(event, payload) | Formats the data according to the protocol specification. |
apply(action, params) | Processes inbound API calls from clients and maps them to Adapter actions. |
Sources: CONTRIBUTING.md:472-498, architecture.html:185-195
3. Register the Protocol
Use the ProtocolRegistry to make the protocol available to the application.
ProtocolRegistry.register('my-protocol', 'v1', MyProtocolClass, {
name: 'my-protocol',
displayName: 'My Custom Protocol',
description: 'A description of what this protocol does.',
versions: ['v1'],
});
Sources: CONTRIBUTING.md:500-505, architecture.html:200-205
Data Flow Logic
Protocols handle two distinct directions of data: Upstream (Events) and Downstream (API Actions).
Upstream: Event Transformation
When the platform generates an event, the Adapter normalizes it into a CommonEvent. The Protocol then reformats this into the target standard.
Downstream: API Execution
When a client calls an API, the Protocol validates the request and maps it to the specific Adapter implementation.
Key Considerations
Authentication
Protocols must implement authentication checks. Standard implementations typically support access_token via the Authorization: Bearer header or URL query parameters.
Sources: tests/PROTOCOL_AUTH_HEARTBEAT.md:15-30, protocols/satori-v1/protocol/src/tests/format.test.ts:160-180
Event Filtering
The filterFn property allows the protocol to ignore specific events based on user configuration, preventing unnecessary traffic to downstream clients.
Sources: architecture.html:194, protocols/satori-v1/protocol/src/tests/format.test.ts:35-40
Multi-Version Support
A single protocol package can register multiple versions. Each version is instantiated separately per account, allowing a single account to expose multiple protocol standards simultaneously.
Sources: README.en.md:45-50, architecture.html:215-225
Summary
Creating a custom protocol involves implementing a transformation layer that maps OneBots' internal CommonEvent and Adapter actions to a specific external standard. By following the Protocol abstract class structure and registering the implementation in the ProtocolRegistry, developers can extend OneBots to support any IM protocol or proprietary API.
Sources: CONTRIBUTING.md:460-510, AGENTS.md:180-190