Skip to content

Latest commit

 

History

2,122 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ErisPulse

English | 简体中文 | 繁體中文 | 日本語 | Русский

ErisPulse

Write once, deploy to QQ / Telegram / Kook / Yunhu / WeChat Public 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; with a flexible plugin system, hot reload support, and a complete developer toolchain, suitable for scenarios ranging from simple chatbots to complex automation systems.

PyPI Python OneBot 11 OneBot 12 Docker License Downloads Ruff Socket Documentation DeepWiki Module Market Discussion



Core Features


Event-Driven Architecture

Event-Driven Architecture

Based on the unified event model of OneBot12, a single handler adapts to all adapters.


Cross-Platform Compatibility

Cross-Platform Compatibility

QQ / Telegram / Kook / Yunhu and 15+ platforms, business code remains unchanged.


Modular Design

Modular Design

Hot-plug plugins without restart, scope controlled by platform / Bot / session.


Hot Reload

Hot Reload

Save and apply changes instantly, lightweight and seamless.


AI Assistance

AI Assistance

Describe requirements in natural language, directly generate usable modules.


Lightweight and Elegant

Lightweight and Elegant

Chainable API: @ user, reply, retry, batch send, all in one line.


How It Works

ErisPulse uses an adapter layer to abstract platform differences, allowing business code to focus solely on events:

graph LR
    subgraph Platforms[Platforms]
        QQ["QQ"]
        TG["Telegram"]
        Kook["Kook"]
        YH["Yunhu"]
        WX["WeChat Public 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 Handler<br/>@command"]
        M2["Message Handler<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
Loading
  • Adapter Layer converts native platform protocols into OneBot12 standard events, so business modules are unaware of platform differences.
  • Event Bus executes the middleware chain first, then dispatches events to five types of handlers based on event type.
  • Your Code subscribes to events using decorators, and replies using event.reply() or SendDSL. Replies flow back through the same path to the platform.

For a detailed overview of the module composition, initialization process, and lifecycle events, see Architecture Overview.


Quick Start

One-Click Installation Script (Recommended)

The installation script automatically detects your environment (Docker, Python, uv), guides you to the most suitable installation method, and supports multiple languages (Chinese/English/Japanese/Russian/Traditional Chinese).

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

install_pip.mp4

pip Installation Demo

install_docker.mp4

Using Docker (Recommended)

docker pull erispulse/erispulse:latest
Docker Hub Unavailable?

If Docker Hub is inaccessible, you can use GitHub Container Registry:

docker pull ghcr.io/erispulse/erispulse:latest

When using the ghcr.io image, modify docker-compose.yml to update the image:

image: ghcr.io/erispulse/erispulse:latest
Quick Start
# 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 using the set token.

The image includes the ErisPulse framework and Dashboard management panel, supporting linux/amd64 and linux/arm64 architectures.

Persistence: Configuration files and installed modules/adapters are persisted to the host via volume mounts, so they are not lost after container restart. Framework updates are completed through Dashboard hot updates.

Docker Environment Variables
Variable Default Description
ERISPULSE_DASHBOARD_TOKEN empty Dashboard login token (automatically written to config when set)
ERISPULSE_PORT 8000 Dashboard port mapping
ERISPULSE_TAG latest Image tag, can be set to dev for pre-release images
ERISPULSE_BUILD_TARGET production Build target: production (stable) or dev (pre-release)
CONTAINER_NAME erispulse Container name
TZ Asia/Shanghai Container timezone
LANG en_US.UTF-8 System language, automatically detects 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 is available in the 1Panel third-party app store, and can be installed using the okxlin/appstore third-party repository.

Using pip Installation

pip install ErisPulse

You can also use the one-click installation script above, which automatically detects the environment and guides 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 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 bot is online")
async def ping_handler(event):
    await event.reply("Pong! 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! Bot is running normally.


Running Method

epsdk run main.py
# Or in development mode
epsdk run main.py --reload

For more detailed instructions, see:


Same Code, Multiple Platforms.

Identical command handlers. Different platforms. No changes to business logic.

Kook

Kook Demo

QQ

QQ Demo

Yunhu

Yunhu Demo

Chainable Send DSL

A single chain call completes all sending logic, including @, 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: one chain sends multiple messages
results = await (yunhu.Send.To("user", "123")
                .Build()
                .Text("Notification 1")
                .Image("pic.jpg")
                .Retry(2)
                .send_all())

Supports Hook (success callback), Retry (failure retry), Timeout (timeout cancel), OnProgress (progress monitoring), Defer (delayed send), Build (bulk build), and other chainable methods. See SendDSL Documentation.


Multi-Turn Conversation Example

ErisPulse includes a powerful multi-turn conversation engine, making it easy to implement guided operations and information collection 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 collection of user information, 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 approved automatically, welcome {user_name}")
See More Conversation API (Branching / Selection / Persistence)
@command("quiz")
async def quiz_handler(event):
    conv = event.conversation(timeout=30)
    
    # Option-based 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("Timed out, 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, building complex interaction flow
    @conv.branch("main")
    async def main_menu():
        await conv.say("=== Main Menu ===\n1. Personal Info\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 Conversation Multi-Turn Dialogue


Core Modules

ErisPulse provides a complete multi-platform chatbot development toolchain, with each core module serving its own purpose:

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"]
Loading
Module Description
Event Event system, providing command / message / notice / request / meta event types + Conversation multi-turn dialogue
Adapter Adapter management, BaseAdapter base class for unified event conversion and SendDSL sending, supporting 15+ platforms including QQ / Telegram / Kook / Yunhu / WeChat Public 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 in one line
Router HTTP/WebSocket routing system (FastAPI + Uvicorn)
Storage SQLite-based key-value storage + general SQL chain 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), with built-in retry and ErisPulse exception system

For more design details (initialization process, lifecycle events, module loading strategy), see Architecture Overview.


Scope — Three-Dimensional Permission Control

Without modifying any module code, declare "what is effective in what scope" in the configuration:

[ErisPulse.scope.platforms.onebot11]
modules = ["Chat", "Tool*"]           # ① Module level: only these modules are open on this platform (glob / regex)

[ErisPulse.scope.identity.users.onebot11]
deny = ["u_bad", "spam_*"]            # ② Identity level: events from blacklisted users are discarded

[ErisPulse.scope.actions.MyModule]
send = { allow = ["Text"] }           # ③ Outbound level: this module only allows sending text
api = { deny = ["set_*", "leave_*"] } #    and prohibits management APIs
# Runtime also modifiable, immediate effect (supports dictionary-style read/write via dot notation)
sdk.scope.set_action("MyModule", "api", deny=["set_*"])

See Scope


Event Override — Without Modifying Module Code, Override Behavior of Any Event Type

# Override message handler trigger conditions (AND with code conditions; supports all types: meta/message/notice/request/command)
[ErisPulse.event.overrides.message.ChatModule]
pattern = "闲聊*"

# Override command implementation parameters (master / hidden / aliases / prefix, user priority)
[ErisPulse.event.overrides.command.MyModule.restart]
master = true

See Event Override


Ecosystem

ErisPulse is not just a framework. Start using it right away, no need to build wheels from scratch.

Framework

Core runtime

Unified event & message model

Dashboard

Visual management

Plugins · Logs · Configuration

Online Demo →

AI Builder

Natural language → usable module

Experience Now →

Module Market

Ready-to-use plugins

Explore Modules →

Adapters

15+ platform integrations

ErisPulse-App

Official multi-platform client

Mobile directly run · Desktop tray always on

Download and Install →

Docker

Multi-architecture support

erispulse/erispulse

Documentation & CLI

erisdev.com

epsdk scaffolding tool


Supported Platforms

We welcome contributions to adapters! Not sure where to start? See Contribution Guide.

Adapter Description
Kook Kook Kook (open black room) instant messaging platform
Matrix Matrix Matrix decentralized communication protocol
OneBot OneBot11 OneBot v11 general robot protocol
OneBot OneBot12 OneBot v12 standard protocol
QQ QQ QQ official robot platform
Sandbox Sandbox Web terminal debugging, no need to connect to real platform
Terminal Terminal Command line chat, zero configuration development and debugging
Telegram Telegram Global instant messaging platform
Email Email Email protocol adapter
Yunhu Yunhu Enterprise-level instant messaging platform (robot access)
Yunhu Yunhu User User protocol-based Yunhu adapter
HuaFeng Coffee House Allons! (・ω・) /
Discord Discord Global community communication platform, supports servers, channels, and private messages
Webhook Webhook General HTTP bridge adapter, connects to any system
WechatMp WeChat Public Account Official WeChat public account platform

See Adapter Details


Community

Connect with us:


Contribution Guidelines

The health of the ErisPulse project still needs your contribution! We welcome contributions in various forms:

  1. Report Issues — Submit bug reports in GitHub Issues
  2. Feature Requests — Propose new ideas through Community Discussions
  3. Code Contributions — Read Code Style and Contribution Guidelines before submitting PRs
  4. Documentation Improvements — Help improve documentation and example code

First-time contributor? Start here 👉 First Contribution Practice

Join Community Discussions


Acknowledgments

Thanks

Some code in this project is based on sdkFrame.

The core adapter standardization layer is referenced and benefited 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 were born here.

We also thank all developers and project authors who have contributed to ErisPulse, OneBot, and the open-source community.

About

Event-driven multi-platform bot framework with Dashboard, Docker, hot-reload & module marketplace | 事件驱动的多平台机器人框架 — 一次编写部署 QQ/Telegram/Kook/云湖/Matrix/邮件等 15+ 平台

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

57 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages