Skip to content

Repository files navigation

flowr — non-deterministic state machine specification to knead workflows

CoverageCIPythonPyPIMIT License

A declarative, validatable YAML format for non-deterministic state machine workflows.

Read the specification →


The specification

flowr defines what a workflow is — its states, transitions, guard conditions, subflows — not what it does. No execution engine. No side effects. No opinions about retries, timeouts, or error handling. A YAML file declares structure. A validator checks integrity. Tools query, track, and visualise. The format is the foundation.

What the specification covers:

  • States with unique ids, per-state attributes, and transition mappings
  • Transitions that resolve to state ids or declared exit names
  • Guard conditions gated by evidence-based expressions using 6 operators (==, !=, >=, <=, >, <)
  • Named condition groups reusable across transitions on the same state
  • Subflows with call-stack semantics — push on entry, pop on exit
  • Within-flow cycles for iterative workflows
  • Validation rules — structural integrity checks independent of any runtime

What the specification does not cover:

  • Execution engines, side-effect hooks, retry logic, timeout handling
  • Parallel (fork-join) states
  • Orchestration, scheduling, or event dispatch

Full specification with examples and visual diagrams


The reference implementation

This repository contains a Python reference implementation — a CLI and library that validates, queries, and tracks flow definitions conforming to the specification. The specification is the contract; this code is one tool that honours it.

flowr validate deploy.yaml → valid: True
flowr states deploy.yaml → prepare, execute, review
flowr next deploy.yaml review → approve → deployed [blocked] need: score=>=80
→ reject → failed
flowr transition deploy.yaml review approve --evidence score=85
→ from: review, to: deployed
flowr session init deploy-flow → session created at state: prepare
flowr --session transition approve → from: prepare, to: review
flowr export deploy.yaml --format mermaid → stateDiagram-v2 ...

Validation. Structural constraints — missing fields, ambiguous targets, cross-flow cycles, subflow exit contracts — checked against the specification.

Query. States, transitions, conditions, attributes — ask any question the flow can answer.

Sessions. Init, show, set-state, transition, list. Subflow push/pop for nested workflows. Auto-enters initial subflow on session init. One --session flag turns any command session-aware.

Config.flowr config shows where every value comes from — default, pyproject.toml, or CLI override.

Mermaid export. Generate state diagrams from any flow definition.

Visualise.flowr serve starts a local web server with an interactive D3.js graph — clickable nodes, subflow navigation, zoom and pan. See every state, transition, and guard condition at a glance.

flowr serve screenshot


Quick start

Install:

pip install flowr

Requires Python 3.13+.

For the visual editor:

pip install flowr[viz]

Start the server:

flowr serve --path my-project
# Opens http://localhost:8080 — interactive flow browser

Define a flow:

flow: deployversion: 1.0.0exits: [deployed, failed]states:
- id: preparenext:
ready: execute
- id: executenext:
success: deployederror: failed
- id: reviewnext:
approve:
to: deployedwhen: { score: ">=80" }reject: failed

Use it:

$ flowr validate deploy.yaml
valid: True
$ flowr states deploy.yaml
prepare
execute
review
$ flowr next deploy.yaml review
state: review
approve → deployed [blocked] need: score=>=80
reject → failed
$ flowr transition deploy.yaml review approve --evidence score=85
from: review
trigger: approve
to: deployed
$ flowr session init deploy-flow
flow: deploy-flow
state: prepare
name: default
$ flowr --session transition approve
from: prepare
trigger: approve
to: review
$ flowr session show
flow: deploy-flow
state: review
name: default
stack: (none)
$ flowr config
project_root = /my/project (default)
flows_dir = .flowr/flows (default)
sessions_dir = .flowr/sessions (default)
default_flow = main-flow (default)
default_session = default (default)

Who is this for?

Specification adopters

You build editors, visualizers, CI systems, or orchestration layers. You need a structural format for workflow state machines — not an execution engine. The flowr specification gives you states, transitions, guard conditions, and subflows in a declarative YAML format with a conforming validator. Any tool can parse it. Read the spec.

Agent operators

You run flowr check, then flowr transition, then flowr check again — each time passing the flow name and current state by hand. Or you let sessions track it: flowr session init deploy-flow, flowr --session transition approve, flowr --session check. The session file remembers where you are. Push into a subflow; pop back out. No state to reconstruct, no context to pass.

Developers

You write a flow YAML. You need to know: is it valid? Which states can I reach from here? Does this transition have guard conditions? flowr validate, flowr states, flowr next, flowr check answer these questions — from the terminal for humans, from the Python library for tools.


CLI Reference

CommandDescription
flowr validate <flow>Validate a flow definition
flowr states <flow>List all state ids
flowr check <flow> <state> [<target>]Show state details or transition conditions
flowr next <flow> <state> [--evidence K=V]Show all transitions with trigger→target and condition status
flowr transition <flow> <state> <trigger> [--evidence K=V]Compute next state
flowr export <path> --format <fmt> [-o FILE]Export flow as JSON, Mermaid, or viz pipeline
flowr serve [--path DIR] [--host HOST] [--port PORT] [--edit]Start interactive D3.js visualization server
flowr session init <flow> [--name NAME]Create a new session (auto-enters initial subflow)
flowr session show [--name NAME] [--format FORMAT]Display current session state
flowr session set-state <state> [--name NAME]Update the session's current state
flowr session list [--format FORMAT]List all sessions
flowr config [--json]Show resolved configuration with sources
flowr --session <command>Run a command using session state (works with validate, states, check, next, transition)

<flow> accepts a file path or a short flow name (resolved from .flowr/flows/). Use --flows-dir to override the configured flows directory. All query commands accept --json for machine-readable output (not serve). Evidence: --evidence key=value (repeatable) or --evidence-json '{"key": "value"}'.


Architecture

flowr/
├── domain/ # Core domain — Flow, State, Transition, Session, conditions, validation
│ ├── flow_definition.py
│ ├── loader.py
│ ├── session.py
│ ├── condition.py
│ ├── validation.py
│ └── mermaid.py
├── infrastructure/ # Adapters — config resolution, session persistence
│ ├── config.py
│ └── session_store.py
├── cli/ # Primary adapter — CLI commands, resolution, output formatting
│ ├── resolution.py
│ ├── session_cmd.py
│ ├── serve.py
│ └── output.py
├── server/ # Viz server — FastAPI REST API, flow scanner
│ ├── app.py
│ ├── config.py
│ └── scanner.py
├── static/ # Frontend — D3.js HTML/CSS/JS assets
│ ├── index.html
│ ├── css/
│ └── js/
└── __main__.py # CLI entrypoint — argparse dispatch

Hexagonal architecture. Domain has no infrastructure dependencies. CLI is the primary adapter. Session store is a secondary adapter behind a Protocol port.


Documentation


Development

uv sync --all-extras # install with dev dependencies
uv run task test# run tests
uv run task test-fast # fast tests only
uv run task test-build # full suite with coverage
uv run task lint # lint and format
uv run task static-check # type checking

License

MIT — see LICENSE.

About

Non-deterministic YAML state machine specification for AI agent orchestration

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages