Skip to main content

flowli

A workflow engine that runs a workflow as a coroutine execution stack and journals every frame to CairnDB.

Documentation: https://quadratic-labs.github.io/flowli/ — the quickstart, the concepts, the architecture, every setting, the hosting guide, and the API reference from the docstrings. The specifications stay in specs/.

uv sync --extra docs
uv run sphinx-build -b html -W docs docs/_build/html    # or: make -C docs livehtml

Layout:

  • src/flowli/domain/ — pure domain objects and ports. No I/O, no CairnDB import.
  • src/flowli/adapters/ — port implementations (CairnDB, in-memory).
  • src/flowli/api/ — the HTTP service (the api extra).
  • web/ — the operator interface over that service.
  • runner/ — flowli-runner: coding agents as delegate consumers.
  • codeflow/ — flowli-codeflow: the controller over the runner.

Running the jobs

Install with the CLI extra, then point the CLI at your workflow registry:

pip install "flowli[cli]"
export CAIRNDB_STORAGE_TYPE=s3 CAIRNDB_S3_BUCKET=my-bucket      # or --storage-path ./bucket

flowli worker    --app myapp.flows:registry --queue default --queue finance
flowli sweeper   --app myapp.flows:registry --interval 60
flowli retention --app myapp.flows:registry --delay-days 30 --once

--app module:attr names a Registry, an Engine, or a zero-argument callable returning one. With a Registry the CLI builds the CairnDB backend from the CAIRNDB_* variables. --once runs one pass and exits, which suits a cron job. --projection PATH makes the sweeper and retention read statuses from the SQLite projection instead of folding the control log. Every job stops cleanly on SIGINT or SIGTERM.

Operator commands share the same --app and storage options:

flowli status  EID --journal
flowli signal  EID payments '{"amount": 100}' --by bank@example.com
flowli cancel  EID --by ops@example.com
flowli migrate EID 2 --by ops@example.com

--by names the actor recorded in provenance: an email, or kind:id with kind human, system, schedule or worker. It defaults to the local user, or to FLOWLI_BY. Commands exit with code 1 on an unknown execution or a refused action, such as cancelling a finished execution.

What the commands print

status answers the two questions an operator arrives with — where is it, and what happened last:

eid        01a093cc-265e-730a-b05c-e7e36d377452
status     completed
workflow   greet v1
queue      default
created    2026-09-12T04:07:05.054046Z by human:thomas@example.com
last       execution.completed at 2026-09-12T04:07:05.128988Z by worker:w-1 on host-3 epoch 1
payload
{
  "value": "hi zoe"
}

A suspended execution names what it waits for instead of a payload:

status     suspended
last       execution.suspended at 2026-09-12T04:07:05.193632Z by worker:w-1 on host-3 epoch 1
waiting    channel:01a093cc-26cd-7373-8944-38c18b531442.go

--journal appends the whole log, one event per line:

           seq  type                   fid                              at                       actor
       1000000  execution.started      root                             2026-09-12T04:07:05.128988Z worker:w-1
       2000000  frame.started          root/greet#0                     2026-09-12T04:07:05.139587Z worker:w-1
       3000000  frame.completed        root/greet#0                     2026-09-12T04:07:05.139587Z worker:w-1
       4000000  execution.completed    root                             2026-09-12T04:07:05.128988Z worker:w-1

Every --once job answers with one line of counters, which suits a cron job that mails its output:

flowli sweeper   --once     # timers_fired=1 recovered=0 restarted=0 repaired=0 waits_cleared=0
flowli retention --once     # archived=1 cleaned=0, then one line per archived execution
flowli-runner    --once     # recovered=0 processed=1, then one line per reattached task
flowli-codeflow merge --once   # merged=1
flowli-codeflow board --once   # reconciled=3

Colour

On a terminal the output is coloured: the status by what it means (green completed, red failed, yellow suspended), workflow names in cyan, timestamps and actor kinds dimmed so the identity stands out, and JSON payloads syntax highlighted. The theme paints with the terminal's own sixteen colours, so it suits a light background as well as a dark one.

Piped output is plain text, byte for byte. Redirect the output, capture it in a test, or run it under cron, and you get exactly the columns above with no escape sequences — so grep, awk and cut keep working. Set NO_COLOR to drop the colour on a terminal too.

The HTTP service and the interface

pip install "flowli[api]"
uv run python web/dev_server.py        # an engine, a worker and the service
cd web && npm install && npm run dev   # the operator interface

flowli.api.create_app(engine, projection=..., authenticator=...) is the service: the catalog and the control plane (specs/09-http-api.md, sections 7 and 8), the worker plane for consumers that cannot reach the bucket (section 9), and evidence (section 10). It holds no state of its own: reads come from the projection, writes go through the engine, and the actor of every write comes from the access token.

web/ is the interface over it. web/dev_server.py runs a demo backend for it. See web/README.md.

Logging

Every component emits structured events through structlog, the library CairnDB uses, so one configuration produces one stream:

from flowli.log import configure_logging
configure_logging("INFO", "json")      # or "console"

All three CLIs — flowli, flowli-runner and flowli-codeflow — take --log-level and --log-format console|json; flowli also reads FLOWLI_LOG_LEVEL and FLOWLI_LOG_FORMAT. Logs go to stderr, so a job's report on stdout stays pipeable on its own. Events are named with snake_case nouns such as execution_started, execution_suspended, frame_failed, execution_recovered and execution_archived. While a worker holds a task, worker_id, task_id, eid and epoch are bound to every event it emits, and live frames add fid and attempt. Frame events are at DEBUG level.

License

MIT. See LICENSE.

Release files for flowli 0.1.0

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

Source distribution (sdist)

Source distribution for flowli 0.1.0
File Size Uploaded
flowli-0.1.0.tar.gz 89.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for flowli 0.1.0
File Interpreter ABI Platform
flowli-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 199.4 kB

Release files / flowli-0.1.0.tar.gz

Download URL flowli-0.1.0.tar.gz
Size 89.9 kB
Tags Source
SHA-256 checksum
How to use checksums
f0615de9029a6b2b2c1e1d26541e12f79fd2d81834f3d8d737bbf9e9c7a24533
BLAKE2b-256 checksum
How to use checksums
6f4cb13fb1c286be5c348bf7a26ee6eaf1496c9f3205030be8a27c9444d57b6f
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 Sep 26, 2026.

Transparency log

Release files / flowli-0.1.0-py3-none-any.whl

Download URL flowli-0.1.0-py3-none-any.whl
Size 109.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8f66f3d14203487703cb9fa2f9c8031ce4e93ccc8ccfc11c1ea889863ada8fbe
BLAKE2b-256 checksum
How to use checksums
bfeea3f50019a2f8bb3481c0eea9a716a88c76efca267966a3e3734fd3a56268
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 Sep 26, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 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