pub struct AgentState {
pub messages: Vec<Message>,
pub iteration: usize,
pub stop_reason: Option<StopReason>,
pub tool_results: Vec<ToolResult>,
pub total_tokens: usize,
pub input_tokens: usize,
pub output_tokens: usize,
pub last_input_tokens: Option<usize>,
pub last_estimate_at_report: Option<usize>,
pub last_estimate_divergence: Option<f64>,
}Expand description
Agent execution state
Tracks the full lifecycle of an agent conversation including messages, token usage, tool results, and iteration progress.
Derives Serialize/Deserialize for session persistence and
cross-process state transfer (e.g. oxios supervisor serialization).
Fields§
§messages: Vec<Message>Conversation message history (user, assistant, and tool-result messages).
iteration: usizeCurrent agent loop iteration (incremented after each assistant turn).
stop_reason: Option<StopReason>The reason the last turn stopped, if any.
tool_results: Vec<ToolResult>Accumulated results from tool executions in the current conversation.
total_tokens: usizeCumulative token count (input + output) across all turns.
input_tokens: usizeCumulative prompt / input tokens across all turns.
output_tokens: usizeCumulative completion / output tokens across all turns.
last_input_tokens: Option<usize>Most-recent reported input-token count from a single LLM response.
Unlike Self::input_tokens (which is cumulative across all turns),
this is overwritten on every ProviderEvent::Done with the count
that turn actually sent to the model. It is the ground-truth signal
used by compaction when available — see Self::current_token_source.
None until the first Done event has been observed.
last_estimate_at_report: Option<usize>Heuristic token estimate (bytes/4) that was current when
last_input_tokens was last set. Used to detect the bytes/4 drift
described in #28 and surface it as a warning.
last_estimate_divergence: Option<f64>Divergence factor (reported / estimate) at the time of the last
Done. Surfaced in logs so the operator can see how badly the
bytes/4 heuristic is undercounting on token-dense workloads.
None until first divergence observation.
Implementations§
Source§impl AgentState
impl AgentState
Sourcepub fn add_user_message(&mut self, content: String)
pub fn add_user_message(&mut self, content: String)
Add a user message
Sourcepub fn add_assistant_message(&mut self, content: String)
pub fn add_assistant_message(&mut self, content: String)
Add an assistant message
Sourcepub fn add_tool_result(&mut self, tool_call_id: String, content: String)
pub fn add_tool_result(&mut self, tool_call_id: String, content: String)
Add a tool result message to both the message history and the tool results list.
Sourcepub fn increment_iteration(&mut self)
pub fn increment_iteration(&mut self)
Increment the iteration counter after an assistant turn completes.
Sourcepub fn set_stop_reason(&mut self, reason: StopReason)
pub fn set_stop_reason(&mut self, reason: StopReason)
Record the reason the last turn stopped.
Sourcepub fn record_usage(&mut self, input: usize, output: usize)
pub fn record_usage(&mut self, input: usize, output: usize)
Accumulate token usage from a completed LLM call.
input is the input-token count for the just-completed turn —
NOT a per-turn delta. The provider reports a fresh per-turn
usage.input_tokens on every Done; we accumulate it into
Self::input_tokens for lifetime accounting and also cache
it as the most-recent observation via Self::record_provider_turn.
Sourcepub fn record_provider_turn(
&mut self,
input_tokens: usize,
estimate_at_report: usize,
)
pub fn record_provider_turn( &mut self, input_tokens: usize, estimate_at_report: usize, )
Record the most recent provider-reported input-token count and the heuristic estimate that was current at the time of the report, so the loop can use the real count for compaction decisions and surface drift (issue #28 gap 2).
input_tokens is the value from ProviderEvent::Done.message.usage.input.
estimate_at_report is the bytes/4 estimate taken at the same moment
(i.e. the value the legacy path would have used for compaction).
Sourcepub fn current_token_source(&self) -> TokenSource
pub fn current_token_source(&self) -> TokenSource
Current best estimate of context size, tagged with its source.
Real(n)if the last completed turn reportedusage.input_tokens.Heuristic(n)only before the firstDoneis observed (cold start).Noneif there are no messages yet.
Callers (notably maybe_compact) should prefer Real and only
fall back to Heuristic on cold start. See issue #28.
Sourcepub fn replace_messages(&mut self, messages: Vec<Message>)
pub fn replace_messages(&mut self, messages: Vec<Message>)
Replace the entire message history (used after context compaction).
Sourcepub fn estimate_tokens(&self) -> usize
pub fn estimate_tokens(&self) -> usize
Rough token-count estimate based on the serialized message JSON length.
Sourcepub fn is_complete(&self) -> bool
pub fn is_complete(&self) -> bool
Returns true if the agent has signaled a stop reason.
Trait Implementations§
Source§impl Clone for AgentState
impl Clone for AgentState
Source§fn clone(&self) -> AgentState
fn clone(&self) -> AgentState
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for AgentState
impl Debug for AgentState
Source§impl Default for AgentState
impl Default for AgentState
Source§fn default() -> AgentState
fn default() -> AgentState
Source§impl<'de> Deserialize<'de> for AgentState
impl<'de> Deserialize<'de> for AgentState
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Auto Trait Implementations§
impl Freeze for AgentState
impl RefUnwindSafe for AgentState
impl Send for AgentState
impl Sync for AgentState
impl Unpin for AgentState
impl UnsafeUnpin for AgentState
impl UnwindSafe for AgentState
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
impl<T> ErasedDestructor for Twhere
T: 'static,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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 moreimpl<T> MaybeSendSync for T
Source§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.Source§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<R, P> ReadPrimitive<R> for P
impl<R, P> ReadPrimitive<R> for P
Source§fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
ReadEndian::read_from_little_endian().Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.