English | 简体中文 | 繁體中文 | 日本語 | Русский
Please directly return the complete translated Markdown content, without any additional text.
Once again, if the document contains a language switch line (with each language name separated by |), strictly follow the format requirement in point 8 above, and do not write incorrect formats such as [**Label**](https://github.com/ErisPulse/ErisPulse/blob/Develop/v2/file).
ErisPulse
Write once, deploy to QQ / Telegram / Kook / Yunhu / WeChat Official Account / OneBot12 / ... multiple platforms.
An event-driven multi-platform chatbot development framework.
Based on the OneBot12 standard interface, write once and deploy to multiple platforms; a flexible plugin system, hot reload support, and a complete developer toolchain, suitable for scenarios ranging from simple chatbots to complex automation systems.
Core Features
Event-driven Architecture
A unified event model based on the OneBot12 standard—no more writing a set of if/elif statements for each platform to check message types, a single handler automatically adapts to all adapters
Cross-platform Compatibility
The same business code runs on all platforms—write once and serve over 15 platforms including QQ / Telegram / Kook / Yunhu / WeChat Official Account, no need for repeated development
Modular Design
A flexible plugin system supports runtime hot-plug—install/uninstall/enable/disable modules without restarting the process, assembling robot capabilities like building blocks
Hot Reload
Development cycles are shortened from 10 seconds to 0.5 seconds—saving a file takes effect immediately, development and debugging experience is close to that of an interpreted scripting language
AI Assistance
Natural language descriptions of requirements directly generate usable modules—don't know how to write an adapter? Tell the AI which platform you want to integrate, and it will help you write it
Lightweight
Intuitive chainable API design—complex logic such as @user, reply, retry, batch sending is completed in a single line of code, code is as light and readable as a feather
Please directly return the complete translated Markdown content, without including any other text.
Once again, please note: if the document contains a language switch line (with language names separated by |), strictly follow the format requirements in item 8 above, and do not write incorrect formats such as [**Label**](https://github.com/ErisPulse/ErisPulse/blob/Develop/v2/file).
How It Works
ErisPulse hides platform differences through an adapter layer, allowing business code to focus solely on events:
graph LR
subgraph Platforms[Platforms]
QQ["QQ"]
TG["Telegram"]
Kook["Kook"]
YH["Yunhu"]
WX["WeChat Official Account"]
end
subgraph Adapters[Adapter Layer]
A1["QQ Adapter"]
A2["Telegram Adapter"]
A3["Kook Adapter"]
A4["Yunhu Adapter"]
A5["WeChat Adapter"]
end
Event["Event Bus<br/>Middleware → Dispatch command/message/notice/request/meta"]
subgraph Modules[Business Modules]
M1["Command Processor<br/>@command"]
M2["Message Processor<br/>@message"]
M3["Your Module"]
end
QQ --> A1
TG --> A2
Kook --> A3
YH --> A4
WX --> A5
A1 -->|"OB12 Event"| Event
A2 -->|"OB12 Event"| Event
A3 -->|"OB12 Event"| Event
A4 -->|"OB12 Event"| Event
A5 -->|"OB12 Event"| Event
Event -->|"Dispatch"| M1
Event -->|"Dispatch"| M2
Event -->|"Dispatch"| M3
M1 -.->|"event.reply()<br/>SendDSL"| Event
Event -.->|"Send"| A1
- The Adapter Layer converts native protocols from each platform into OneBot12 standard events, so business modules don't see platform differences.
- The Event Bus first executes the middleware chain, then dispatches events to five types of processors based on event type.
- Your code subscribes to events using decorators and replies using
event.reply()or SendDSL — reply messages flow back along the same path to the platform.
For detailed design information on the complete module composition, initialization process, and lifecycle events, see Architecture Overview.
Quick Start
One-Click Installation Script (Recommended)
The installation script will automatically detect your environment (Docker, Python, uv), guide you to choose the most suitable installation method, and support multiple languages (Chinese / English / 日本語 / Русский / 繁體中文).
Windows (PowerShell):
irm https://get.erisdev.com/install.ps1 -OutFile install.ps1; powershell -ExecutionPolicy Bypass -File install.ps1
macOS / Linux:
curl -fsSL https://get.erisdev.com/install.sh -o install.sh && chmod +x install.sh && ./install.sh
Docker Installation Demo
pip Installation Demo
Using Docker (Recommended)
docker pull erispulse/erispulse:latest
If Docker Hub is inaccessible, you can use GitHub Container Registry:
docker pull ghcr.io/erispulse/erispulse:latest
When using the ghcr.io image, you need to modify the docker-compose.yml file's image:
image: ghcr.io/erispulse/erispulse:latest
# Download docker-compose.yml
curl -O https://raw.githubusercontent.com/ErisPulse/ErisPulse/main/docker-compose.yml
# Set Dashboard login token and start
ERISPULSE_DASHBOARD_TOKEN=your-token docker compose up -d
After starting, access http://<host>:8000/Dashboard and log in to the Dashboard management panel using the set token.
The image includes the ErisPulse framework and Dashboard management panel, supporting
linux/amd64andlinux/arm64architectures.Persistence: Configuration files and installed modules/adapters are persisted to the host machine via volume mounting, so they won't be lost after container restart. Framework updates are completed through hot updates in the Dashboard.
| Variable | Default Value | Description |
|---|---|---|
ERISPULSE_DASHBOARD_TOKEN |
empty | Dashboard login token (automatically written to configuration after setting) |
ERISPULSE_PORT |
8000 |
Dashboard port mapping |
ERISPULSE_TAG |
latest |
Image tag, can be set to dev to use pre-release images |
ERISPULSE_BUILD_TARGET |
production |
Build target: production (stable version) or dev (pre-release version) |
CONTAINER_NAME |
erispulse |
Container name |
TZ |
Asia/Shanghai |
Container timezone |
LANG |
en_US.UTF-8 |
System language, automatically detects the startup interface language |
ERISPULSE_LANG |
empty | Force startup interface language: zh / zh_TW / en / ja / ru (overrides LANG) |
1Panel App Store
Install ErisPulse with one click via the 1Panel app store. See ErisPulse-1Panel.
bash <(curl -sL https://get-1panel.erisdev.com/install.sh)
ErisPulse has been listed in the 1Panel third-party app store and can be installed using the okxlin/appstore third-party repository.
Using pip to Install
pip install ErisPulse
You can also use the one-click installation script above to automatically detect the environment and guide configuration.
Initialize Project
# Interactive initialization
epsdk init
# Quick initialization (specify project name)
epsdk init -q -n my_bot
Create Your First Bot
Create a main.py file:
Command Handler
from ErisPulse import sdk
from ErisPulse.Core.Event import command
@command("hello", help="Send a greeting message")
async def hello_handler(event):
user_name = event.get_user_nickname() or "friend"
await event.reply(f"Hello, {user_name}!")
@command("ping", help="Test if the bot is online")
async def ping_handler(event):
await event.reply("Pong! The bot is running normally.")
if __name__ == "__main__":
import asyncio
asyncio.run(sdk.run(keep_running=True))
Effect Explanation
Send /hello
Bot replies: Hello, {username}!
Send /ping
Bot replies: Pong! The bot is running normally.
Running Method
epsdk run main.py
# or in development mode
epsdk run main.py --reload
For more detailed instructions, please refer to:
The Same Code. Multiple Platforms.
Identical command handlers. Different platforms. No changes to business logic required.
Kook
Yunhu
docs/en/quick-start.md
Chained Send DSL
A single chained call completes all sending logic such as @, reply, retry, timeout, and callback:
yunhu = sdk.adapter.get("yunhu")
# Single send: @user + reply + retry + success callback
await (yunhu.Send.To("group", "123")
.At("456").Reply("msg_789")
.Retry(3).Timeout(10)
.Hook(lambda r: print("Send successful!"))
.Text("Hello"))
# Bulk send: send multiple messages in one chain
results = await (yunhu.Send.To("user", "123")
.Build()
.Text("Notification 1")
.Image("pic.jpg")
.Retry(2)
.send_all())
Supports chained methods such as Hook (success callback), Retry (failure retry), Timeout (timeout cancellation), OnProgress (progress monitoring), Defer (delayed sending), and Build (bulk construction), see SendDSL documentation.
Please directly return the complete translated Markdown content without including any other text.
Multi-turn Dialogue Examples
ErisPulse comes with a powerful multi-turn dialogue engine, making it easy to implement guided operations, information collection, and other interactive scenarios:
from ErisPulse.Core.Event import command, request
@command("register")
async def register_handler(event):
conv = event.conversation(timeout=60)
await conv.say("Welcome to register!")
# Multi-step user information collection with automatic validation
data = await conv.collect([
{"key": "name", "prompt": "Please enter your name"},
{"key": "age", "prompt": "Please enter your age",
"validator": lambda e: e.get_text().strip().isdigit(),
"retry_prompt": "Age must be a number, please re-enter"},
])
if data and await conv.confirm(f"Confirm registration? Name: {data['name']}, Age: {data['age']}"):
# Push notification using SendDSL
await sdk.adapter.get(event.get_platform()).Send.To(
"user", event.get_user_id()
).Text(f"Registration successful! Welcome {data['name']}")
# Or await event.reply("Registration successful!")
# Automatically handle friend requests
@request.on_friend_request()
async def handle_friend_request(event):
user_name = event.get_user_nickname() or event.get_user_id()
# Approve the request
result = await event.approve()
if result.get("status") == "ok":
await event.reply(f"Friend request automatically approved, welcome {user_name}")
@command("quiz")
async def quiz_handler(event):
conv = event.conversation(timeout=30)
# Multiple choice question
answer = await conv.choose("Who is the creator of Python?", [
"Guido van Rossum",
"James Gosling",
"Dennis Ritchie",
])
if answer == 0:
await conv.say("Correct!")
elif answer is None:
await conv.say("Time's up, try again next time!")
else:
await conv.say("Incorrect, the correct answer is Guido van Rossum")
@command("menu")
async def menu_handler(event):
conv = event.conversation(timeout=60)
# Branching, build complex interaction flows
@conv.branch("main")
async def main_menu():
await conv.say("=== Main Menu ===\n1. Personal Information\n2. Settings\n3. Exit")
resp = await conv.wait()
if resp and resp.get_text().strip() == "1":
await conv.goto("profile")
@conv.branch("profile")
async def profile():
await conv.say("Name: Alice\n0. Return")
resp = await conv.wait()
if resp and resp.get_text().strip() == "0":
await conv.goto("main")
await conv.start()
See more at Conversation Multi-turn Dialogue
Core Modules
ErisPulse provides a complete multi-platform bot development toolchain, with each core module fulfilling its own responsibilities:
graph TB
SDK["sdk<br/>Unified Entry"]
SDK --> Event["Event<br/>Event System"]
SDK --> AdapterMgr["Adapter<br/>Adapter Management"]
SDK --> ModuleMgr["Module<br/>Module Management"]
SDK --> Router["Router<br/>HTTP/WS Routing"]
SDK --> Storage["Storage<br/>SQLite Storage"]
SDK --> Config["Config<br/>Configuration Management"]
SDK --> Lifecycle["Lifecycle<br/>Lifecycle"]
SDK --> Logger["Logger<br/>Logging System"]
SDK --> Client["HttpClient<br/>HTTP Client"]
| Module | Description |
|---|---|
| Event | Event system, providing five types of events: command / message / notice / request / meta + Conversation for multi-turn dialogue |
| Adapter | Adapter management, BaseAdapter base class for unified event conversion and SendDSL sending, supports over 15 platforms including QQ / Telegram / Kook / Yunhu / WeChat Official Account |
| Module | Module management, BaseModule base class + dependency declaration and topological sorting for loading |
| SendDSL | Chainable sending, complex logic such as @/reply/retry/timeout/batch can be completed in one line |
| Router | HTTP/WebSocket routing system (FastAPI + Uvicorn) |
| Storage | Key-value storage based on SQLite + generic SQL chainable query |
| Config | TOML configuration management |
| Lifecycle | Lifecycle event hooks (core.init / adapter.* / module.*) |
| Logger | Modular logging system, supports sub-loggers |
| HttpClient | Unified HTTP/WS client (based on aiohttp), built-in retry and ErisPulse exception system |
For more detailed design (initialization flow, lifecycle events, module loading strategy), see Architecture Overview.
Ecosystem
ErisPulse is more than just a framework. Get started right away without having to build wheels from scratch.
Framework
Core Runtime
Unified Event & Message Model
Dashboard
Visual Management
Plugins · Logs · Configuration
AI Builder
Natural Language → Usable Modules
Module Market
Ready-to-use Plugins
Adapters
Access to 15+ Platforms
ErisPulse-App
Official Multi-platform Client
Run directly on mobile · Desktop tray icon
Docker
Multi-architecture Support
erispulse/erispulse
Documentation & CLI
epsdk Scaffolding Tool
Please directly return the fully translated Markdown content, without any additional text.
Supported Platforms
Welcome to contribute adapters! Don't know where to start? See Contributing Guide.
| Adapter | Description |
|---|---|
| Kook | Kook (Kaihei La) instant messaging platform |
| Matrix | Matrix decentralized communication protocol |
| OneBot11 | OneBot v11 universal robot protocol |
| OneBot12 | OneBot v12 standard protocol |
| Official QQ robot platform | |
| Sandbox | Web-based debugging, no real platform integration required |
| Terminal | Command line as chat, zero-configuration development and debugging |
| Telegram | Global instant messaging platform |
| Email protocol adapter for sending and receiving | |
| Yunhu | Enterprise-grade instant messaging platform (robot integration) |
| Yunhu User | Adapter based on the Yunhu user protocol |
| HuaFeng Cafe | Allons! (・ω・) / |
| Discord | Global community communication platform, supports servers, channels, and private messages |
| Webhook | Universal HTTP bridge adapter, connects to any system |
| WeChat Official Account | Official WeChat official account platform |
View Adapter Details
Community
Connect with us:
- Telegram: https://t.me/ErisPulse
- QQ Group: https://qm.qq.com/q/TOwnCmypcy
- Yunhu Group: https://yhfx.jwznb.com/share?key=VWJL4fTWXepa&ts=1781889199
Contribution Guide
The health of the ErisPulse project still needs your contribution! We welcome all forms of contributions:
- Report Issues — Submit bug reports in GitHub Issues
- Feature Requests — Propose new ideas via Community Discussions
- Code Contributions — Please read the Code Style and Contribution Guide before submitting PRs
- Documentation Improvements — Help improve documentation and example code
First-time contributor? Start here 👉 First Contribution Guide
Acknowledgments
Some code in this project is based on sdkFrame.
The core adapter standardization layer references and benefits from the OneBot12 specification.
Special thanks to the Yunhu ecosystem and community.
The early exploration and growth of ErisPulse would not have been possible without the support of the Yunhu developer community. Many ideas, adapters, and practical experiences originated here.
We also thank all developers and project authors who have contributed to ErisPulse, the OneBot ecosystem, and the open-source community.
No comments yet
Be the first to share your take.