Back to docs

Roots (0.1.1)

An AI-native process orchestration framework — YAML-defined directed graphs executed by a crash-safe orchestrator.

On this page

View Release Notes

#What is Roots?

Roots is an AI-native process orchestration framework. You describe a process — an agent pipeline, an approval workflow, a fan-out/fan-in computation — as a directed graph in YAML, then run it with a stateless-between-ticks orchestrator that persists state after every node. Because state is checkpointed continuously, runs survive crashes and restarts.

The process definition is decoupled from implementation: nodes reference agents by name (a local Python callable, a remote HTTP service, or an MCP tool), and the graph routes between them using deterministic conditions or AI-driven decisions.

  • YAML process graphs — 10 node types and 4 decision modes
  • Crash-safe orchestrator — state persists after each node; fork/join and parallel pools checkpoint per-branch
  • Process compositionsubprocess nodes call other processes; iterator nodes fan out over a list
  • Pluggable storage — SQLite by default, PostgreSQL for production
  • Agents & events — local / HTTP / MCP agents, webhooks, and wait_for subscriptions
  • Typed end-to-end — Pydantic v2 models, ships py.typed, strict pyright

#Installation

pip install rootsflow        # or:  uv pip install rootsflow

The distribution is named rootsflow; the import package is roots:

from roots import Roots, SqliteBackend

Requires Python 3.12+.


#Quick Start

#1. Define a process (echo.yaml)

id: echo
name: Echo Process
version: "1.0.0"

nodes:
  - id: greet
    type: agent
    label: Greet
    config:
      agent: echo_agent
      output_key: greeting
  - id: done
    type: end
    label: Done
    config:
      status: completed

edges:
  - from: greet
    to: done

entry_point: greet

#2. Run it from Python

import asyncio
from roots import Roots, SqliteBackend


async def echo_agent(work_item_state: dict) -> dict:
    return {"message": f"Hello, {work_item_state.get('name', 'world')}!"}


async def main() -> None:
    backend = SqliteBackend("roots.db")
    await backend.initialize()

    async with Roots(storage=backend) as app:
        await app.register_agent("echo_agent", echo_agent)
        await app.load_process("echo.yaml")

        run, _event = await app.start_and_wait("echo", {"name": "Roots"})
        print(run.status, run.work_item_state)


asyncio.run(main())

#3. Or use the CLI

roots validate echo.yaml          # validate a process definition
roots run echo.yaml --work-item '{"name": "Roots"}'
roots serve                       # start the HTTP API on 127.0.0.1:8000
roots pack ./echo.yaml -o echo.root   # bundle into a portable .root archive

#Node Types

TypePurpose
agentInvoke a single agent (local / HTTP / MCP)
agent_poolRun several agents in parallel or sequence, then merge or vote
decisionRoute on conditions — deterministic or AI-driven
checkpointPause for human approval
fork / joinSplit into parallel branches and recombine (crash-safe)
emitEmit a custom event
iteratorFan a subprocess out over a list (for_each)
subprocessCall another process as a child run
endTerminate the run with a status

Decision modes: deterministic, ai_bounded, ai_checkpoint, ai_autonomous.


#How it works

A tick-based orchestrator advances each run one node at a time, persisting state to the StorageBackend after every step. Each node declares an output_key; its result is accumulated into the run’s state for downstream nodes to read — an implicit data pipeline through the graph. Expression conditions are evaluated with simpleeval (no eval/exec), and all models use Pydantic v2.

For the full guide — node reference, agent contracts, packaging, and the HTTP API — see the Integration Guide on GitHub.


#Security note

Roots is beta software. The HTTP API has no authentication by default and binds to 127.0.0.1. Set ROOTS_API_KEY to require an X-API-Key header, and do not expose roots serve to an untrusted network without your own authentication layer. Process definitions, event sinks, and MCP command-agents are treated as trusted input.



#License

MIT License