Skip to main content

StateGraph

StateGraph is the fluent builder used to define your graph before compiling it.

API

from synapsekit import StateGraph

graph = StateGraph()

All methods return self so they can be chained.

add_node(name, fn)

Register a node with a unique name and a NodeFn.

async def my_node(state: dict) -> dict:
return {"result": state["input"].upper()}

graph.add_node("upper", my_node)

NodeFn signature: (state: dict) → dict | Awaitable[dict]. Both sync and async functions are accepted.

add_edge(src, dst)

Add a static edge from src to dst.

graph.add_edge("upper", "next_node")

Use END as dst to terminate the graph after that node.

from synapsekit import END

graph.add_edge("last_node", END)

add_conditional_edge(src, condition_fn, mapping)

Route to different nodes based on the current state.

def route(state: dict) -> str:
return "good" if state["score"] > 0.5 else "bad"

graph.add_conditional_edge(
"score_node",
route,
{"good": "approve_node", "bad": "reject_node"},
)

condition_fn can be sync or async. It receives the current state and returns a string key that is looked up in mapping.

set_entry_point(name)

Set the first node to execute.

graph.set_entry_point("fetch")

set_finish_point(name)

Shorthand for add_edge(name, END).

graph.set_finish_point("summarize")

compile(allow_cycles=False, max_steps=None)

Validate the graph and return a CompiledGraph.

compiled = graph.compile()

Parameters:

ParameterTypeDefaultDescription
allow_cyclesboolFalseSkip static cycle detection (for intentional loops)
max_stepsint | NoneNone (uses _MAX_STEPS=100)Maximum execution waves

Raises GraphConfigError if:

  • No entry point is set
  • An unknown node is referenced in an edge
  • A cycle exists in static edges (unless allow_cycles=True)
# Allow cycles with a custom step limit
compiled = graph.compile(allow_cycles=True, max_steps=50)

Full example

import asyncio
from synapsekit import StateGraph, END

async def ingest(state):
return {"tokens": state["text"].split()}

async def count(state):
return {"token_count": len(state["tokens"])}

async def flag_long(state):
return {"flag": "long"}

async def flag_short(state):
return {"flag": "short"}

def route(state):
return "long" if state["token_count"] > 100 else "short"

graph = (
StateGraph()
.add_node("ingest", ingest)
.add_node("count", count)
.add_node("flag_long", flag_long)
.add_node("flag_short", flag_short)
.add_edge("ingest", "count")
.add_conditional_edge("count", route, {"long": "flag_long", "short": "flag_short"})
.add_edge("flag_long", END)
.add_edge("flag_short", END)
.set_entry_point("ingest")
.compile()
)

result = asyncio.run(graph.run({"text": "hello world"}))
print(result["flag"]) # "short"