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.1.0.tar.gz (950.2 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.1.0-py3-none-any.whl (62.3 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for zerograph-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3180807e0762502be9768d97a660cc8f4372aefaf88534902e9a213c61cdd727
MD5 fa66cb8040b8639fa8e8e4bc948f8585
BLAKE2b-256 cfec6ee28c24ba1ede47e7d0f43ebb2554f94e9f1497969489e08070abdbb567

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for zerograph-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a7c05f1b8563995a38580aa0a67fbcb3b8700087b26e7c33013d44f976d3ad49
MD5 e83c553cf61c7bc199ff842090c14742
BLAKE2b-256 85780a4d17e4aacb22578c839b0054c41e32105b014f9b94deb701191218b3e1

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