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
InMemorySaverandSqliteSaver(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 —
@entrypointand@taskdecorators for workflow-style definitions - Cache & Store — Node-level result caching (with TTL) and long-term key-value memory
- Prebuilt Agents —
ToolNode,create_react_agent,create_supervisor,create_swarm - LLM Streaming —
LLMStreamAdapterfor 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
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3180807e0762502be9768d97a660cc8f4372aefaf88534902e9a213c61cdd727
|
|
| MD5 |
fa66cb8040b8639fa8e8e4bc948f8585
|
|
| BLAKE2b-256 |
cfec6ee28c24ba1ede47e7d0f43ebb2554f94e9f1497969489e08070abdbb567
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a7c05f1b8563995a38580aa0a67fbcb3b8700087b26e7c33013d44f976d3ad49
|
|
| MD5 |
e83c553cf61c7bc199ff842090c14742
|
|
| BLAKE2b-256 |
85780a4d17e4aacb22578c839b0054c41e32105b014f9b94deb701191218b3e1
|