Skip to main content

StateGraph

Struct StateGraph 

Source
pub struct StateGraph<S: State, I: IntoState<S> = S, O: FromState<S> = S> { /* private fields */ }
Expand description

Builder for constructing executable Juncture graphs

§Examples

use juncture_core::{StateGraph, State, IntoNode};

struct MyState;
impl State for MyState { type Update = MyStateUpdate; }
struct MyStateUpdate;

// Build a simple graph
let mut graph = StateGraph::<MyState>::new();
graph.add_node_simple("process", |state: MyState| async move {
    Ok(MyStateUpdate)
});
graph.set_entry_point("process");
graph.set_finish_point("process");

// Compile and validate
let compiled = graph.compile()?;

Implementations§

Source§

impl<S: State, I: IntoState<S>, O: FromState<S>> StateGraph<S, I, O>

Source

pub fn new() -> Self

Create a new empty graph

Source

pub fn add_node( &mut self, name: impl Into<String>, node: impl IntoNode<S>, defer: bool, metadata: Option<HashMap<String, Value>>, destinations: Option<Vec<String>>, retry_policies: Vec<RetryPolicy>, timeout_policies: Vec<TimeoutPolicy>, ) -> Result<&mut Self, TopologyError>

Add a node with full configuration options

Returns &mut Self on success for fluent builder chaining.

§Errors

Returns an error if a node with the same name already exists.

§Panics

Panics if the node name contains invalid characters for graph identifiers.

Source

pub fn add_node_simple( &mut self, name: impl Into<String>, node: impl IntoNode<S>, ) -> Result<&mut Self, TopologyError>

Add a node with default configuration options

This convenience method uses these defaults:

  • defer: false
  • metadata: None
  • destinations: None
  • retry_policies: empty
  • timeout_policies: empty

Returns &mut Self on success for fluent builder chaining.

§Errors

Returns an error if a node with the same name already exists.

Source

pub fn add_node_with_error_handler( &mut self, name: impl Into<String>, node: impl IntoNode<S>, handler: Arc<dyn Fn(NodeError<S>) -> Command<S> + Send + Sync>, ) -> Result<&mut Self, TopologyError>
where S: Clone,

Add a node with an error recovery handler

When the wrapped node returns an error, the handler is invoked to produce a fallback command instead of propagating the error.

The handler receives NodeError with detailed information (node name, error, state snapshot, attempt count) and returns a recovery command.

Returns &mut Self on success for fluent builder chaining.

§Arguments
  • name - Node name
  • node - The node to wrap
  • handler - Error recovery function receiving NodeError
§Errors

Returns an error if a node with the same name already exists.

Source

pub fn add_node_with_retry( &mut self, name: impl Into<String>, node: impl IntoNode<S>, policy: RetryPolicy, ) -> Result<&mut Self, TopologyError>
where S: Clone,

Add a node with automatic retry behavior

When the wrapped node fails, it is retried according to the provided retry policy with exponential backoff.

Returns &mut Self on success for fluent builder chaining.

§Arguments
  • name - Node name
  • node - The node to wrap
  • policy - Retry policy governing retry behavior
§Errors

Returns an error if a node with the same name already exists.

Source

pub fn add_subgraph( &mut self, mount: SubgraphMount<S>, ) -> Result<&mut Self, TopologyError>

Add a compiled subgraph as a node in this graph

The subgraph is mounted with input/output mapping functions that transform state between the parent and child graph.

Returns &mut Self on success for fluent builder chaining.

§Arguments
  • mount - Subgraph mount containing the compiled graph and mapping functions
§Errors

Returns an error if a node with the same name as the subgraph already exists.

Source

pub fn add_subgraph_node<Sub>( &mut self, name: &str, subgraph: Arc<CompiledGraph<Sub>>, ) -> Result<&mut Self, TopologyError>
where Sub: StateSubset<S> + State + Clone + Serialize + for<'de> Deserialize<'de>, Sub::Update: Serialize, S: Clone,

Add a subgraph with shared state using StateSubset

This method adds a subgraph that shares state with its parent graph using the StateSubset trait for type-safe state transformation.

§Type Parameters
  • Sub - The subgraph’s state type, which must implement StateSubset<S>
§Arguments
  • name - The node name for the subgraph mount point
  • subgraph - The compiled subgraph to add
§Returns

A mutable reference to self for chaining

§Errors

Returns an error if a node with the same name already exists.

Source

pub fn add_subgraph_with_config<Sub>( &mut self, name: &str, subgraph: Arc<CompiledGraph<Sub>>, input_map: impl Fn(&S) -> Sub + Send + Sync + 'static, output_map: impl Fn(&Sub) -> S::Update + Send + Sync + 'static, config: SubgraphConfig, ) -> Result<&mut Self, TopologyError>
where Sub: State + Serialize + for<'de> Deserialize<'de>, Sub::Update: Serialize, S: Clone,

Add a subgraph with explicit state mapping and custom config

This method adds a subgraph with different state types than the parent, using explicit mapping functions to transform between state types.

§Type Parameters
  • Sub - The subgraph’s state type
§Arguments
  • name - The node name for the subgraph mount point
  • subgraph - The compiled subgraph to add
  • input_map - Function to transform parent state to subgraph input
  • output_map - Function to transform subgraph output to parent state update
  • config - Subgraph configuration options
§Returns

A mutable reference to self for chaining

§Errors

Returns an error if a node with the same name already exists.

Source

pub fn add_subgraph_explicit<Sub>( &mut self, name: &str, subgraph: Arc<CompiledGraph<Sub>>, input_map: impl Fn(&S) -> Sub + Send + Sync + 'static, output_map: impl Fn(&Sub) -> S::Update + Send + Sync + 'static, ) -> Result<&mut Self, TopologyError>
where Sub: State + Serialize + for<'de> Deserialize<'de>, Sub::Update: Serialize, S: Clone,

Add a subgraph with explicit state mapping using default config

Convenience overload for add_subgraph_with_config() that uses SubgraphConfig::default(). See that method for full documentation.

§Type Parameters
  • Sub - The subgraph’s state type
§Arguments
  • name - The node name for the subgraph mount point
  • subgraph - The compiled subgraph to add
  • input_map - Function to transform parent state to subgraph input
  • output_map - Function to transform subgraph output to parent state update
§Errors

Returns an error if a node with the same name already exists.

Source

pub fn add_edge(&mut self, from: impl Into<String>, to: impl Into<String>)

Add a fixed edge between two nodes

§Examples
graph.add_edge("node_a", "node_b")?;
§Errors

This method doesn’t validate node existence. Validation happens during compile.

Source

pub fn add_conditional_edges( &mut self, from: impl Into<String>, router: Arc<dyn Router<S>>, path_map: PathMap, )

Add a conditional edge with dynamic routing

§Examples
use juncture_core::edge::{PathMap, Router};
use std::sync::Arc;

let router = |state: &MyState| -> &str {
    if state.should_continue { "continue" } else { "stop" }
};

let path_map = PathMap::from(&[
    ("continue", "process_more"),
    ("stop", "finish"),
]);

graph.add_conditional_edges("decide", Arc::new(router), path_map)?;
§Errors

This method doesn’t validate node existence or path map targets. Validation happens during compile.

Source

pub fn set_entry_point(&mut self, node: impl Into<String>)

Set the entry point for the graph

This is equivalent to add_edge(START, node).

§Examples
graph.set_entry_point("start_node");
Source

pub fn set_finish_point(&mut self, node: impl Into<String>)

Set a finish point for the graph

This is equivalent to add_edge(node, END).

§Examples
graph.set_finish_point("end_node");
Source

pub fn add_sequence( &mut self, nodes: &[impl AsRef<str>], ) -> Result<&mut Self, TopologyError>

Add a sequence of nodes as a chain

Automatically adds edges between consecutive nodes and sets the first node as the entry point.

Returns &mut Self on success for fluent builder chaining.

§Examples
graph.add_sequence(&["step1", "step2", "step3"])?;
§Errors

Returns an error if any of the nodes don’t exist.

Source

pub fn validate_keys(&self) -> Result<(), TopologyError>

Validate that all state keys are present

Key validation ensures that all nodes can access their required state fields. This validates:

  • Node names are non-empty and contain no reserved characters
  • Entry point references an existing node
  • Finish points reference existing nodes
  • Reducer field indices are within bounds of the State type’s field count
§Errors

Returns TopologyError if:

  • A node name is empty or contains reserved characters (:, /, \)
  • Entry point references a non-existent node
  • A finish point references a non-existent node
  • A reducer field index exceeds the number of fields in the State type
Source

pub fn compile(&self) -> Result<CompiledGraph<S, I, O>, TopologyError>

Compile the graph into an executable form

Runs topology validation and builds the optimized execution structure using default compile configuration (no compile-time interrupts).

§Errors

Returns TopologyError if validation fails.

§Examples
let compiled = graph.compile()?;
Source

pub fn compile_with_config( &self, config: CompileConfig, ) -> Result<CompiledGraph<S, I, O>, TopologyError>

Compile the graph with explicit compile-time configuration

Like compile but accepts a CompileConfig that sets compile-time defaults for interrupt behavior. Runtime [RunnableConfig] values override these when present.

§Errors

Returns TopologyError if validation fails.

§Examples
use juncture_core::graph::CompileConfig;

let compiled = graph.compile_with_config(CompileConfig {
    interrupt_before: vec!["human_review".into()],
    interrupt_after: vec!["llm_call".into()],
    ..Default::default()
})?;
Source

pub fn compile_ephemeral(&self) -> Result<CompiledGraph<S, I, O>, TopologyError>

Compile the graph without persistence (dev/test)

Creates a compiled graph with no checkpointer attached. Useful for development and testing where persistence is not needed.

§Errors

Returns TopologyError if validation fails.

Source

pub fn compile_with_checkpointer( &self, checkpointer: Option<Arc<dyn CheckpointSaver>>, ) -> Result<CompiledGraph<S, I, O>, TopologyError>

Compile the graph with optional checkpointer

This is a forward-compatible method that accepts an optional checkpointer. Uses default compile configuration (no compile-time interrupts).

§Errors

Returns TopologyError if validation fails.

Trait Implementations§

Source§

impl<S: State, I: IntoState<S>, O: FromState<S>> Debug for StateGraph<S, I, O>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<S: State, I: IntoState<S>, O: FromState<S>> Default for StateGraph<S, I, O>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl<S, I, O> Freeze for StateGraph<S, I, O>

§

impl<S, I = S, O = S> !RefUnwindSafe for StateGraph<S, I, O>

§

impl<S, I, O> Send for StateGraph<S, I, O>

§

impl<S, I, O> Sync for StateGraph<S, I, O>

§

impl<S, I, O> Unpin for StateGraph<S, I, O>
where I: Unpin, O: Unpin,

§

impl<S, I, O> UnsafeUnpin for StateGraph<S, I, O>

§

impl<S, I = S, O = S> !UnwindSafe for StateGraph<S, I, O>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more