Ouroboros
A plugin framework for Python built on reversible registration as a first-class citizen.
Phase 1 core is implemented and validated, but the public API remains pre-1.0 and may change without notice.
What is this?
Ouroboros is a general-purpose composition framework that lets any Python application decompose itself into plugins that can be dynamically mounted, safely unmounted, and discover each other by service key rather than by import. A synchronous root Context composes the registry, event bus, service resolver, logger, and root lifecycle; every runtime operation still receives its invoking Context explicitly so derived scopes retain ownership.
It is a Python-native reimplementation of the architectural protocol pioneered by Cordis, the meta-framework extracted from the Koishi chatbot by Shigma and later vendored by DeepSeek Harness as its plugin substrate.
Relationship to Cordis
Ouroboros is not a line-by-line port of Cordis. It is an independent Python implementation that shares the same core protocol:
- Reversible effects — every registration returns a disposer; unloading a plugin unwinds all its registrations in reverse order.
- Dynamic fiber lifecycle — plugins mount and unmount at runtime; dependencies are resolved reactively, not by topological sort.
- Key-based service discovery — plugins obtain dependencies via
ctx.get("name")rather than importing concrete implementations. - Multi-semantics event bus —
emit,serial,bail,parallel, andwaterfalldispatch modes cover observation, short-circuit, concurrent, and around-middleware patterns. - Scope isolation —
ctx.isolate("name", label)creates independent service scopes so the same service key can coexist in multiple instances.
The implementation diverges where Python's language semantics and standard library offer a simpler path than Cordis's TypeScript original:
| Cordis (TypeScript) | Ouroboros (Python) | Why |
|---|---|---|
| Hand-written effect disposal | Explicit DisposerStack |
Preserves synchronous rollback before setup errors escape, then joins mixed async cleanup |
| Traceable Proxy system (~120 LOC) | Not needed | Python's bound methods preserve self — no JS this-binding problem |
| Schemastery (vendored schema lib) | Pydantic v2 | Python ecosystem standard |
| Custom logger service (246 LOC) | logging module |
Standard library |
String-concatenated epoch ":3:5:7" |
frozenset of (service, provider id) pairs |
Order-insensitive, name-preserving snapshot |
Symbol for isolate keys |
object() instances |
Python objects are naturally unique |
AggregateError |
ExceptionGroup (3.11+) |
Standard library |
No Cordis source code is included in this repository. The design is documented as an architectural reference; the code is an original Python implementation.
Quick start
import asyncio
from ouroboros import Context
async def main() -> None:
async with Context() as ctx:
def greeting(plugin_ctx: Context, config: str) -> None:
plugin_ctx.provide("greeting", config)
fiber = ctx.plugin(greeting, "hello")
await fiber
print(ctx.greeting)
asyncio.run(main())
See examples/basic.py for dependency activation, events,
and automatic teardown in one runnable example.
Phase 1 scope
Phase 1 includes synchronous Context bootstrap, reversible mixed-mode Effects, reactive Fibers, scoped services, five event modes, plugin registry/runtime tracking, Pydantic validation, config intercepts, and stdlib logging.
Current limitations:
- Python 3.11+ and one running asyncio loop per active root;
- plugin mounting requires a running loop, although
Context()does not; - config validation supports Pydantic v2
BaseModelsubclasses and is synchronous; - event names and service names are strings, with best-effort typing for core events;
- circular dependencies remain
PENDING; Phase 1 does not diagnose the cycle; - there is no persistence/loader layer or cross-process transport.
Target use cases
Any system that satisfies all three criteria:
- Runtime evolution — components join and leave while the process runs.
- Reversible extensions — side effects of an extension must unwind cleanly when it is removed.
- Swappable implementations — the same interface may have multiple implementations switchable at runtime.
Examples: AI agent harnesses, chatbot frameworks, data pipelines, IDE extension systems, game server mod systems, test infrastructure.
License
Apache-2.0. See LICENSES/Apache-2.0.txt.
SPDX headers are used throughout the codebase in compliance with the REUSE specification.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cordis_ouroboros-0.1.0.tar.gz.
File metadata
- Download URL: cordis_ouroboros-0.1.0.tar.gz
- Upload date:
- Size: 42.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d1b2b72e801fb90db3ca591b61c3fc0bbc7f140798a79fbdd1af3119d5bca91b
|
|
| MD5 |
13a0604762af6baaf7cdfac8f6989a8d
|
|
| BLAKE2b-256 |
3c3521a02a8380c3f61caf7e0032e694b0ec489a39b0bdb01e02024c75f35f13
|
Provenance
The following attestation bundles were made for cordis_ouroboros-0.1.0.tar.gz:
Publisher:
publish.yml on ghrah/ouroboros
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cordis_ouroboros-0.1.0.tar.gz -
Subject digest:
d1b2b72e801fb90db3ca591b61c3fc0bbc7f140798a79fbdd1af3119d5bca91b - Sigstore transparency entry: 2579961216
- Sigstore integration time:
-
Permalink:
ghrah/ouroboros@4983f741b9fb7e023bbb0cb0b97f10868ef86db4 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ghrah
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4983f741b9fb7e023bbb0cb0b97f10868ef86db4 -
Trigger Event:
push
-
Statement type:
File details
Details for the file cordis_ouroboros-0.1.0-py3-none-any.whl.
File metadata
- Download URL: cordis_ouroboros-0.1.0-py3-none-any.whl
- Upload date:
- Size: 30.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eaa683a437d762dce01680ef2ffa2867a021260d47e22c4758f19e8fdfc11311
|
|
| MD5 |
8e60a3a61ecaccac2ab1ee6af9bce566
|
|
| BLAKE2b-256 |
aceac310e82353c78e88dd1e19fc1659dd37d711898b6631ce6d85679f5ab9e6
|
Provenance
The following attestation bundles were made for cordis_ouroboros-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on ghrah/ouroboros
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cordis_ouroboros-0.1.0-py3-none-any.whl -
Subject digest:
eaa683a437d762dce01680ef2ffa2867a021260d47e22c4758f19e8fdfc11311 - Sigstore transparency entry: 2579961220
- Sigstore integration time:
-
Permalink:
ghrah/ouroboros@4983f741b9fb7e023bbb0cb0b97f10868ef86db4 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ghrah
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4983f741b9fb7e023bbb0cb0b97f10868ef86db4 -
Trigger Event:
push
-
Statement type: