Skip to main content

TurnStateMachine

Struct TurnStateMachine 

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

State machine for turn orchestration.

This is the core abstraction that unifies turn logic between in-memory and durable execution. It tracks the current phase, determines the next action, and handles state transitions.

§Thread Safety

The state machine is not thread-safe. For durable execution, each task execution creates its own state machine from serialized state.

Implementations§

Source§

impl TurnStateMachine

Source

pub fn new(context: TurnContext, max_iterations: usize) -> Self

Create a new state machine for a turn.

§Arguments
  • context - Turn context with session, turn, and agent IDs
  • max_iterations - Maximum Reason → Act cycles before stopping
Source

pub fn context(&self) -> &TurnContext

Get the turn context.

Source

pub fn phase(&self) -> TurnPhase

Get the current phase.

Source

pub fn current_iteration(&self) -> usize

Get the current iteration count.

Source

pub fn total_tool_calls(&self) -> usize

Get the total tool calls made so far.

Source

pub fn next_action(&self) -> TurnAction

Determine the next action to take.

This is the core dispatch method. Call this in a loop and execute the returned action until TurnAction::Complete is returned.

Source

pub fn on_input_completed(&mut self)

Record that input processing completed.

Call this after successfully executing the input atom.

Source

pub fn on_reason_completed( &mut self, response: String, has_tool_calls: bool, tool_call_count: usize, success: bool, error: Option<String>, has_pending_user_messages: bool, )

Record that reasoning completed.

§Arguments
  • response - The text response from the LLM (may be empty)
  • has_tool_calls - Whether the LLM requested tool calls
  • tool_call_count - Number of tool calls (0 if none)
  • success - Whether the LLM call succeeded
  • error - Error message if success is false
  • has_pending_user_messages - Whether new user messages arrived during this turn (steering signals). When true and reason would otherwise complete (no tool calls, success), the turn stays in PendingReason so the next iteration picks up the new messages from the conversation history. This is “in-turn steering” — matching Claude Code behavior.
Source

pub fn on_act_completed(&mut self)

Record that action (tool execution) completed.

Call this after successfully executing the act atom. The turn then loops back to Reason for another iteration.

Source

pub fn seal(&mut self, reason: SealReason)

Deliberately seal the turn, stopping further scheduling (EVE-534).

Call this between atoms when the engine decides to stop a turn to prevent waste — e.g. the work budget is exhausted (SealReason::Budget). The turn transitions to Completed and next_action resolves to TurnOutcome::Sealed. Sealing is idempotent and the first reason wins.

Source

pub fn is_completed(&self) -> bool

Check if the turn has completed.

Trait Implementations§

Source§

impl Debug for TurnStateMachine

Source§

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

Formats the value using the given formatter. Read more

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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FutureExt for T

Source§

fn with_context(self, otel_cx: Context) -> WithContext<Self>

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
Source§

fn with_current_context(self) -> WithContext<Self>

Attaches the current Context to this type, returning a WithContext wrapper. Read more
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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> IntoRequest<T> for T

Source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
Source§

impl<L> LayerExt<L> for L

Source§

fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>
where L: Layer<S>,

Applies the layer to a service and wraps it in Layered.
Source§

impl<T> ParallelSend for T

Source§

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

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
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