Skip to main content

ModelRequest

Struct ModelRequest 

Source
pub struct ModelRequest {
Show 17 fields pub model: String, pub messages: Vec<Message>, pub system: SystemPrompt, pub max_tokens: Option<u32>, pub temperature: Option<f32>, pub top_p: Option<f32>, pub top_k: Option<u32>, pub stop_sequences: Vec<String>, pub tools: Arc<[ToolSpec]>, pub tool_choice: ToolChoice, pub parallel_tool_calls: Option<bool>, pub response_format: Option<ResponseFormat>, pub end_user_id: Option<String>, pub seed: Option<i64>, pub reasoning_effort: Option<ReasoningEffort>, pub provider_extensions: ProviderExtensions, pub continued_from: Vec<ProviderEchoSnapshot>,
}
Expand description

One model invocation, before encoding to vendor wire format.

Built by users (or higher-level recipes) and handed to Codec::encode. Codecs produce vendor-shaped JSON; the IR is the canonical surface and never carries vendor-specific fields directly.

Fields§

§model: String

Vendor model identifier (e.g. claude-opus-4-7, gpt-4.1).

§messages: Vec<Message>

Conversation up to this turn. Must contain at least one user message for most providers; codecs reject empty lists at encode time.

§system: SystemPrompt

Ordered system-prompt blocks. Empty = “no system prompt” (codecs treat as if the field were absent). Per-block crate::ir::CacheControl is honored natively by codecs that support it (Anthropic, Bedrock Converse for Claude); other codecs concatenate block text and emit LossyEncode warnings when any block is cached.

§max_tokens: Option<u32>

Hard cap on output tokens. None = vendor default.

§temperature: Option<f32>

Sampling temperature [0.0, 2.0]. Codecs clamp to vendor range.

§top_p: Option<f32>

Nucleus sampling parameter.

§top_k: Option<u32>

Top-k sampling parameter — restrict candidate-token sampling to the k most-likely tokens. None defers to the vendor default.

Codec mapping (CLAUDE.md §“Provider IR promotion”; native on Anthropic, Gemini, Bedrock Converse on Claude — three vendors, criterion satisfied):

  • Anthropic, Bedrock Converse on Claude — pass-through to the Messages API top_k field.
  • Gemini — pass-through to generationConfig.topK.
  • OpenAI Chat / OpenAI ResponsesLossyEncode (no native parameter).
§stop_sequences: Vec<String>

Sequences that, when produced, halt generation.

§tools: Arc<[ToolSpec]>

Tools advertised to the model. Empty = no tool calls permitted. Held as Arc<[ToolSpec]> so per-dispatch cloning of the request shape is an atomic refcount bump rather than a deep walk of every tool’s JSON schema. Codecs read through the Deref<Target = [ToolSpec]> coercion — every &request.tools site continues to see &[ToolSpec] unchanged.

§tool_choice: ToolChoice

Constraint on tool selection. Defaults to ToolChoice::Auto.

§parallel_tool_calls: Option<bool>

Allow the model to emit more than one tool call in a single turn. Some(true) opts in to parallel tool use, Some(false) forces serial dispatch, None defers to the vendor default.

Codec mapping:

  • Anthropic, Bedrock Converse on Claude — translate to tool_choice.disable_parallel_tool_use (inverted polarity); the codec only emits when a tool_choice block is present.
  • OpenAI Chat / OpenAI Responses — pass-through to the parallel_tool_calls field.
  • GeminiLossyEncode (no native parallel-tool toggle).

Promoted to IR per the rule “≥ 2 first-party vendors carry the concept natively → IR field” (CLAUDE.md §“Provider IR promotion”).

§response_format: Option<ResponseFormat>

Optional structured-output constraint. Codecs route to vendor-canonical channels (Anthropic output_config.format, OpenAI response_format / text.format, Gemini responseJsonSchema).

§end_user_id: Option<String>

Pseudonymous end-user identifier — abuse-monitoring, per-user rate-limit attribution, and audit trail. Vendor pseudonym, never PII (no email / IP / real name).

Codec mapping (native on Anthropic + OpenAI Chat + OpenAI Responses — two distinct vendors, criterion satisfied):

  • Anthropicmetadata.user_id.
  • OpenAI Chat / OpenAI Responses — top-level user.
  • Gemini, Bedrock ConverseLossyEncode (no native end-user attribution channel).
§seed: Option<i64>

Deterministic-generation seed. Same seed + same request → same output, best-effort (vendors document this as not strictly guaranteed across model versions).

Codec mapping (native on OpenAI Chat + OpenAI Responses + Gemini — two distinct vendors, criterion satisfied):

  • OpenAI Chat / OpenAI Responses — top-level seed.
  • GeminigenerationConfig.seed.
  • Anthropic, Bedrock ConverseLossyEncode (no native deterministic-sampling knob).
§reasoning_effort: Option<ReasoningEffort>

Cross-vendor reasoning-effort knob. When Some, codecs translate onto their native wire shape per the mapping in ReasoningEffort’s module doc — Off/Minimal/Low/ Medium/High/Auto snap to vendor buckets, lossy approximations emit ModelWarning::LossyEncode, and VendorSpecific(s) passes through the literal vendor wire value. None ⇒ vendor default (codec emits no thinking / reasoning field).

§provider_extensions: ProviderExtensions

Per-vendor typed knobs that don’t generalise to a cross-provider IR field — e.g. Anthropic disable_parallel_tool_use, Gemini safetySettings, Bedrock guardrails. Codecs read their own ext when encoding and emit ModelWarning::ProviderExtensionIgnored when another vendor’s ext is present (the operator intended a knob this wire format cannot honour).

§continued_from: Vec<ProviderEchoSnapshot>

Vendor-keyed opaque round-trip tokens carrying state from a prior turn — OpenAI Responses previous_response_id is the canonical example. Codecs read entries matching their own Codec::name and translate to the vendor’s chain-pointer wire field; non-matching entries are ignored. Empty when the request does not chain from a prior turn.

Implementations§

Source§

impl ModelRequest

Source

pub fn continue_turn( self, prior_response: &ModelResponse, next_message: Message, ) -> Self

Advance this request to the next conversational turn — append the prior assistant turn, chain the vendor’s opaque echoes, and add the next message (whatever its role).

The transformation is:

  1. The model’s prior reply (prior_response.content) is wrapped in Message::new(Role::Assistant, ...) and pushed to self.messages.
  2. self.continued_from is replaced with prior_response.provider_echoes so vendor-specific continuation pointers (OpenAI Responses previous_response_id, Anthropic extended-thinking signatures, Gemini thought signatures) ride the next wire encoding. Codecs whose wire format represents the prior turn through a server-side chain pointer (OpenAI Responses) deduplicate the appended assistant turn against that pointer at encode time so the transcript is not double-carried.
  3. next_message is pushed onto self.messages. The role is free — Role::User is the common case, Role::Tool is the canonical shape when chaining a tool-round-trip result into the next turn, and operator-driven flows that splice a Role::System correction message are also valid.

Model / system prompt / tools / response format / sampling knobs survive unchanged. Callers needing per-turn adjustments chain further builder methods on the returned value.

§Tool round-trip

Role::Tool results for pending ToolUse blocks in prior_response.content are passed in via next_message — either directly (single tool round-trip) or by composing additional pushes on the returned request before the next dispatch (multi-tool fan-out). The helper does not auto-synthesise tool results; agent loops dispatch tools and produce the matching Message::Tool themselves.

§Why a self-consuming method

ModelRequest is cheap to clone but the chain shape is fundamentally “previous turn → next turn”; consuming self makes accidental mutation of the old request impossible and reads naturally at the call site:

let next = prior_request.continue_turn(&prior_response, Message::user("more"));

Trait Implementations§

Source§

impl Clone for ModelRequest

Source§

fn clone(&self) -> ModelRequest

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 ModelRequest

Source§

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

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

impl Default for ModelRequest

Source§

fn default() -> ModelRequest

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for ModelRequest

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 ModelRequest

Source§

fn eq(&self, other: &ModelRequest) -> 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 ModelRequest

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 ModelRequest

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

Source§

type Output = T

Should always be Self
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
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,