Ariadne, the Python QQ bot framework built on Mirai
一个优雅且完备的 Python QQ 自动化框架,基于 Mirai API HTTP v2。 Powered by Graia Project.
At a glance
- What is it?
- GraiaProject/Ariadne is an asyncio framework for building QQ bots on top of mirai-api-http v2, with a broadcast receiver model, a message commander chain and a creart extension point. It is a good fit if you already run a Mirai backend, and it is a poor fit if you were expecting a standalone bot, because the protocol layer lives elsewhere.
- Who is it for?
- Adopt graia-ariadne when you already run a mirai-api-http v2 backend and want a typed, asyncio native way to write QQ bots in Python. Do not adopt it expecting a deployable bot on its own, since the protocol side is a separate project, and check the AGPL-3.0 terms with whoever handles your compliance before you modify it and run it as a network service.
- Can I use it commercially?
- Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 18 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 October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A client framework, not a bot you can launch
The first thing to get right about Ariadne is where it sits in the stack. It is a Python QQ bot framework built on Mirai API HTTP v2, and the README states plainly that the project applies to mirai-api-http 2.0 and above, that this framework requires mirai-api-http v2, and that the whole point is to give you a good Python QQ bot development experience.
The implication is straightforward: you need something else to talk to QQ. Ariadne is the application layer. The protocol handling, the connection to the Mirai core, the login and session mechanics, all of that lives in mirai-api-http, and Ariadne's job is to give you a pleasant way to express reactions to messages once events arrive.
Who is it for then? Python developers who have already decided to use the Mirai stack, or who are willing to run it, and who want their bot code to be asyncio native, type annotated and structured around decorators rather than around a callback soup. The repository topics match that audience precisely, listing asyncio, bot, chatbot, framework, mirai, mirai-api-http, qq and qqbot.
The lineage is documented too. Ariadne is described as a work produced by the Graia Project after inheriting and improving on Application, a separate repository. That inheritance is not incidental background, because it explains the shape of the API: the Application design is still visible in how a bot is wired up, and the differences are the improvements the project claims.
The licence is GNU AGPL-3.0, and the README says directly that this means you need to comply with the corresponding rules. There is more on that below, because for a network service the AGPL is not a formality.
Broadcast receivers and the message commander
The programming model is the part worth understanding before you install anything. An event arrives, and a decorated function handles it. The example in the README is the whole pattern in a dozen lines: create the application from a config, register a receiver for the FriendMessage event, and send a reply.
from graia.ariadne.app import Ariadne
from graia.ariadne.connection.config import config
from graia.ariadne.model import Friend
app = Ariadne(config(verify_key="ServiceVerifyKey", account=123456789))
@app.broadcast.receiver("FriendMessage")
async def friend_message_listener(app: Ariadne, friend: Friend):
await app.send_message(friend, "Hello, World!")
Ariadne.launch_blocking()Four things are visible there. The application is constructed from a config object that takes a verify_key and an account, so credentials and identity are configuration rather than globals. The receiver decorator names the event type, and the handler signature is typed, taking the application and a Friend model, which is where the type annotations in the project metadata earn their keep. The handler is async, and it awaits the send. And the process is started with a blocking launch call, which is the standard shape for an asyncio application that owns the event loop until it stops.
The event dispatch itself is handled by a separate package, graia-broadcast, pinned in the dependency list, which is where the receiver graph and event matching live. The message layer is a third piece. The project exposes entry points under the creart.creators group, registering a CommanderCreator and a CommanderBehaviourCreator from graia.ariadne.message.commander.creart, which is the hook for extending message construction and behaviour. Optional extras pull in more: the standard extra brings richuru, graia-scheduler and graia-saya, and the graia extra brings the scheduler and saya as well.
For a reader coming from a plain HTTP client, this is the value proposition in one line: you write handlers against typed events instead of writing a websocket parser and a dispatch table.
Install with pdm, poetry or pip
Installation is a single package name, graia-ariadne, and the project supports three package managers. The README lists them in this order: `pdm add graia-ariadne`, `poetry add graia-ariadne` or `pip install graia-ariadne`.
The project recommends the first two strongly, and the reasoning is visible in the repository itself rather than stated: the tree includes a pdm.lock file, and the project carries a pdm-managed badge. A locked dependency set matters for a bot that has to keep running unattended, and the lock file is the difference between a reproducible install and one that resolves to new versions on a Saturday.
The packaging metadata in pyproject.toml is modern PEP 621. The interesting part for an adopter is the dependency list and the interpreter support:
requires-python = ">=3.8,<4.0"
dependencies = [
"graia-broadcast~=0.23.0",
"aiohttp~=3.8",
"pydantic~=1.9",
"typing-extensions>=4.4,<5.0",
"graia-amnesia~=0.7.0",
"launart>=0.6.4,<0.7",
"packaging>=23.0",
"creart~=0.3.0",
]Two details there deserve a second look before you build on this. The framework is pinned to pydantic 1.9, which is the 1.x series, and typing-extensions is capped below 5.0. Both are compatible pins rather than breakage, but they do mean your project cannot adopt pydantic 2 in the same environment without checking how the framework's models behave, and that is a real constraint for a long-lived service.
The version number itself is not in the file. It is declared dynamic, and the tree contains a bump-version.py script, which suggests the release tooling writes the version into the package metadata as part of the release process rather than maintaining it by hand.
A dev branch that moved past the last published release
Here is the part that deserves a careful reading before you adopt the project. The listed releases are v0.11.7 on 2023-08-05, v0.11.6 on 2023-08-03 and v0.11.5 on 2023-05-08. The last push to the repository, however, was on 2026-10-05, and the default branch is dev rather than master or main.
So the branch that carries the current work is three years ahead of the most recent published release in the list. The repository is not archived, and the tree shows a release workflow badge alongside a documentation deploy workflow, plus extract-release-notes.py and a CHANGELOG.md. There is also a migrate_src/ directory, which is the kind of thing that appears when a source layout is being restructured.
What this means in practice is that the packaging story has two timelines. The published version on PyPI carries a 2023 date, while the dev branch carries ongoing work that you would consume from source rather than from the index. The project classifiers describe the package as Development Status :: 4 - Beta, and the supported interpreters listed are Python 3.8 through 3.12 with 3 :: Only, so there is a stated support window even though the published artifacts are old.
The README carries a short motto about accepting the present and facing the future, and it also names a compatibility constraint: the project applies to mirai-api-http 2.0 and above. Both of those details matter for the same reason. The framework version you install and the backend version you run are a pair, and a mismatch is the most likely reason a fresh install fails to connect. The README does not document a compatibility matrix between framework releases and backend releases, so that pairing is something you have to establish yourself.
For an evaluation, the practical move is to read CHANGELOG.md on the dev branch, install from the branch in a virtual environment, and only then decide whether the published release is enough for your use.
AGPL-3.0 is the part to raise with your compliance team
The licence is GNU AGPL-3.0, and the README states it plainly, with a link to the licence text and the note that you need to follow the corresponding rules. This is worth more than a line, because a QQ bot is a network service by definition: it runs, it accepts events over a connection, and other people interact with it.
The reason the AGPL exists as a licence is precisely to cover that case. The copyleft obligations of the AGPL attach to conveying modified versions, and its network clause targets running a modified version as a service. Whether and not that clause is engaged by your particular bot depends on facts I cannot check for you: whether you modify the framework, whether you convey it, and how your deployment is arranged. I am not going to give you legal advice on that, and any article that does is doing you a disservice.
What I would do is take the licence to whoever signs off on licence compliance in your organisation, with a short question: does running a modified Ariadne bot as a publicly reachable service create an obligation to publish our modified source? That is a specific question with a checkable answer, and it is much easier to resolve before you write the bot than after.
The alternative licences are in play too. The project is published under AGPL-3.0, and the tree contains a LICENSE file at the root. If your organisation has a standing policy against AGPL in server-side components, that is a decision you may have made long before you look at Ariadne, and it is worth checking before you spend an evening on the integration.
Where Ariadne sits against writing the client yourself
The genuine alternative is not another framework, it is writing the client yourself over the same HTTP API with aiohttp, which is already a dependency of Ariadne anyway.
The difference in approach is the layer you take on. Call mirai-api-http v2 directly and you own everything: connecting, keeping the session alive, subscribing to events, decoding payloads, and dispatching them to your own handlers. You also own the failure modes, including what happens when an event arrives that your dispatch table does not expect, and you own the typing story, which is exactly what the pydantic models in Ariadne are there to provide.
Ariadne removes that work and charges you for it in dependencies. The event graph, the typed message models, the message commander chain with its creart extension hook, the scheduler and saya from the optional extras, and the convenience of the Ariadne class owning the lifecycle, all of that is a lot of behaviour you did not write and now must version, pin and upgrade.
For a large bot with many event types, a chainable message builder, and a team that will extend it, that trade is clearly worth it. For a bot that handles one or two event types and that nobody will extend, the framework is overhead, and calling the API with aiohttp is a smaller dependency and a smaller thing to keep alive.
The closer alternative inside the same family is Application, the project Ariadne inherited and improved. If you find yourself reading Ariadne's source to understand an inherited behaviour, that is a signal to compare the two directly before committing.
Editorial conclusion
Adopt graia-ariadne when you already run a mirai-api-http v2 backend and want a typed, asyncio native way to write QQ bots in Python. Do not adopt it expecting a deployable bot on its own, since the protocol side is a separate project, and check the AGPL-3.0 terms with whoever handles your compliance before you modify it and run it as a network service. Verify first which version the dev branch corresponds to, because the last published release listed is v0.11.7 from 2023-08-05 while the branch itself was pushed on 2026-10-05.
Frequently asked questions
What does graia-ariadne need in order to run?
It is a client framework for QQ bots built on mirai-api-http, and the README states the project applies to mirai-api-http 2.0 and above and that the framework requires mirai-api-http v2. You therefore need a Mirai backend running separately; Ariadne does not include the protocol layer.
How do I install graia-ariadne and handle a FriendMessage?
Install it with pdm add graia-ariadne, poetry add graia-ariadne or pip install graia-ariadne, with the project recommending pdm or poetry. Create the application with config(verify_key=..., account=...) and register an async handler with @app.broadcast.receiver("FriendMessage"), then start the process with Ariadne.launch_blocking().
Which Python versions and dependencies does graia-ariadne support?
pyproject.toml declares requires-python of >=3.8,<4.0 with classifiers for Python 3.8 through 3.12, and the package is marked Development Status :: 4 - Beta. Dependencies include graia-broadcast, aiohttp 3.8, pydantic 1.9, typing-extensions below 5.0, graia-amnesia, launart, packaging and creart.
What licence is graia-ariadne released under?
The project uses the GNU AGPL-3.0 licence, with the terms in the LICENSE file and a statement in the README that you need to comply with the corresponding rules. The version is taken from the project and should be checked with your own compliance review before you modify the framework and run it as a network service.
Official sources
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.
[](https://hysenlabs.com/projects/graiaproject-ariadne)Was this useful?