Quickstart¶
Build and run a two-node graph in under a minute. No LLM required — this is the smallest possible openarmature program so you can see every part of the shape on one screen.
Install¶
Requires Python ≥ 3.12.
A minimal graph¶
Two nodes (hello → world), one shared field, the append reducer.
import asyncio
from typing import Annotated
from openarmature.graph import END, GraphBuilder, State, append
from pydantic import Field
class S(State):
log: Annotated[list[str], append] = Field(default_factory=list)
async def hello(_s: S) -> dict[str, list[str]]:
return {"log": ["hello"]}
async def world(_s: S) -> dict[str, list[str]]:
return {"log": ["world"]}
graph = (
GraphBuilder(S)
.add_node("hello", hello)
.add_node("world", world)
.add_edge("hello", "world")
.add_edge("world", END)
.set_entry("hello")
.compile()
)
final = asyncio.run(graph.invoke(S()))
assert final.log == ["hello", "world"]
What just happened¶
Sis the state schema — a frozen Pydantic model. Nodes can't mutate it; they return partial-update dicts and the engine merges them.appendis the reducer attached tolog. Whenhelloreturns{"log": ["hello"]}, the engine appends to the existing list rather than replacing it.add_node+add_edgedeclare the graph shape;ENDis the terminal sentinel imported fromopenarmature.graph.compile()runs structural checks at construction time (no dangling edges, no unreachable nodes, no duplicate reducers) and returns an immutableCompiledGraph. Bad shapes fail here, not at run time.invoke()runs the graph fromset_entry()toENDand returns the final state.
Next¶
- Concepts — deeper on state, reducers, projections, fan-out, subgraphs, observability.
- Examples — five runnable demos, each driving a local OpenAI-compatible LLM endpoint to do real work.
- API reference — auto-generated from docstrings.