Skip to main content

fastapi-cordis

An independent Python library for managing plugin services in FastAPI and asyncio applications. Define how each service starts, which other services it needs, and how it closes. The runtime handles ordering and waits for callers before disposing resources.

Status: experimental. The package is available on PyPI. The distribution name is fastapi-cordis and the Python import is fastapi_cordis.

Inspired by Cordis, this is an independent implementation, not an official port. It does not run JavaScript Cordis plugins.

What it provides

  • Explicit plugin definitions and optional Pydantic configuration validation.
  • Typed service keys that let callers keep the same contract when providers change.
  • Multiple capabilities per plugin and scoped provider overrides.
  • Dependency-ordered startup and reverse-order cleanup, including failed setup.
  • Owned resource scopes, context managers, and cancellable background tasks.
  • Typed events with owned listeners and leases around running handlers.
  • Reactive dependency recovery, runtime registration, and configuration replacement.
  • Configuration previews, equivalent-update detection, and lifecycle diagnostics.
  • Service leases that protect resources and their dependencies during async or worker-thread calls.
  • FastAPI lifespan integration, service injection, and optional management routes.
  • An asyncio lifecycle API for applications without an HTTP server.

Requirements and installation

Python 3.11+ and asyncio are required. The package depends on FastAPI 0.135.2+ and Pydantic 2.12.5+; pyproject.toml defines the supported version ranges.

Install from PyPI in a virtual environment:

python -m venv .venv
source .venv/bin/activate
python -m pip install fastapi-cordis

On Windows, activate with .venv\Scripts\Activate.ps1 in PowerShell instead. To install this release exactly, use python -m pip install fastapi-cordis==0.2.2. The source archive on the release page includes the guides, examples, and tests. Cloning the GitHub repository requires repository access.

Alternatively, from the root of a source checkout:

python -m pip install .

For development, install the package and test tools together:

uv sync --python 3.14

To build and install a local distribution:

uv build
python -m pip install dist/fastapi_cordis-0.2.2-py3-none-any.whl

Building these files does not publish them.

Quick start

Save this as demo.py after installing the package:

from collections.abc import Callable
from typing import Annotated

from fastapi import Depends, FastAPI
from fastapi_cordis import Plugin, PluginContext, PluginManager, install, service
from pydantic import BaseModel, ConfigDict


class GreetingConfig(BaseModel):
    model_config = ConfigDict(extra="forbid")
    prefix: str = "Hello"


async def greeting(ctx: PluginContext):
    return lambda name: f"{ctx.config.prefix}, {name}"


manager = PluginManager([Plugin("greeting", greeting, config_model=GreetingConfig)])
app = FastAPI()
install(app, manager)


@app.get("/hello/{name}")
async def hello(
    name: str,
    greet: Annotated[Callable[[str], str], Depends(service("greeting"))],
):
    return {"message": greet(name)}

Install an ASGI server and start the app:

python -m pip install uvicorn
python -m uvicorn demo:app --host 127.0.0.1

GET /hello/Ada returns {"message":"Hello, Ada"}. GET /plugins reports the plugin's state. install starts plugins before the existing application lifespan and closes them after it. service("greeting") holds a lease while the request uses the service, so a concurrent stop waits for that request to finish.

The source checkout also includes examples/app.py, which enables management writes for local experimentation:

uv run --with uvicorn uvicorn examples.app:app --host 127.0.0.1

For a serverless example of late registration, typed events, owned resources, configuration previews, and scoped provider replacement:

uv run python examples/reactive.py

Runtime management

Use install(app, manager, management=True) to enable mutation routes. The host application supplies authentication and authorization for these routes.

Endpoint Behavior
GET /plugins List states, dependencies, and in-flight counts
POST /plugins/{name}/enable Enable a plugin; start when its dependencies become available
POST /plugins/{name}/disable Stop a plugin and block its enabled dependents
POST /plugins/{name}/disable?cascade=true Explicitly disable the dependent group
POST /plugins/{name}/retry Explicitly retry a failed plugin
PUT /plugins/{name}/config Validate replacement configuration and restart the affected active plugins
POST /plugins/{name}/config/plan Preview affected plugins and protected dependents without applying settings

Ordinary disable preserves dependents' enabled intent, so they resume when their provider returns. Cascading disable explicitly disables the dependent group. Missing providers leave plugins blocked; manager.validate() provides an optional strict check before startup. register() and unregister() change definitions at runtime; they do not install packages or reload source code.

Equivalent validated configuration is a no-op. Snapshots report configuration revisions, service generations, lifecycle timings, and owned task counts. Plans are advisory; applying an update checks the current graph again.

Configuration values and service objects are omitted from diagnostics. Runtime changes stay in this manager; the host owns persistence and coordination across processes. After a cascading disable, enable providers before their dependents.

Scope and documentation

The runtime manages trusted Python services on one owning asyncio event loop. Callers must use leases correctly; leases do not make a service itself thread-safe. Package installation, automatic discovery, source reloads, database migrations, plugin isolation, and coordination between server workers belong to the host. Disabling a plugin does not remove its HTTP routes.

These guides are included in the source checkout and source distribution:

Document Covers
docs/plugins.md Authoring plugins, declaring dependencies, and cleaning up resources
docs/lifecycle.md Leases, state transitions, runtime changes, and failure recovery
docs/events.md Typed payloads, owned listeners, and asynchronous dispatch
docs/services.md Service contracts, multiple capabilities, and scoped providers
docs/fastapi.md Lifespan integration, HTTP behavior, and protected management routes
CONTRIBUTING.md Development, artifact checks, and release preparation
docs/ci.md Isolated local CI, Python matrix, and manual TestPyPI/PyPI publishing
CHANGELOG.md Version changes and migration from 0.1.0

License

MIT. See LICENSE in the source distribution or the license included in the wheel.

Metadata

Release files for fastapi-cordis 0.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fastapi-cordis 0.2.2
File Size Uploaded
fastapi_cordis-0.2.2.tar.gz 71.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fastapi-cordis 0.2.2
File Interpreter ABI Platform
fastapi_cordis-0.2.2-py3-none-any.whl Python 3 none any Details

Total release size: 92.6 kB

Release files / fastapi_cordis-0.2.2.tar.gz

Download URL fastapi_cordis-0.2.2.tar.gz
Size 71.0 kB
Tags Source
SHA-256 checksum
How to use checksums
ecb4acb9675b27f3efe361fb52fe34ee759fb34d98d7bad1b33b08f0cec5f100
BLAKE2b-256 checksum
How to use checksums
de3a8e158363009739ead76562422d6c5bcee415e8f867d2e120f7456650d3ca
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.

Transparency log

Release files / fastapi_cordis-0.2.2-py3-none-any.whl

Download URL fastapi_cordis-0.2.2-py3-none-any.whl
Size 21.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
29a9f24a41835dc53fcc9f6e5ece8201a93b2c9d74631fd4f8ac5a1715723ec8
BLAKE2b-256 checksum
How to use checksums
c9feb8909e8ed3636d62eafb1e52904357761186037e1e9fce3bba74097de21b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.2 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page