Skip to main content

A workflow framework for Python. Build AI agents, data pipelines, and orchestration flows with nodes, graphs, and a shared store.

Project description

orbyt

A workflow framework for Python. Build AI agents, data pipelines, and orchestration flows with nodes, graphs, and a shared store.

Install

pip install orbyt

Quick Start

from orbyt import Flow, SharedStore, Result, new_node, run, DEFAULT_ACTION

# Create nodes
fetch = (
    new_node()
    .with_name("fetch")
    .with_exec_func(lambda r: Result({"users": ["Alice", "Bob", "Charlie"]}))
    .with_post_func(lambda shared, p, e: shared.set("data", e.value) or DEFAULT_ACTION)
)

transform = (
    new_node()
    .with_name("transform")
    .with_prep_func(lambda shared: Result(shared.get_dict("data")))
    .with_exec_func(lambda r: Result([name.upper() for name in r.must_dict()["users"]]))
    .with_post_func(lambda shared, p, e: shared.set("result", e.value) or DEFAULT_ACTION)
)

# Connect into a flow
flow = Flow(fetch)
flow.connect(fetch, DEFAULT_ACTION, transform)

# Run
shared = SharedStore()
flow.run_flow(shared)
print(shared.get_list("result"))  # ['ALICE', 'BOB', 'CHARLIE']

Core Concepts

Nodes

Every node runs three phases: prep (read inputs) → exec (do the work, retryable) → post (write results, return an action).

node = (
    new_node()
    .with_max_retries(3)
    .with_wait(1.0)
    .with_prep_func(lambda shared: Result(shared.get_string("input")))
    .with_exec_func(lambda r: Result(r.must_string().upper()))
    .with_post_func(lambda shared, p, e: shared.set("output", e.value) or DEFAULT_ACTION)
)

Or subclass for stateful nodes:

class MyNode(BaseNode):
    def __init__(self):
        super().__init__(max_retries=3, wait=0.5)

    def prep(self, shared):
        return shared.get_string("input")

    def exec(self, prep_result):
        return prep_result.upper()

    def post(self, shared, prep_result, exec_result):
        shared.set("output", exec_result)
        return DEFAULT_ACTION

Flows

Connect nodes with action-based routing to build directed graphs:

flow = Flow(start_node)
flow.connect(start_node, "success", next_node)
flow.connect(start_node, "error", error_node)
flow.connect(next_node, DEFAULT_ACTION, final_node)
flow.run_flow(shared)

Flows implement the Node interface - nest them inside other flows.

SharedStore

Thread-safe key-value store with typed getters:

shared = SharedStore()
shared.set("count", 42)
shared.get_int("count")          # 42
shared.get_int_or("missing", -1) # -1
shared.bind("user", UserModel)   # pydantic or dataclass

Batch Processing

Process lists of items with configurable concurrency:

from orbyt import new_batch_node

batch = (
    new_batch_node()
    .with_batch_concurrency(5)
    .with_batch_error_handling(True)
    .with_prep_func(lambda shared: [Result(url) for url in shared.get_list("urls")])
    .with_exec_func(lambda r: Result(fetch(r.must_string())))
    .with_post_func(lambda shared, items, results: ...)
)

Retry + Fallback

node = (
    new_node()
    .with_max_retries(3)
    .with_wait(1.0)
    .with_exec_func(call_flaky_api)
    .with_exec_fallback_func(lambda prep, err: {"status": "cached"})
)

Async

Every primitive has an async counterpart. Phase functions may be sync or async, and async flows can contain plain sync nodes — each phase is awaited only when it returns a coroutine.

import asyncio
from orbyt import AsyncFlow, new_async_node, run_async, Result, SharedStore, DEFAULT_ACTION

fetch = (
    new_async_node()
    .with_name("fetch")
    .with_exec_func(async_fetch_users)  # a coroutine function
    .with_post_func(lambda s, p, e: s.set("data", e.value) or DEFAULT_ACTION)
)

flow = AsyncFlow(fetch, max_steps=50)  # max_steps guards against runaway cycles
flow.connect(fetch, DEFAULT_ACTION, transform)

await flow.run_flow(SharedStore())

run_async mirrors run (retries sleep via asyncio.sleep, same fallback behavior). new_async_batch_node() runs items concurrently with an asyncio.Semaphore instead of a thread pool — the right model for I/O-bound work. AsyncFlow.max_steps turns infinite loops into a loud RuntimeError.

Mermaid Graph Export

flow = Flow(node_a, name="My Flow")
flow.connect(node_a, DEFAULT_ACTION, node_b)
print(flow.to_mermaid())

API Reference

Core Types

Type Description
Node Abstract base class - implement prep, exec, post
BaseNode Default implementation with retry/batch config
CustomNode Node with function fields
NodeBuilder Fluent builder from new_node()
Flow Directed graph of nodes (also a Node)
SharedStore Thread-safe key-value store
Result Value wrapper with typed accessors
BatchNode Node for processing lists
WorkerPool Fixed-size thread pool
AsyncNode Abstract async node - async prep/exec/post
AsyncBaseNode Default async node with retry/batch config
AsyncFlow Async directed graph (also an AsyncNode); max_steps loop guard
AsyncBatchNode Async list processing, concurrency via asyncio.Semaphore

Factory Functions

Function Description
new_node() Create a NodeBuilder
new_batch_node() Create a BatchNodeBuilder
run(node, shared) Execute a node through prep→exec→post
new_async_node() Create an AsyncNodeBuilder
new_async_batch_node() Create an AsyncBatchNodeBuilder
run_async(node, shared) Await a node through prep→exec→post (sync nodes too)
to_slice(v) Convert any value to list

License

MIT

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

open_orbyt-0.1.0.tar.gz (26.4 kB view details)

Uploaded Source

Built Distribution

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

open_orbyt-0.1.0-py3-none-any.whl (27.2 kB view details)

Uploaded Python 3

File details

Details for the file open_orbyt-0.1.0.tar.gz.

File metadata

  • Download URL: open_orbyt-0.1.0.tar.gz
  • Upload date:
  • Size: 26.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for open_orbyt-0.1.0.tar.gz
Algorithm Hash digest
SHA256 b6f42a43087f16345497b2bb54ac12625cc46319c665e20ec2584718df2b8298
MD5 34721d9830ca4a85cbaebf7a46c55277
BLAKE2b-256 3cf165d1a2a9103cc13dba956a830bf0e3d07a62cd7d40578e2c786662f81bad

See more details on using hashes here.

Provenance

The following attestation bundles were made for open_orbyt-0.1.0.tar.gz:

Publisher: publish.yml on erickweyunga/orbyt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file open_orbyt-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: open_orbyt-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 27.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for open_orbyt-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3f7017ca962bb8e85564934eaad83fb1a5bc9d9a8b906f9f8d3d1e7e52a9ff88
MD5 b4e2a9969c04d0946da53c002b4df7c3
BLAKE2b-256 19cb5f4711f724d60a3e638fb9fb20f63b170e7d05929ae74f51cc502cd5de0d

See more details on using hashes here.

Provenance

The following attestation bundles were made for open_orbyt-0.1.0-py3-none-any.whl:

Publisher: publish.yml on erickweyunga/orbyt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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