Skip to main content

A lightweight graph execution engine with zero external dependencies — state management, checkpointing, streaming, and multi-agent orchestration.

Project description

ZeroGraph

A lightweight graph execution engine for building stateful, multi-step workflows — with zero external dependencies.

Inspired by LangGraph, ZeroGraph implements a Pregel-like superstep execution model with checkpointing, streaming, subgraph support, and prebuilt LLM agent patterns, all in pure Python.

Features

  • StateGraph — Define workflows as typed state machines with nodes, edges, and conditional routing
  • Channel System — Flexible state management via reducers (LastValue, BinaryOperatorAggregate, AnyValue, Topic, etc.)
  • Checkpointing — Persist and resume execution with InMemorySaver and SqliteSaver (sync + async)
  • Streaming — Multiple stream modes: values, updates, custom, messages, checkpoints, tasks
  • Subgraphs — Nest graphs within graphs with namespace-isolated state
  • Interrupt & Resume — Pause execution at any node and resume later with user input
  • Functional API@entrypoint and @task decorators for workflow-style definitions
  • Cache & Store — Node-level result caching (with TTL) and long-term key-value memory
  • Prebuilt AgentsToolNode, create_react_agent, create_supervisor, create_swarm
  • LLM StreamingLLMStreamAdapter for OpenAI/Anthropic-style chunk streaming
  • Visualization — Generate Mermaid diagrams from any StateGraph

Installation

pip install zerograph

Quick Start

A Simple Linear Graph

from typing import Annotated, TypedDict
import operator
from zerograph import StateGraph, START, END

class State(TypedDict):
    messages: Annotated[list, operator.add]

def greet(state: State) -> dict:
    return {"messages": ["Hello!"]}

def bye(state: State) -> dict:
    return {"messages": ["Goodbye!"]}

graph = StateGraph(State)
graph.add_node("greet", greet)
graph.add_node("bye", bye)
graph.add_edge(START, "greet")
graph.add_edge("greet", "bye")
graph.add_edge("bye", END)

app = graph.compile()
result = app.invoke({"messages": []})
print(result["messages"])  # ['Hello!', 'Goodbye!']

Conditional Routing

from zerograph import StateGraph, START, END

def router(state: dict) -> str:
    if state["x"] > 0:
        return "positive"
    return "negative"

graph = StateGraph(dict)
graph.add_node("positive", lambda s: {"label": "pos"})
graph.add_node("negative", lambda s: {"label": "neg"})
graph.add_conditional_edges(START, router, {"positive": "positive", "negative": "negative"})
graph.add_edge("positive", END)
graph.add_edge("negative", END)

app = graph.compile()
print(app.invoke({"x": 5}))   # {'x': 5, 'label': 'pos'}
print(app.invoke({"x": -3}))  # {'x': -3, 'label': 'neg'}

Streaming

app = graph.compile()
for event in app.stream({"messages": []}, stream_mode="updates"):
    print(event)
# {'greet': {'messages': ['Hello!']}}
# {'bye': {'messages': ['Goodbye!']}}

Checkpointing & Interrupt

from zerograph import StateGraph, START, END, InMemorySaver, interrupt

def human_review(state: dict) -> dict:
    answer = interrupt("Please review and confirm:")
    return {"approved": answer}

graph = StateGraph(dict)
graph.add_node("review", human_review)
graph.add_edge(START, "review")
graph.add_edge("review", END)

checkpointer = InMemorySaver()
app = graph.compile(checkpointer=checkpointer, interrupt_after=["review"])

# First call — pauses at "review"
config = {"configurable": {"thread_id": "1"}}
result = app.invoke({"approved": False}, config)

# Resume with user input
result = app.invoke(Command(resume=True), config)
print(result["approved"])  # True

ReAct Agent

from zerograph import create_react_agent

def search(query: str) -> str:
    """Search the web."""
    return f"Result for {query}"

def calculator(expr: str) -> float:
    """Evaluate a math expression."""
    return eval(expr)

def llm_call(messages, tools=None):
    # Your LLM integration here
    ...

agent = create_react_agent(llm_call, [search, calculator])
result = agent.invoke({"messages": [{"role": "user", "content": "What is 2+2?"}]})

API Overview

Core

Symbol Description
StateGraph Graph builder with typed state
CompiledStateGraph Compiled, executable graph
START, END Special node constants
Send Dynamic fan-out to specific nodes
Command Update state and control flow

Execution

Symbol Description
interrupt() Pause execution from within a node
entrypoint() Decorator for functional API entry points
task() Decorator for discrete work units

Checkpointing

Symbol Description
BaseCheckpointSaver Abstract checkpoint backend
InMemorySaver In-memory checkpoint storage
SqliteSaver SQLite-backed checkpoint storage
AsyncSqliteSaver Async SQLite checkpoint storage

State & Types

Symbol Description
add_messages Reducer for message lists (upsert by ID)
RemoveMessage Marker to remove a message by ID
RetryPolicy Configurable retry with exponential backoff
TimeoutPolicy Per-node timeout configuration

Prebuilt Agents

Symbol Description
ToolNode Node that executes tool calls
create_react_agent Build a ReAct loop in one call
create_supervisor Build a supervisor multi-agent graph
create_swarm Build a swarm with handoff-based routing
LLMStreamAdapter Stream adapter for OpenAI/Anthropic chunks

Infrastructure

Symbol Description
BaseCache / InMemoryCache Node-level result caching with TTL
BaseStore / InMemoryStore Long-term key-value memory

Requirements

  • Python >= 3.11
  • No external dependencies

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

zerograph-0.2.0.tar.gz (133.6 kB view details)

Uploaded Source

Built Distribution

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

zerograph-0.2.0-py3-none-any.whl (65.6 kB view details)

Uploaded Python 3

File details

Details for the file zerograph-0.2.0.tar.gz.

File metadata

  • Download URL: zerograph-0.2.0.tar.gz
  • Upload date:
  • Size: 133.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for zerograph-0.2.0.tar.gz
Algorithm Hash digest
SHA256 b430365bceb8d9c14823500a40b86fe551068d131f89c11ef400cba1ae619617
MD5 720960f564c27994f696df956f556663
BLAKE2b-256 75d143eae0122bc9b2994058da771647391b022a28d8b91424794dcb6c3ca628

See more details on using hashes here.

File details

Details for the file zerograph-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: zerograph-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 65.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for zerograph-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6bd61ebf38a9789fcbcb01d0698552fa343f35517063347e18a00a25bab64d23
MD5 985d19339f6c23d838b386d92e0170d4
BLAKE2b-256 34d384181709faa840f5d208f3fe7873a47af25389551e497ece9d8c87302210

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