Framework
nonebot/nonebot2 avatar
nonebot/nonebot2

NoneBot2: a Python async chatbot framework that treats each chat platform as a plugin

跨平台 Python 异步聊天机器人框架 / Asynchronous multi-platform chatbot framework written in Python

7,723 stars661 forksPythonMIT

At a glance

What is it?
NoneBot2 is an MIT-licensed asynchronous Python framework for building chatbots that run on QQ, Telegram, Feishu and other platforms through adapters. Its value is the plugin and matcher layer, not the transport, and that is also where its learning curve sits.
Who is it for?
Adopt NoneBot2 if you want one Python codebase driving several chat platforms and you are comfortable with async/await and Pydantic-style configuration. Skip it if you need a bot you can configure entirely from a web UI, or if you only ever target one platform and a thin SDK would do.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 9 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem NoneBot2 solves is platform churn, not message handling

A bot that answers questions in a group chat is easy to write and hard to keep alive. The protocol underneath it changes: QQ bots moved through CQHTTP, then OneBot v11 and v12, then the official QQ Bot API; Telegram and Feishu each have their own event shapes. NoneBot2's answer is to put a stable plugin API on top and push every protocol into an adapter. The README describes it as a cross-platform asynchronous Python bot framework, and the badge row names OneBot v11, OneBot v12, QQ Bot, Telegram and Feishu as the targets it advertises.

The audience is narrower than the tagline suggests. This is a framework for people who write Python for a living and want their bot logic to be ordinary Python modules, not a visual flow builder. The pyproject.toml classifier says Production/Stable, and the package requires Python 3.10 or newer, so the floor is a modern interpreter with async/await and structural pattern matching available.

Adapters carry the protocol, matchers carry the routing

The repository splits cleanly: nonebot/ holds the framework, packages/ holds the published distributions, and website/ holds the Docusaurus documentation site that the root package.json builds with pnpm. The runtime dependency list in pyproject.toml is deliberately small: yarl, anyio, loguru, pygtrie, exceptiongroup, python-dotenv, typing-extensions and pydantic. None of the web or websocket machinery is mandatory. That is what the optional dependency groups are for.

There is a websockets extra, an httpx extra, an aiohttp extra, a quart extra and a fastapi extra, plus an all group that pulls websockets, fastapi, httpx, httpx2, aiohttp and uvicorn together. So a bot that connects outward over a websocket installs one set of packages, and a bot that receives HTTP callbacks installs another. The adapter you choose determines which extra you actually need; installing the framework alone gives you the plugin system and nothing to talk to.

Routing happens in matchers. A matcher combines a rule with a permission check and a handler, and the framework decides which matcher a given event belongs to. pygtrie is in the dependency list, which points at prefix-tree matching rather than a flat list of regular expressions. The documentation site is where the matcher semantics are spelled out; the README itself does not explain them.

Installing NoneBot2 and getting a first matcher to answer

The package name on PyPI is nonebot2, not nonebot, and the version in pyproject.toml is 2.5.0. The README points readers at the documentation site at nonebot.dev for setup instructions, and the repository carries a uv.lock and a pyproject.toml as its Python dependency sources. The README itself does not print an install command, a .env example or a plugin snippet, so there is no code to copy here; the two files below are the only Python packaging entries the repository exposes for the framework itself.

toml
[project]
name = "nonebot2"
version = "2.5.0"
description = "An asynchronous python bot framework."
license = "MIT"
requires-python = ">=3.10, <4.0"

The optional dependency groups are declared in the same file, and they are what tell you which extras exist. A bot that connects outward over a websocket installs one set, and a bot that receives HTTP callbacks installs another. The adapter you choose determines which extra you actually need.

toml
[project.optional-dependencies]
websockets = ["websockets >=15.0"]
httpx = ["httpx[http2] >=0.26.0, <1.0.0"]
httpx2 = ["httpx2[http2] >=2.0.0, <3.0.0"]
aiohttp = ["aiohttp[speedups] >=3.11.0, <4.0.0"]
quart = ["Quart >=0.18.0, <1.0.0", "uvicorn[standard] >=0.20.0, <1.0.0"]
fastapi = ["fastapi >=0.93.0, <1.0.0", "uvicorn[standard] >=0.20.0, <1.0.0"]

Because the README gives no install steps, the honest answer to "how do I install NoneBot2" is: get it from PyPI under the name nonebot2, as the badge row indicates, and follow the documentation site for the driver and adapter configuration. What you should see after a successful start is the loguru-formatted startup output listing the loaded plugins and the driver in use. If your plugin does not appear in that list, the module was not discovered, and that is a plugin-loading problem rather than an adapter problem.

Where NoneBot2 becomes the wrong tool

The framework has no built-in adapter. Installing nonebot2 alone produces a plugin system with no transport, and the README's badge row is a list of protocols the ecosystem supports, not code that ships in the wheel. If nobody has published an adapter for your target platform, you are writing one, and an adapter is a real piece of work: event parsing, message segment serialisation, and a driver that fits the framework's connection model.

Async is not optional. Every handler is a coroutine, the driver layer is built on anyio, and blocking calls inside a handler stall the event loop. Developers coming from a synchronous bot library will find that the first thing they must learn is not NoneBot2 but asyncio. The optional dependency groups also mean dependency resolution is a decision the user makes, and choosing the wrong extra produces import errors that surface at startup rather than at install time.

Finally, the project ships its documentation as a Docusaurus site inside the repository and versions it with a pnpm script. That is good for readers and a maintenance cost for contributors: a documentation change is a Node toolchain change, and the repository carries eslint, stylelint, oxfmt, TypeScript and pyright configuration alongside the Python code.

How NoneBot2 differs from a single-platform bot SDK

The closest alternative in the same ecosystem is a protocol-specific SDK: a library that speaks OneBot and nothing else. The difference is where the abstraction sits. A OneBot SDK gives you events and API calls in the shape of that protocol, so a group message is a group message and a friend message is a friend message, and your handler code knows it. NoneBot2 gives you a platform-neutral event and message model, and the adapter translates. The cost is an extra layer to learn and a mapping that cannot always be lossless; the benefit is that the same handler can be reached from QQ and from Telegram.

A different kind of alternative is a bot platform with a web console, where plugins are installed and configured through a UI rather than written as Python modules. That trades expressiveness for reach: non-programmers can deploy it, but anything the plugin author did not anticipate requires either a plugin or a fork. NoneBot2 makes the opposite bet. If your bot logic is genuinely custom, the code-first model wins; if it is a set of well-known features, the console model will get you running faster.

The repository also carries a CITATION.cff, which is unusual for a bot framework and signals that the maintainers expect academic use. That is a small signal, but it fits the design: the plugin API is meant to be extended by third parties, not consumed as a monolith.

Maintenance, licence and what an upgrade actually costs

The repository is not archived, and the last push was on 2026-09-20, two days before this writing, so the project is under current development. The release cadence visible in the release list is roughly two to three minor releases a year: v2.4.3 on 2025-08-07, v2.4.4 on 2025-10-29, and v2.5.0 on 2026-04-01. That is a slow-moving major line, which is what you want from a framework that plugins depend on.

The licence is MIT, declared in both the LICENSE file and the pyproject.toml license field. MIT is permissive: you can use NoneBot2 in a closed-source bot without publishing your plugin code. The practical implication is that the framework imposes no copyleft obligation on your handlers. It says nothing about the licences of the adapters and plugins you install, which are separate packages with their own terms, and those are worth checking individually. This is a description of the licence text, not legal advice.

Upgrade cost is dominated by the plugin ecosystem, not the core. The dependency constraints in pyproject.toml are upper-bounded on almost everything (yarl below 2.0.0, anyio below 5.0.0, pydantic below 3.0.0), and pydantic carries explicit exclusions for versions 2.5.0, 2.5.1, 2.10.0 and 2.10.1. That is a maintainer telling you which pydantic releases broke them. Pinning your own environment to a known-good set is cheaper than debugging a resolution surprise in production.

Editorial conclusion

Adopt NoneBot2 if you want one Python codebase driving several chat platforms and you are comfortable with async/await and Pydantic-style configuration. Skip it if you need a bot you can configure entirely from a web UI, or if you only ever target one platform and a thin SDK would do. Before committing, verify the adapter for your target platform exists and is published, confirm your Python is 3.10 or newer, and read the matcher documentation to check that its rule and permission model matches how you intend to route messages.

Frequently asked questions

What is NoneBot2 and what Python version does it need?

NoneBot2 is an asynchronous Python chatbot framework that runs bots on multiple chat platforms through adapters. Its pyproject.toml declares requires-python of 3.10 or newer and lists the package on PyPI as nonebot2, currently at version 2.5.0.

How do I install NoneBot2 and connect it to QQ?

The README does not print install steps; it points to the documentation site at nonebot.dev, and the PyPI badge identifies the package as nonebot2. The framework ships no adapter, so the QQ connection comes from a separately published adapter package rather than from nonebot2 itself.

Does NoneBot2 include a websocket or HTTP server out of the box?

No. The server and client machinery lives in optional dependency groups: websockets, httpx, httpx2, aiohttp, quart and fastapi, with an all group that combines them. You install the extra that matches the driver and adapter you chose.

What licence is NoneBot2 released under?

MIT, declared in the LICENSE file and in the pyproject.toml license field. That is permissive and does not oblige you to open-source your own plugins, though the adapters and plugins you install carry their own separate licences.

Official sources

  1. License: MIT
  2. nonebot/nonebot2 on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/nonebot-nonebot2.svg)](https://hysenlabs.com/projects/nonebot-nonebot2)