Skip to main content

adk_graph/
lib.rs

1//! # adk-graph
2#![allow(clippy::result_large_err)]
3//!
4//! Graph-based workflow orchestration for ADK-Rust agents, inspired by LangGraph.
5//!
6//! ## Overview
7//!
8//! `adk-graph` provides a powerful way to build complex, stateful agent workflows
9//! using a graph-based approach. It brings LangGraph-style capabilities to the Rust
10//! ADK ecosystem while maintaining full compatibility with ADK's agent system,
11//! callbacks, and streaming infrastructure.
12//!
13//! ## Features
14//!
15//! - **Graph-Based Workflows**: Define agent workflows as directed graphs
16//! - **Cyclic Support**: Native support for loops and iterative reasoning
17//! - **Conditional Routing**: Dynamic edge routing based on state
18//! - **State Management**: Typed state with reducers (overwrite, append, sum, custom)
19//! - **Checkpointing**: Persistent state after each step
20//! - **Human-in-the-Loop**: Interrupt before/after nodes, dynamic interrupts
21//! - **Streaming**: Multiple stream modes (values, updates, messages, debug)
22//! - **ADK Integration**: Full callback support, works with existing runners
23//! - **Functional API** (`functional` feature): Write workflows as async functions
24//!   with `#[entrypoint]`/`#[task]` macros, automatic checkpointing, typed state
25//!   reducers (ReducedValue, UntrackedValue, MessagesValue), state schema
26//!   validation, interrupt/resume, and loop iteration checkpoint keying
27//!
28//! ## Quick Start
29//!
30//! ```rust,ignore
31//! use adk_graph::prelude::*;
32//!
33//! let agent = GraphAgent::builder("processor")
34//!     .description("Process data through multiple steps")
35//!     .node_fn("fetch", |ctx| async move {
36//!         Ok(NodeOutput::new().with_update("data", json!({"items": [1, 2, 3]})))
37//!     })
38//!     .node_fn("transform", |ctx| async move {
39//!         let data = ctx.state.get("data").unwrap();
40//!         Ok(NodeOutput::new().with_update("result", data.clone()))
41//!     })
42//!     .edge(START, "fetch")
43//!     .edge("fetch", "transform")
44//!     .edge("transform", END)
45//!     .build()?;
46//!
47//! // Execute
48//! let result = agent.invoke(State::new(), ExecutionConfig::new("thread_1")).await?;
49//! ```
50//!
51//! ## ReAct Pattern
52//!
53//! ```rust,ignore
54//! use adk_graph::prelude::*;
55//!
56//! let react_agent = GraphAgent::builder("react")
57//!     .node(llm_agent_node)
58//!     .node_fn("tools", execute_tools)
59//!     .edge(START, "llm")
60//!     .conditional_edge(
61//!         "llm",
62//!         |state| {
63//!             if has_tool_calls(state) { "tools" } else { END }
64//!         },
65//!         [("tools", "tools"), (END, END)],
66//!     )
67//!     .edge("tools", "llm")  // Cycle back
68//!     .recursion_limit(25)
69//!     .build()?;
70//! ```
71
72pub mod agent;
73pub mod checkpoint;
74pub mod child;
75pub mod deferred;
76pub mod edge;
77pub mod error;
78pub mod executor;
79pub mod graph;
80pub mod interrupt;
81pub mod node;
82pub mod retry;
83pub mod state;
84pub mod stream;
85pub mod subgraph;
86pub mod timeout;
87pub mod tool;
88
89#[cfg(feature = "node-cache")]
90pub mod cache;
91
92#[cfg(feature = "delta-checkpoint")]
93pub mod delta;
94
95#[cfg(feature = "time-travel")]
96pub mod time_travel;
97
98#[cfg(feature = "action")]
99pub mod action;
100#[cfg(feature = "action")]
101pub mod workflow;
102
103#[cfg(feature = "functional")]
104pub mod functional;
105
106// Functional API re-exports for convenient access
107#[cfg(feature = "functional")]
108pub use functional::schema::{ExpectedType, StateSchemaValidator};
109#[cfg(feature = "functional")]
110pub use functional::{
111    AppendReducer, ExecutionLog, FunctionalError, MergeReducer, MessagesValue, ReducedValue,
112    ReplaceReducer, TaskContext, TypedReducer, UntrackedValue,
113};
114
115// Re-exports
116pub use agent::{GraphAgent, GraphAgentBuilder};
117pub use checkpoint::{Checkpointer, MemoryCheckpointer};
118pub use deferred::{DeferredNodeConfig, FanInTracker, MergeStrategy};
119pub use edge::{END, Edge, EdgeTarget, Router, START};
120pub use error::{GraphError, InterruptedExecution, Result};
121pub use executor::PregelExecutor;
122pub use graph::{CompiledGraph, StateGraph};
123pub use interrupt::{Interrupt, interrupt, interrupt_with_data};
124pub use node::{AgentNode, ExecutionConfig, FunctionNode, Node, NodeContext, NodeOutput};
125pub use state::{Channel, Checkpoint, Reducer, State, StateSchema, StateSchemaBuilder};
126pub use stream::{StreamEvent, StreamMode};
127pub use timeout::{OnTimeout, ProgressHandle, TimeoutPolicy, execute_with_timeout};
128
129#[cfg(feature = "sqlite")]
130pub use checkpoint::SqliteCheckpointer;
131
132#[cfg(feature = "node-cache")]
133pub use cache::{CacheBackend, NodeCache, NodeCachePolicy, compute_cache_key};
134
135#[cfg(feature = "delta-checkpoint")]
136pub use delta::{
137    CheckpointType, DeltaCheckpointer, DeltaConfig, Diff, MapDelta, StringDelta, StringOp, VecDelta,
138};
139
140#[cfg(feature = "time-travel")]
141pub use time_travel::{StepInfo, TimeTravelHandle};
142
143/// Prelude module for convenient imports
144pub mod prelude {
145    pub use crate::agent::{GraphAgent, GraphAgentBuilder};
146    pub use crate::checkpoint::{Checkpointer, MemoryCheckpointer};
147    pub use crate::deferred::{DeferredNodeConfig, FanInTracker, MergeStrategy};
148    pub use crate::edge::{END, Edge, EdgeTarget, Router, START};
149    pub use crate::error::{GraphError, InterruptedExecution, Result};
150    pub use crate::graph::{CompiledGraph, StateGraph};
151    pub use crate::interrupt::{Interrupt, interrupt, interrupt_with_data};
152    pub use crate::node::{
153        AgentNode, ExecutionConfig, FunctionNode, Node, NodeContext, NodeOutput,
154    };
155    pub use crate::state::{Channel, Checkpoint, Reducer, State, StateSchema, StateSchemaBuilder};
156    pub use crate::stream::{StreamEvent, StreamMode};
157
158    #[cfg(feature = "sqlite")]
159    pub use crate::checkpoint::SqliteCheckpointer;
160
161    #[cfg(feature = "action")]
162    pub use crate::action::ActionNodeExecutor;
163
164    // Re-export commonly used serde_json
165    pub use serde_json::{Value, json};
166}