Skip to main content

LoopEvent

Enum LoopEvent 

Source
#[non_exhaustive]
pub enum LoopEvent {
Show 15 variants TextDelta(String), ReasoningDelta(String), ToolCallStart { index: u32, id: String, name: String, }, ToolCallDelta { index: u32, json_chunk: String, }, ToolCallComplete { index: u32, call: ToolCall, }, Usage(Usage), IterationStart { iteration: u32, message_count: usize, }, ToolExecutionStart { call_id: String, tool_name: String, arguments: Value, }, ToolExecutionEnd { call_id: String, tool_name: String, result: ToolResult, duration: Duration, }, ToolResultProcessed { tool_name: String, original_tokens: u32, processed_tokens: u32, }, ToolResultExtracted { tool_name: String, original_tokens: u32, extracted_tokens: u32, }, ToolResultCached { tool_name: String, original_tokens: u32, summary_tokens: u32, }, ObservationsMasked { masked_count: usize, tokens_saved: u32, }, LoopDetected { tool_name: String, consecutive_count: u32, action: LoopAction, }, Done(ToolLoopResult),
}
Expand description

Unified event emitted during tool loop execution.

LoopEvent merges LLM streaming events (text deltas, tool call fragments) with loop-level lifecycle events (iteration boundaries, tool execution progress) into a single stream. This gives consumers a complete, ordered view of everything happening inside the loop.

The stream terminates with Done carrying the final ToolLoopResult.

§Example

use llm_stack::tool::{tool_loop_stream, ToolLoopConfig, LoopEvent};
use futures::StreamExt;
use std::sync::Arc;

let mut stream = tool_loop_stream(provider, registry, params, ToolLoopConfig::default(), Arc::new(()));
while let Some(event) = stream.next().await {
    match event.unwrap() {
        LoopEvent::TextDelta(text) => print!("{text}"),
        LoopEvent::IterationStart { iteration, .. } => {
            println!("\n--- Iteration {iteration} ---");
        }
        LoopEvent::ToolExecutionStart { tool_name, .. } => {
            println!("[calling {tool_name}...]");
        }
        LoopEvent::ToolExecutionEnd { tool_name, duration, .. } => {
            println!("[{tool_name} completed in {duration:?}]");
        }
        LoopEvent::Done(result) => {
            println!("\nDone: {:?}", result.termination_reason);
            break;
        }
        _ => {}
    }
}

Variants (Non-exhaustive)§

This enum is marked as non-exhaustive
Non-exhaustive enums could have additional variants added in future. Therefore, when matching against variants of non-exhaustive enums, an extra wildcard arm must be added to account for any future variants.
§

TextDelta(String)

A fragment of the model’s text output.

§

ReasoningDelta(String)

A fragment of the model’s reasoning (chain-of-thought) output.

§

ToolCallStart

Announces that a new tool call has started.

Fields

§index: u32

Zero-based index identifying this call when multiple tools are invoked in parallel.

§id: String

Provider-assigned identifier linking start → deltas → complete.

§name: String

The name of the tool being called.

§

ToolCallDelta

A JSON fragment of the tool call’s arguments.

Fields

§index: u32

The tool-call index this delta belongs to.

§json_chunk: String

A chunk of the JSON arguments string.

§

ToolCallComplete

The fully assembled tool call, ready to execute.

Fields

§index: u32

The tool-call index this completion corresponds to.

§call: ToolCall

The complete, parsed tool call.

§

Usage(Usage)

Token usage information for this LLM call.

§

IterationStart

A new iteration of the tool loop is starting.

Fields

§iteration: u32

The iteration number (1-indexed).

§message_count: usize

Number of messages in the conversation so far.

§

ToolExecutionStart

About to execute a tool.

When parallel_tool_execution is true, events arrive in completion order (whichever tool finishes first), not the order the LLM listed the calls. Use call_id to correlate start/end pairs.

Fields

§call_id: String

The tool call ID from the LLM.

§tool_name: String

Name of the tool being called.

§arguments: Value

Arguments passed to the tool.

§

ToolExecutionEnd

Tool execution completed.

When parallel_tool_execution is true, events arrive in completion order. Use call_id to correlate with the corresponding ToolExecutionStart.

Fields

§call_id: String

The tool call ID from the LLM.

§tool_name: String

Name of the tool that was called.

§result: ToolResult

The result from the tool.

§duration: Duration

How long the tool took to execute.

§

ToolResultProcessed

A tool result was post-processed (compressed, truncated, etc.).

Emitted when a ToolResultProcessor modifies a tool’s output before it enters the conversation context. Use this for monitoring compression ratios and token savings.

Fields

§tool_name: String

Name of the tool whose result was processed.

§original_tokens: u32

Estimated token count of the original output.

§processed_tokens: u32

Estimated token count after processing.

§

ToolResultExtracted

A tool result was semantically extracted (condensed by an LLM).

Emitted when a ToolResultExtractor condenses a large tool result into task-relevant content using an async extraction call (typically a fast/cheap LLM like Haiku).

Fields

§tool_name: String

Name of the tool whose result was extracted.

§original_tokens: u32

Estimated token count before extraction.

§extracted_tokens: u32

Estimated token count after extraction.

§

ToolResultCached

A tool result was cached out-of-context.

Emitted when a ToolResultCacher stores an oversized result externally and replaces it with a compact summary.

Fields

§tool_name: String

Name of the tool whose result was cached.

§original_tokens: u32

Estimated token count of the content that was cached.

§summary_tokens: u32

Estimated token count of the summary that replaced it.

§

ObservationsMasked

Old tool results were masked before an LLM call.

Emitted when observation masking replaces old tool results with compact placeholders to reduce context size. The full results may still be available in the result cache.

Fields

§masked_count: usize

Number of tool results masked in this pass.

§tokens_saved: u32

Estimated total tokens saved by masking.

§

LoopDetected

A tool call loop was detected.

Emitted when the same tool is called with identical arguments for threshold consecutive times. Only emitted when LoopDetectionConfig is configured.

Fields

§tool_name: String

Name of the tool being called repeatedly.

§consecutive_count: u32

Number of consecutive identical calls detected.

§action: LoopAction

The action being taken in response.

§

Done(ToolLoopResult)

The loop has finished. Carries the final ToolLoopResult with the accumulated response, usage, iteration count, and termination reason.

Trait Implementations§

Source§

impl Clone for LoopEvent

Source§

fn clone(&self) -> LoopEvent

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for LoopEvent

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<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

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> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: 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: 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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