pub struct UtilityScorer { /* private fields */ }Expand description
Computes utility scores for tool calls before dispatch.
Not Send + Sync — lives on the agent’s single-threaded tool loop (same lifecycle as
ToolResultCache and recent_tool_calls).
Implementations§
Source§impl UtilityScorer
impl UtilityScorer
Sourcepub fn new(config: UtilityScoringConfig) -> Self
pub fn new(config: UtilityScoringConfig) -> Self
Create a new scorer from the given config.
Sourcepub fn is_enabled(&self) -> bool
pub fn is_enabled(&self) -> bool
Whether utility scoring is enabled.
Sourcepub fn score(
&self,
call: &ToolCall,
ctx: &UtilityContext,
) -> Option<UtilityScore>
pub fn score( &self, call: &ToolCall, ctx: &UtilityContext, ) -> Option<UtilityScore>
Score a candidate tool call.
Returns None when scoring is disabled. When scoring produces a non-finite
result (misconfigured weights), returns None — the caller treats None as
fail-closed (skip the tool call) unless user_requested is set.
Sourcepub fn recommend_action(
&self,
score: Option<&UtilityScore>,
ctx: &UtilityContext,
) -> UtilityAction
pub fn recommend_action( &self, score: Option<&UtilityScore>, ctx: &UtilityContext, ) -> UtilityAction
Recommend an action based on the utility score and turn context.
Decision tree (thresholds from arXiv:2603.19896):
user_requested→ alwaysToolCall(bypass policy).- Scoring disabled → always
ToolCall. mandated_retry→ alwaysToolCall— this is the retry theRetrieverule (8) itself demanded via the injected hint; the gate must honor its own contract instead of re-vetoing compliance as a redundant duplicate (#5719).scoreisNone(invalid score, scoring enabled) →Stop(fail-closed).cost > 0.9(budget nearly exhausted) →Stop.redundancy == 1.0(duplicate call) →Respond.gain >= 0.7 && total >= threshold→ToolCall.gain >= 0.5 && uncertainty > 0.5→Retrieve.total < threshold && tool_calls_this_turn > 0→Verify.total >= threshold→ToolCall.- Default →
Respond.
Sourcepub fn record_call(&mut self, call: &ToolCall)
pub fn record_call(&mut self, call: &ToolCall)
Record a call as executed for redundancy tracking.
Must be called after score() and before the next call to score() for the
same tool in the same turn.
Sourcepub fn mark_mandated_retry(&mut self, call: &ToolCall)
pub fn mark_mandated_retry(&mut self, call: &ToolCall)
Marks call as an in-flight mandated retry after the Retrieve rule instructs the LLM
to call it again with the same arguments (#5719).
Called by the tool loop when it injects the “you MUST call it again” hint. The next
occurrence of the identical call this turn bypasses the redundancy veto — see
take_mandated_retry.
Sourcepub fn take_mandated_retry(&mut self, call: &ToolCall) -> bool
pub fn take_mandated_retry(&mut self, call: &ToolCall) -> bool
Returns true and consumes the pending mandated-retry marker for call, if any.
Consuming rather than merely peeking ensures the bypass applies exactly once per
Retrieve veto: a genuine third identical call afterward is scored normally instead of
being exempted forever.
Sourcepub fn note_action(&mut self, action: &UtilityAction) -> bool
pub fn note_action(&mut self, action: &UtilityAction) -> bool
Record the recommended action and check whether the consecutive-low-utility window is exhausted.
Returns true when config.utility_window > 0 and consecutive_low >= utility_window,
indicating that the current batch should be downgraded and the caller should signal
a hard break of the outer iteration loop. Always returns false when
utility_window == 0 (disabled) so existing behaviour is fully preserved.
Must be called only for calls that actually went through recommend_action — exempt and
pre-exec-blocked calls bypass scoring and must NOT call this method.
Sourcepub fn is_exempt(&self, tool_name: &str) -> bool
pub fn is_exempt(&self, tool_name: &str) -> bool
Returns true when tool_name is in the exempt list (case-insensitive).
Exempt tools bypass the utility gate unconditionally and always receive ToolCall.
Sourcepub fn is_high_gain(&self, tool_name: &str) -> bool
pub fn is_high_gain(&self, tool_name: &str) -> bool
Returns true when tool_name is in the high_gain_tools opt-in list (case-insensitive).
Tools in this list receive the same 0.75 “direct action” gain as
diagnostics/edit/etc, regardless of whether default_gain has a hardcoded entry
for them. Intended for MCP-registered tools whose ids default_gain can never match
(#5659).
Sourcepub fn utility_window(&self) -> usize
pub fn utility_window(&self) -> usize
The configured consecutive-low-utility window size. 0 means disabled.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for UtilityScorer
impl RefUnwindSafe for UtilityScorer
impl Send for UtilityScorer
impl Sync for UtilityScorer
impl Unpin for UtilityScorer
impl UnsafeUnpin for UtilityScorer
impl UnwindSafe for UtilityScorer
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
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 moreSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request