ri-agent-graph
Graph-based agent orchestration for Rust — a LangGraph-inspired execution engine with checkpointing, parallel fan-out/fan-in, interrupt/resume, and cryptographic execution receipts.
What it gives you
- Deterministic graph execution — define nodes as computational steps, edges as control flow, and execute with typed state
- 8 node types —
llm,router,join,parallel,passthrough,state_transform,subgraph,human_approval - Parallel fan-out/fan-in — automatic concurrent execution with configurable join policies (
collect_array,merge_objects,first_non_null,all_success,quorum) - Checkpointing & interrupt/resume — SQLite-backed persistence with atomic checkpoint transactions and crash recovery
- Cryptographic receipts — HMAC-SHA256 authenticated
GraphExecutionReceiptV1for every run - Event streaming — lifecycle events (node start/complete/error), token streaming, and state snapshots
- stack-ids integration —
TraceCtx,AttemptId,TrialIdexecution tracing at every layer - Zero-cost abstractions — generic over user-defined state
S, no heap allocation beyond what your nodes require
Installation
Or in your Cargo.toml:
[]
= "0.2"
Feature flags
| Flag | Default | Description |
|---|---|---|
checkpointing |
✅ on | SQLite-backed checkpoint persistence via rusqlite |
To disable checkpointing (embedded/no_std targets):
= { = "0.2", = false }
Quick start
use *;
async
Node types
| Type | Description | Status |
|---|---|---|
llm |
Invoke an LLM with system/user prompts and optional tool calls. Response merged via configurable reducer. | ✅ |
router |
Conditional branching. Evaluate a function/predicate to select the next edge dynamically. | ✅ |
join |
Fan-in synchronization. Wait for parallel branches and merge state via a join policy. | ✅ |
parallel |
Fan-out dispatch. Spawns concurrent branches from a single node; the engine's JoinSet handles real parallelism. |
✅ |
passthrough |
No-op state pass. Useful for fan-out distribution points. | ✅ |
state_transform |
10 state mutations: set, copy, delete, increment, append, merge, merge_object, select, compare, format. |
✅ |
subgraph |
Reference another registered graph as a node. Enables composition and reuse. | ✅ |
human_approval |
HITL gate. Emits an InterruptError and waits for external approval via checkpoint/resume. |
✅ |
Router example
use ;
use json;
let graph = builder
.add_node
.add_node
.add_node
.add_node
.add_edge
.add_router
.add_edge
.add_edge
.add_edge
.build?;
Parallel fan-out with join
let graph = builder
.add_node
.add_node
.add_node
.add_node
.add_node
.add_node
.add_edge
.add_edge
.add_edge
.add_edge
.add_edge
.add_edge
.add_edge
.add_edge
.with_reducers
.build?;
Checkpointing & interrupt/resume
Enable checkpointing to persist execution state to SQLite:
use SqliteCheckpointStore;
let store = open.await?;
let mut executor = new
.with_checkpoint_store;
// Execute with interrupt detection
match executor.execute_with_interrupt.await
Execution receipts
Every completed run produces a GraphExecutionReceiptV1:
Each step receipt carries:
- Node ID, attempt count, wall-clock duration
- Input/output state digests
- Error details (if any)
TraceCtx/AttemptId/TrialIdfrom stack-ids
Ecosystem
| Crate | Description | Status |
|---|---|---|
| ri-agent-graph | Core graph execution engine | ✅ v0.2.1 |
| agent-graph-mcp | MCP server — 25 typed tools for graph lifecycle, execution, approval, templates | ✅ v0.2.2 |
| stack-ids | Shared identity, scope, and trace primitives | ✅ v0.1.3 |
| llm-pipeline | Reusable LLM node payloads (Ollama, prompt templating, parsing) | ✅ v0.2.0 |
API overview
// Core types
// The graph: nodes + edges + reducers
AgentState // Key-value state flowing through execution
// The runtime engine
GraphExecutionReceiptV1 // Cryptographic execution receipt
// Node construction
node! // Inline closure node
passthrough_node! // No-op passthrough
router! // Conditional routing
join_node! // Fan-in synchronization
// Sentinels
START // Virtual entry node
END // Virtual exit node
Claim boundaries
- This crate provides graph execution semantics — it does not include LLM provider clients, prompt templating, or response parsing. Those belong in
llm-pipelineor your application layer. - Receipts prove structural execution — they do not prove that an external LLM call occurred, what model responded, or what the provider's internal state was. Receipts carry cryptographic digests of the local execution trace only.
- Interrupt/resume is deterministic local resume — it supports linear chains of deterministic
passthroughand localstate_transformnodes with SQLite-bound state. It does not support resuming across LLM calls, network I/O, or external tool invocations. - Parallelism is best-effort — concurrent branch execution uses Tokio's
JoinSet. Unordered parallel writes to the same state key are rejected unless an explicitReduceris declared.
Error handling
All fallible operations return Result<T, AgentGraphError>:
Verification
# Build
# Test
# Clippy (strict)
# Format check
# Publish dry-run
Roadmap
- Typed state extractors (derive macro for
StateExtract) - Graph visualization (Mermaid/DOT export)
- Streaming LLM token passthrough
- Distributed checkpoint backend (PostgreSQL, S3)
- Subgraph composition with state isolation
- WebAssembly target support (
wasm-bindgen)
License
MIT — see LICENSE-MIT for details.
Built by RecursiveIntell — an applied R&D studio building local-first AI infrastructure.