adk-graph
Graph-based workflow orchestration for Rust Agent Development Kit (ADK-Rust) agents, inspired by LangGraph.
Overview
adk-graph provides a powerful way to build complex, stateful agent workflows using a graph-based approach. It brings LangGraph-style capabilities to the Rust ADK ecosystem while maintaining full compatibility with ADK's agent system, callbacks, and streaming infrastructure.
Features
- Graph-Based Workflows: Define agent workflows as directed graphs with nodes and edges
- AgentNode: Wrap LLM agents as graph nodes with custom input/output mappers
- Cyclic Support: Native support for loops and iterative reasoning (ReAct pattern)
- Conditional Routing: Dynamic edge routing based on state
- State Management: Typed state with reducers (overwrite, append, sum, custom)
- Checkpointing: Persistent state after each step (memory, SQLite)
- Durable Resume: Automatically resume from the last checkpoint after a crash — skips already-completed nodes
- Human-in-the-Loop: Interrupt before/after nodes, dynamic interrupts
- Streaming: Multiple stream modes (values, updates, messages, debug)
- ADK Integration: Full callback support, works with existing runners
- Functional API (feature:
functional): Write workflows as async functions with automatic checkpointing - Typed State Reducers: ReducedValue, UntrackedValue, MessagesValue containers
- State Schema Validation: Type-level validation at workflow boundaries
- Proc Macros:
#[entrypoint]and#[task]for zero-boilerplate workflow definition
Architecture
┌─────────────────────────────────────────┐
│ Agent Trait │
│ (name, description, run, sub_agents) │
└────────────────┬────────────────────────┘
│
┌───────────────────────┼───────────────────────┐
│ │ │
┌──────▼──────┐ ┌─────────▼─────────┐ ┌─────────▼─────────┐
│ LlmAgent │ │ GraphAgent │ │ RealtimeAgent │
│ (text-based)│ │ (graph workflow) │ │ (voice-based) │
└─────────────┘ └───────────────────┘ └───────────────────┘
Quick Start
Add to your Cargo.toml:
[]
= { = "1.0.0", = ["sqlite"] }
= "1.0.0"
= "1.0.0"
= "1.0.0"
Basic Graph with AgentNode
use ;
use LlmAgentBuilder;
use GeminiModel;
use json;
use Arc;
async
Conditional Routing with LLM Classification
use ;
// Create a classifier agent
let classifier = new;
let classifier_node = new
.with_input_mapper
.with_output_mapper;
// Build conditional routing graph
let graph = with_channels
.add_node
.add_node
.add_node
.add_node
.add_edge
.add_conditional_edges
.add_edge
.add_edge
.add_edge
.compile?;
Human-in-the-Loop with Risk Assessment
use ;
let checkpointer = new;
// Planner agent assesses risk
let planner_node = new
.with_output_mapper;
let graph = with_channels
.add_node
.add_node
.add_node_fn
.add_edge
.add_edge
.add_edge
.add_edge
.compile?
.with_checkpointer_arc;
// Execute - may pause for approval
let result = graph.invoke.await;
match result
ReAct Agent with Tools
use Part;
use FunctionTool;
// Create agent with tools
let reasoner = new;
let reasoner_node = new
.with_output_mapper;
// Build ReAct graph with cycle
let graph = with_channels
.add_node
.add_node_fn
.add_edge
.add_edge
.add_conditional_edges
.compile?
.with_recursion_limit;
Node Types
AgentNode
Wraps any ADK Agent (typically LlmAgent) as a graph node:
let node = new
.with_input_mapper
.with_output_mapper;
FunctionNode
Simple async functions for data processing:
.node_fn
State Management
Channels and Reducers
let schema = builder
.channel // Overwrite (default)
.list_channel // Append to list
.channel_with_reducer // Sum values
.build;
Checkpointing
// Memory (development)
let checkpointer = new;
// SQLite (production)
let checkpointer = new.await?;
// View checkpoint history
let checkpoints = checkpointer.list.await?;
for cp in checkpoints
Durable Resume
When a checkpointer is configured, the executor automatically checks for existing checkpoints before starting. If a checkpoint exists for the thread ID, execution resumes from where it left off — skipping already-completed nodes:
use *;
use Arc;
let checkpointer = new;
let graph = builder
.description
.node_fn
.node_fn
.edge
.edge
.edge
.checkpointer_arc
.build?;
// First run — completes step_a, saves checkpoint, then crashes before step_b
// Second run — resumes from checkpoint, skips step_a, runs only step_b
let result = graph.invoke.await?;
When streaming, a StreamEvent::Resumed event is emitted to indicate execution was restored from a checkpoint.
Examples
Examples are in the adk-playground repo:
# Parallel LLM agents with callbacks
# Sequential multi-agent pipeline
# LLM-based sentiment classification and routing
# ReAct pattern with tools
# Multi-agent supervisor
# Human-in-the-loop with risk assessment
# Checkpointing and time travel
Comparison with LangGraph
| Feature | LangGraph | adk-graph |
|---|---|---|
| State Management | TypedDict + Reducers | StateSchema + Reducers |
| Execution Model | Pregel super-steps | Pregel super-steps |
| Checkpointing | Memory, SQLite, Postgres | Memory, SQLite |
| Human-in-Loop | interrupt_before/after | interrupt_before/after + dynamic |
| Streaming | 5 modes | 5 modes |
| Cycles | Native support | Native support |
| Type Safety | Python typing | Rust type system |
| LLM Integration | LangChain | AgentNode + ADK agents |
Feature Flags
| Flag | Description |
|---|---|
sqlite |
Enable SQLite checkpointer |
functional |
Functional API: TaskContext, typed reducers, schema validation, proc macros |
full |
Enable all features |
License
Apache-2.0
Functional API
The Functional API (feature: functional) provides a higher-level programming model that lets you write agent workflows as normal async Rust functions with automatic checkpointing, typed state reducers, and interrupt/resume support.
Quick Start
[]
= { = "1.0.0", = ["functional"] }
use Arc;
use MemoryCheckpointer;
use ;
use StateSchema;
// Create a TaskContext with a checkpointer
let checkpointer = new;
let schema = builder
.channel
.list_channel
.build;
// ReducedValue — append-only accumulator
let mut results: = new;
results.push;
results.push;
assert_eq!;
// MessagesValue — chat messages with deduplication
let mut messages = new;
// Duplicate IDs are replaced (upsert semantics)
// ExecutionLog — resume-skip behavior
let mut log = new;
log.record_start;
log.record_completion;
assert!; // Skip on resume
Features
| Type | Purpose |
|---|---|
TaskContext |
Runtime context for tasks (state, checkpointing, streaming, interrupts) |
ReducedValue<T> |
Append-only accumulator persisted across checkpoints |
UntrackedValue<T> |
Transient data excluded from checkpoints |
MessagesValue |
Chat messages with ID-based deduplication |
StateSchemaValidator |
Type validation for state and task output |
ExecutionLog |
Task completion tracking for resume-skip |
TypedReducer |
Custom merge strategies (Replace, Append, Merge) |
Examples
Part of ADK-Rust
This crate is part of the ADK-Rust framework for building AI agents in Rust.