Skip to main content

A Python DSL for writing dataflow programs.

Project description

Flowno

Flowno is a Python DSL for building concurrent, cyclic, and streaming dataflow programs—ideal for designing modular LLM agents. Inspired by no-code flowchart tools like ComfyUI, Flowno lets you describe workflows in code while handling complex dependency resolution (including cycles and streaming) behind the scenes.

Key Features

  • Node-Based Design
    Define processing steps as nodes with a simple decorator. Nodes can be stateless or stateful - consume, yield or transform streams - single or multiple outputs.

  • Cycles & Streaming
    Unlike many workflow/flowchart/visual dataflow tools, Flowno supports cyclic graphs and streaming outputs. Use default values to bootstrap cycles.

  • Concurrent By Default
    The Flowno runtime schedules nodes to run as soon as their inputs are ready. Flowno provides a set of basic non-blocking concurrency primitives.

  • Type-Checked & Autocompleted Flowno is designed to work well with type checkers and IDEs to catch incompatible connections between nodes.

Quickstart

Set up a virtual environment and install Flowno:

python -m venv .venv  # Requires Python 3.10+
source .venv/bin/activate  # On Windows use: .venv\Scripts\activate
pip install flowno

Create a minimal flow (hello.py):

from flowno import node, FlowHDL

@node
async def Add(x, y):
    return x + y

@node
async def Print(value):
    print(f"Value: {value}")

with FlowHDL() as f:
    f.sum = Add(1, 2)
    f.print = Print(f.sum)

f.run_until_complete()
(.venv) $ python hello.py
Value: 3

How It Works

Flowno has three key components that work together to create dataflow programs:

1. Node Creation

The @node decorator transforms async functions (or classes) into a constructor for a new subclass of DraftNode. The transformed function takes takes connections to other nodes or constant values as arguments and returns a DraftNode instance.

@node
async def Add(x, y):
    return x + y

draft_node_1 = Add(1, 2)  # Creates a node that will add 1 and 2
draft_node_2 = Add(draft_node_1, 3)  # Connects to the output of draft_node_1 to first input of draft_node_2

2. Flow Description

The FlowHDL context manager provides a declarative way to define node connections. Inside this context, nodes are assigned as attributes and can reference other nodes' outputs:

with FlowHDL() as f:
    f.node_a = Add(1, 2)          # No references
    f.node_b = Add(f.node_a, 1)   # Backward reference

    f.node_c = Add(f.node_d, 1)   # Forward reference
    f.node_d = Add(f.node_c, 1)   # Backward reference creating a cycle

The context uses Python's __getattr__ method to return placeholder objects when accessing undefined attributes like f.node_d. These forward references are a core feature of Flowno—they're not errors. However, each forward-referenced node must eventually be defined in the flow (as shown in the last line for f.node_d). During __exit__, the placeholders are resolved into proper node connections, and all DraftNode instances are finalized into full Node objects.

This mechanism allows you to define nodes in any order, which simplifies the construction of cyclic graphs.

3. Execution

When you call f.run_until_complete(), Flowno executes your flow:

  1. Identifies nodes ready to run (those with all inputs available)
  2. Executes ready nodes concurrently
  3. Propagates outputs to dependent nodes
  4. For cyclic flows, uses default values to bootstrap the cycle

The runtime is asynchronous - nodes only wait for their direct dependencies and run concurrently with other nodes. Execution continues until all nodes complete or, for cyclic flows, until an uncaught exception occurs.

Features TODO

  • Conditional Nodes
    Currently all nodes are executed unconditionally. The only way to skip a node is to add an immediate return statement to bypass the node's logic. I plan to add a way to conditionally execute nodes based on the output of other nodes.

Non-Goals

  • Visual Editor
    Flowno is a DSL for defining dataflows in code. It does not include a visual editor for creating flows. I have a crude prototype of a visual editor, but I just don't see the value in dragging and dropping nodes. A visual editor can't be used by a LLM agent, for example.

  • Backpropagation
    Flowno is not a machine learning framework. I considered adding some sort of automatic differentiation, but I could never do it as well as PyTorch, and cycles would be difficult.

About The Naming Conventions

A Foolish Consistency is the Hobgoblin of Little Minds

-- Style Guide for Python Code (PEP-8)

My naming conventions deviate from standard Python style. I capitalize node names (like Add instead of add) because they are factory functions that behave like classes - when you call a decorated node function, it returns a DraftNode instance.

The FlowHDL context with its f.node_name = Node() syntax is an abuse of Python's __getattr__ method. However, this approach enables:

  • LSP type checking support
  • Slightly better IDE autocomplete functionality
  • Forward references for natural cycle definitions

License

Flowno is released under the MIT License.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

flowno-0.1.7.tar.gz (104.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

flowno-0.1.7-py3-none-any.whl (96.3 kB view details)

Uploaded Python 3

File details

Details for the file flowno-0.1.7.tar.gz.

File metadata

  • Download URL: flowno-0.1.7.tar.gz
  • Upload date:
  • Size: 104.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for flowno-0.1.7.tar.gz
Algorithm Hash digest
SHA256 5aec0e8c057e6d1c5c646be4aecbef753bdd4833b0d3ae76c4f78c5b9c2c5d96
MD5 00906f0e879864d38c5c4ff5a919726e
BLAKE2b-256 09db5791278eec36b0404b83081adf5ca181f8000c2b9e693ec3dd6a26eeaf1c

See more details on using hashes here.

File details

Details for the file flowno-0.1.7-py3-none-any.whl.

File metadata

  • Download URL: flowno-0.1.7-py3-none-any.whl
  • Upload date:
  • Size: 96.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for flowno-0.1.7-py3-none-any.whl
Algorithm Hash digest
SHA256 53047a6b44345c149d4534dc18b3a1b0ca53517783c07f351c503a3ae4dc4985
MD5 2b011f70c0e5d71ed7a05c98c4e2a13f
BLAKE2b-256 00b634def7f648c899d3afd09949b0d9922288a7dbb8f8339e367caf8e742c6c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page