FF FlexiFlow
Open source

FlexiFlow Async components, done right.

A lightweight async component engine with events, state machines, persistence, and a minimal CLI. Under 2,000 lines of pure Python.

Install

pip install flexiflow

Create

engine = FlexiFlowEngine()

Run

await engine.handle_message(name, 'start')

Features

Everything you need, nothing you don’t.

Async Event Bus

Priority-based subscriptions with sequential or concurrent delivery and pluggable error policies.

State Machines

Declarative states with built-in message types. Load custom states via dotted paths or YAML packs.

Persistence

JSON for dev, SQLite for production. Snapshot history with retention pruning built in.

Structured Logging

Correlation IDs baked into every log entry. Trace any message through the full pipeline.

Config Introspection

explain() validates your config and shows what will happen before you run anything.

Minimal CLI

Register, handle messages, hot-swap rules, and debug — all from the command line.

Usage

Install

# Core
pip install flexiflow

# With extras
pip install flexiflow[reload]  # hot-reload
pip install flexiflow[api]     # FastAPI

CLI

# Register and start a component
flexiflow register --config config.yaml --start

# Send messages
flexiflow handle --config config.yaml confirm

Embedded

from flexiflow.engine import FlexiFlowEngine
from flexiflow.config_loader import ConfigLoader

config = ConfigLoader.load_component_config('config.yaml')
engine = FlexiFlowEngine()
component = engine.create_component(config)
await engine.handle_message(component.name, 'start')

Event Bus

# Subscribe with priority
handle = await bus.subscribe(
    'my.event', 'my_component', handler, priority=2
)

# Publish
await bus.publish('my.event', data, delivery='sequential')

Observability Events

Built-in events for monitoring your components.

Event
When
Payload
engine.component.registered
Component registered
{component}
component.message.received
Message received
{component, message}
state.changed
State transition
{component, from_state, to_state}
event.handler.failed
Handler exception
{event_name, component_name, exception}

Persistence

Choose the right backend for your use case.

Feature
JSON
SQLite
History
Overwrites
Appends
Retention
N/A
prune_snapshots_sqlite()
Best for
Dev / debugging
Production