pub struct StateGraphExecutor { /* private fields */ }Expand description
Executor for StateGraph — walks cyclic graph with conditional routing.
The executor processes a StateGraph by:
- Starting at the
entry_pointnode - Executing each node’s
NodeActionvia theGraphActionExecutor - Evaluating outgoing
EdgeConditions to select the next node - Handling interrupt points (nodes marked with
interrupt: true) - 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
impl StateGraphExecutor
Sourcepub fn new(
action_executor: Arc<dyn GraphActionExecutor>,
delegate_factory: Arc<dyn DelegateFactory>,
interaction_gate: Arc<dyn InteractionGate>,
max_iterations: usize,
) -> Self
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.
Sourcepub fn with_defaults(
action_executor: Arc<dyn GraphActionExecutor>,
delegate_factory: Arc<dyn DelegateFactory>,
interaction_gate: Arc<dyn InteractionGate>,
) -> Self
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).
Sourcepub fn with_custom_condition(
self,
name: impl Into<String>,
evaluator: CustomConditionFn,
) -> Self
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.
Sourcepub 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
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).
Sourcepub 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
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.
Sourcepub async fn execute(
&self,
graph: &StateGraph,
initial_state: GraphState,
) -> Result<GraphExecutionResult>
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:
- If any frontier node is terminal, execute the deterministic-first
one alone and return
completed: true. - 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
interruptpoint; 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). - Route each executed node’s outgoing edges (
route_next_nodes— all satisfiable edges, so a node with twoAlwaysedges 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). - Terminate when the frontier is empty,
should_terminateis set, ormax_iterationsis 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.