Skip to main content

AgentEvent

Enum AgentEvent 

Source
#[non_exhaustive]
pub enum AgentEvent {
Show 16 variants TurnStarted, UserPromptCommitted { content: Vec<ContentBlock>, }, TurnEnded { reason: StopReason, usage: Usage, }, TurnAborted, AssistantText { content: ContentBlock, }, AssistantThought { content: ContentBlock, }, ToolCallStarted { id: ToolCallId, name: String, fields: ToolCallUpdateFields, }, ToolCallProgress { id: ToolCallId, fields: ToolCallUpdateFields, }, ToolCallFinished { id: ToolCallId, fields: ToolCallUpdateFields, }, PolicyDecision { id: ToolCallId, decision: PolicyDecision, }, PermissionResolved { id: ToolCallId, outcome: PermissionResolution, }, LlmCallStarted { model: String, attempt: u32, request: Arc<LlmRequestSnapshot>, }, LlmCallFinished { model: String, attempt: u32, usage: Usage, error: Option<String>, }, ContextCompressed { tokens_before: u64, tokens_after: u64, }, ContextMicrocompacted { tokens_before: u64, tokens_after: u64, cleared: usize, }, Subagent { ancestor_path: Vec<ToolCallId>, agent_type: String, inner: Box<AgentEvent>, },
}
Expand description

Events published by the agent main loop.

Final-state semantics: the event stream for a turn starts with AgentEvent::TurnStarted and ends with AgentEvent::TurnEnded. After TurnEnded, no more events for that turn are produced — defect-acp stops pushing session/update and responds with PromptResponse upon seeing it.

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

TurnStarted

A prompt turn has started.

§

UserPromptCommitted

The user prompt has been committed to history by the main loop.

Fields

§

TurnEnded

A prompt turn ended. reason directly borrows the semantic category from ACP.

Fields

§reason: StopReason
§usage: Usage

Cumulative token usage for this turn (field-wise sum from crate::llm::ProviderChunk::Usage).

§

TurnAborted

A prompt turn failed permanently (e.g. a provider error after retries) and was rolled back. Everything the turn appended to history — starting with the user prompt — has been discarded in memory; consumers that persist or mirror history (storage) must drop the same tail so a failed turn leaves no orphan to be replayed on reload or re-sent on the next request. Audit-only on the wire (the ACP bridge reports failure via the JSON-RPC error, not this event).

§

AssistantText

Incremental assistant text. Maps to ACP SessionUpdate::AgentMessageChunk.

Fields

§

AssistantThought

Assistant thought chain delta. Maps to ACP SessionUpdate::AgentThoughtChunk.

Fields

§

ToolCallStarted

A tool call start declaration. Maps to ACP SessionUpdate::ToolCall (status = Pending).

§

ToolCallProgress

Tool call progress delta. Maps to ACP SessionUpdate::ToolCallUpdate.

§

ToolCallFinished

Tool call finished (success/failure is indicated by fields.status). Maps to ACP SessionUpdate::ToolCallUpdate (with a terminal status).

§

PolicyDecision

The sandbox policy makes a decision about a tool call. Ask triggers the ACP session/request_permission; Allow / Deny are only audited and not sent over the wire.

Fields

§

PermissionResolved

User’s response to a PolicyDecision::Ask. Audit-only, not sent on the wire.

§

LlmCallStarted

A single LLM provider call has started.

Fields

§model: String
§attempt: u32

The attempt number (1-based). Retries are driven by the main loop.

§request: Arc<LlmRequestSnapshot>

A snapshot of the request sent to the provider (system message + full message history).

Used by observability to reconstruct the generation’s input as a standard chat message array (including the system message). Not sent over the wire; storage currently ignores this field.

Wrapped in Arc: when events are fanned out to subscribers via crate::session::EventEmitter, each subscriber clones the event. With long contexts, deep-copying the entire message history repeatedly is expensive. The snapshot is read-only once inside the event, so Arc reduces clone to a reference-count increment. #[serde(skip)]: the serde derive on AgentEvent is not currently used, and we prefer not to enable serde’s rc feature for it—on deserialization this field takes the default empty snapshot.

§

LlmCallFinished

A single LLM provider call has finished. error being Some indicates failure (the retry hint determines whether to proceed to the next attempt).

Fields

§model: String
§attempt: u32
§usage: Usage
§error: Option<String>

Error description on failure (the full error object is not stored here — it goes into tracing).

§

ContextCompressed

The main loop compressed / truncated the history.

Fields

§tokens_before: u64
§tokens_after: u64
§

ContextMicrocompacted

The main loop performed a micro-compaction: it cleaned up oversized tool_result bodies from older turns (without calling the LLM or deleting messages). cleared is the number of tool_result entries actually cleaned. This is distinguished from Self::ContextCompressed so that observability and the UI can display them separately.

Fields

§tokens_before: u64
§tokens_after: u64
§cleared: usize
§

Subagent

A leaf event produced inside a spawn_agent sub-agent turn, bridged from the sub-turn’s isolated event stream into the parent session’s event stream.

Design intent: the sub-agent runs in a fresh, isolated context (its own crate::session::EventEmitter), and the parent agent cannot see its intermediate steps — this is the isolation contract of spawn_agent. However, observability (langfuse) wants to display the sub-turn’s LLM calls / tool calls nested under the parent’s spawn_agent tool call span. So spawn_agent attaches a bridging subscriber to the sub-emitter, wrapping each sub-event as this variant and forwarding it to the parent emitter.

§Flattening (supports recursive subagents)

inner is always a leaf event (never another Subagent). Nesting depth is expressed by the ancestor chain Self::Subagent::ancestor_path, not by nested Box wrappers: the chain lists ids from the top-level spawn_agent tool call down to the current layer. Each bridging layer prepends its own parent_tool_call_id to the chain head, leaving the leaf inner unchanged (see the bridge closure in spawn_agent.rs). The projector uses the full chain to locate the parent mount point — the chain is globally unique, naturally avoids ToolCallId collisions across sub-sessions, and the projector does not need to recursively unwrap.

Consumption contract: only the langfuse projector processes this (emitting nested generations/spans under the parent tool span). All other consumers (defect-storage persistence, defect-acp wire projection, REPL rendering) ignore it — the isolation contract remains unchanged for them.

Fields

§ancestor_path: Vec<ToolCallId>

Ancestor chain of ToolCallIds from the top-level spawn_agent tool call down to the current subagent layer. The head is the top-level spawn_agent (directly attached to the parent turn trace), and the tail is the spawn_agent that initiated this leaf event. Depth equals ancestor_path.len().

§agent_type: String

The profile name of the subagent that initiated this leaf event (e.g. weebs-in), used for naming / metadata of nested spans.

§inner: Box<AgentEvent>

The bridged child turn leaf event (never another Subagent). Box prevents the enum from growing unbounded due to self-reference.

Trait Implementations§

Source§

impl Clone for AgentEvent

Source§

fn clone(&self) -> AgentEvent

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

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

Performs copy-assignment from source. Read more
Source§

impl Debug for AgentEvent

Source§

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

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

impl<'de> Deserialize<'de> for AgentEvent

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl PartialEq for AgentEvent

Source§

fn eq(&self, other: &AgentEvent) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Serialize for AgentEvent

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for AgentEvent

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> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

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> IntoMaybeUndefined<T> for T

Source§

impl<T> IntoOption<T> for T

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