Skip to main content

StateGraphExecutor

Struct StateGraphExecutor 

Source
pub struct StateGraphExecutor { /* private fields */ }
Expand description

Executor for StateGraph — walks cyclic graph with conditional routing.

The executor processes a StateGraph by:

  1. Starting at the entry_point node
  2. Executing each node’s NodeAction via the GraphActionExecutor
  3. Evaluating outgoing EdgeConditions to select the next node
  4. Handling interrupt points (nodes marked with interrupt: true)
  5. Terminating when a terminal node is reached or max iterations exceeded

P2-2: The executor now uses a GraphActionExecutor for node action execution. This enables AgentLoop integration — when an AgentLoopGraphActionExecutor (from oneai-agent) is provided, LlmInfer/ToolCall nodes delegate to the AgentLoop’s full pipeline (hooks, permission, domain pack, tool definitions).

Template interpolation ({{variable}}) is still applied to tool_name and args_template fields before tool execution, using GraphState.variables.

Implementations§

Source§

impl StateGraphExecutor

Source

pub fn new( action_executor: Arc<dyn GraphActionExecutor>, delegate_factory: Arc<dyn DelegateFactory>, interaction_gate: Arc<dyn InteractionGate>, max_iterations: usize, ) -> Self

Create a new StateGraphExecutor with a GraphActionExecutor.

This is the P2-2 constructor — when an AgentLoopGraphActionExecutor is provided, LlmInfer/ToolCall nodes get full AgentLoop integration.

Source

pub fn with_defaults( action_executor: Arc<dyn GraphActionExecutor>, delegate_factory: Arc<dyn DelegateFactory>, interaction_gate: Arc<dyn InteractionGate>, ) -> Self

Create with default max_iterations (50).

Source

pub fn with_custom_condition( self, name: impl Into<String>, evaluator: CustomConditionFn, ) -> Self

Register a user-provided evaluator for EdgeCondition::Custom { name, .. }.

When the graph routes along an edge whose condition is Custom, the executor looks up the registered callback by name and evaluates it against the current GraphState. Unregistered conditions warn and default to false. Multiple registrations may be chained since this consumes and returns Self.

Source

pub fn with_direct_provider( provider: Arc<dyn LlmProvider>, tools: Arc<RwLock<HashMap<String, Arc<dyn Tool>>>>, delegate_factory: Arc<dyn DelegateFactory>, interaction_gate: Arc<dyn InteractionGate>, max_iterations: usize, ) -> Self

Create with direct provider + tools (backward-compatible constructor).

This constructor creates a DirectProviderActionExecutor internally, providing the same behavior as the original StateGraphExecutor (before P2-2). Use this when you don’t have an AgentLoop available (e.g., standalone StateGraph execution without AgentLoop integration).

Source

pub fn with_direct_provider_defaults( provider: Arc<dyn LlmProvider>, tools: Arc<RwLock<HashMap<String, Arc<dyn Tool>>>>, delegate_factory: Arc<dyn DelegateFactory>, interaction_gate: Arc<dyn InteractionGate>, ) -> Self

Create with direct provider + default max_iterations (50). Backward-compatible with the original with_defaults() constructor.

Source

pub async fn execute( &self, graph: &StateGraph, initial_state: GraphState, ) -> Result<GraphExecutionResult>

Execute a StateGraph starting from its entry point.

Walks the graph as a frontier of ready nodes (not a single walker). Each iteration:

  1. If any frontier node is terminal, execute the deterministic-first one alone and return completed: true.
  2. Otherwise execute every frontier node — sequentially when the frontier has one node (the historical ReAct/conditional case, no clone overhead, behaviour identical to the pre-frontier loop) or any node carries an interrupt point; concurrently when the frontier fans out ≥2 non-interrupt nodes (a fork — each branch runs on an isolated state clone, results merged back deterministically by node ID order).
  3. Route each executed node’s outgoing edges (route_next_nodes — all satisfiable edges, so a node with two Always edges forks both targets). The union of targets is the next frontier; a target reached by multiple branches appears once (natural join — it runs only after the barrier since all branches completed this iteration).
  4. Terminate when the frontier is empty, should_terminate is set, or max_iterations is exceeded.

Single-branch graphs (the common ReAct/conditional case) keep frontier size 1 throughout → the sequential path → identical to the old loop (regression guarantee). Forks (≥2 simultaneous satisfiable edges) are the only behaviour that differs, and they couldn’t be expressed before.

Auto Trait Implementations§

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 = !

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

fn try_from(value: U) -> Result<T, !>

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<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