pub enum FinishReason {
Stop,
Length,
ToolCalls,
ContentFilter,
Other(String),
}Expand description
Why the model stopped generating, normalized across providers.
Providers report this under different names and vocabularies
(finish_reason, stop_reason, stopReason, …). Each provider’s response
conversion maps its wire value onto these variants and preserves anything
unmapped verbatim in FinishReason::Other, so a provider adding a new
terminal reason never silently reads as a natural stop. Closes #2090/#1886.
Provider failure statuses that arrive with parseable output (a Gemini
Interactions failed/cancelled interaction, a Cohere ERROR) follow one
policy: the response converts normally and the status is preserved verbatim
as FinishReason::Other, leaving the caller to decide whether a
failure-flagged-but-parseable turn is usable. Statuses that arrive with no
usable output surface as errors instead.
Variants§
Stop
Natural end of the response.
Length
The response hit the output-token limit.
ToolCalls
The model stopped to call one or more tools.
ContentFilter
The provider filtered the content.
Other(String)
A provider-specific reason outside the normalized vocabulary, carried verbatim in the provider’s own wire spelling.
Implementations§
Source§impl FinishReason
impl FinishReason
Sourcepub fn reconcile_with_output(self, has_tool_call: bool) -> FinishReason
pub fn reconcile_with_output(self, has_tool_call: bool) -> FinishReason
Reconcile a provider’s reported reason with what the turn actually produced.
Several providers report a plain stop on a turn that carried tool
calls (OpenAI-compatible gateways are the usual offenders). A caller
branching on FinishReason::ToolCalls to decide whether to run tools
would then miss the call entirely, so a natural stop is upgraded
whenever the turn emitted at least one tool call.
Only FinishReason::Stop is upgraded: Length, ContentFilter, and
Other describe terminations that remain true regardless of the
content, and overriding them would lose information.
This is the single place the upgrade happens. Construct normalized
responses through CompletionResponse::with_finish_reason or
CompletionResponse::with_optional_finish_reason (and, for streams,
crate::streaming::normalize_stream) so it is always applied.
Sourcepub fn truncated_output(&self) -> bool
pub fn truncated_output(&self) -> bool
Whether the provider cut the turn short instead of letting the model finish.
A turn that ended this way can legitimately carry no content at all — an output-token cap consumed entirely by hidden reasoning tokens, or a filter that removed everything the model produced — and the reason is then the only diagnostic the caller has. Normalization keeps such an empty turn rather than rejecting it as a malformed response, so a caller can tell “you hit the cap” from “the provider misbehaved”.
Stop and ToolCalls describe turns
that ran to completion, so an empty one really is a provider defect;
Other is unclassified and gets the strict treatment —
it carries a provider’s own wire spelling with no normalized meaning.
This is also the set rig-agent has a remedy for when a turn arrives
without an answer (“raise max_tokens” / “the provider filtered the
response”), and that is the same question: the reasons a provider may
hand back an answerless turn are the reasons there is something useful
to say about it. Both sides read this predicate so they cannot drift.
Trait Implementations§
Source§impl Clone for FinishReason
impl Clone for FinishReason
Source§fn clone(&self) -> FinishReason
fn clone(&self) -> FinishReason
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 FinishReason
impl Debug for FinishReason
Source§impl<'de> Deserialize<'de> for FinishReason
impl<'de> Deserialize<'de> for FinishReason
Source§fn deserialize<__D>(
__deserializer: __D,
) -> Result<FinishReason, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(
__deserializer: __D,
) -> Result<FinishReason, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
impl Eq for FinishReason
Source§impl PartialEq for FinishReason
impl PartialEq for FinishReason
Source§impl Serialize for FinishReason
impl Serialize for FinishReason
Source§fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
impl StructuralPartialEq for FinishReason
Auto Trait Implementations§
impl Freeze for FinishReason
impl RefUnwindSafe for FinishReason
impl Send for FinishReason
impl Sync for FinishReason
impl Unpin for FinishReason
impl UnsafeUnpin for FinishReason
impl UnwindSafe for FinishReason
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> CloneDebuggableStorage for Twhere
T: DebuggableStorage + Clone,
impl<T> CloneDebuggableStorage for Twhere
T: DebuggableStorage + Clone,
fn clone_storage(&self) -> Box<dyn CloneDebuggableStorage>
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> CloneableStorage for T
impl<T> CloneableStorage for T
fn clone_storage(&self) -> Box<dyn CloneableStorage>
impl<T> DebuggableStorage for T
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.