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: StringVendor 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: SystemPromptOrdered 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_kfield. - Gemini — pass-through to
generationConfig.topK. - OpenAI Chat / OpenAI Responses —
LossyEncode(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: ToolChoiceConstraint 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 atool_choiceblock is present. - OpenAI Chat / OpenAI Responses — pass-through to the
parallel_tool_callsfield. - Gemini —
LossyEncode(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):
- Anthropic —
metadata.user_id. - OpenAI Chat / OpenAI Responses — top-level
user. - Gemini, Bedrock Converse —
LossyEncode(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. - Gemini —
generationConfig.seed. - Anthropic, Bedrock Converse —
LossyEncode(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: ProviderExtensionsPer-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
impl ModelRequest
Sourcepub fn continue_turn(
self,
prior_response: &ModelResponse,
next_message: Message,
) -> Self
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:
- The model’s prior reply (
prior_response.content) is wrapped inMessage::new(Role::Assistant, ...)and pushed toself.messages. self.continued_fromis replaced withprior_response.provider_echoesso vendor-specific continuation pointers (OpenAI Responsesprevious_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.next_messageis pushed ontoself.messages. The role is free —Role::Useris the common case,Role::Toolis the canonical shape when chaining a tool-round-trip result into the next turn, and operator-driven flows that splice aRole::Systemcorrection 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
impl Clone for ModelRequest
Source§fn clone(&self) -> ModelRequest
fn clone(&self) -> ModelRequest
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 ModelRequest
impl Debug for ModelRequest
Source§impl Default for ModelRequest
impl Default for ModelRequest
Source§fn default() -> ModelRequest
fn default() -> ModelRequest
Source§impl<'de> Deserialize<'de> for ModelRequest
impl<'de> Deserialize<'de> for ModelRequest
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>,
Source§impl PartialEq for ModelRequest
impl PartialEq for ModelRequest
Source§fn eq(&self, other: &ModelRequest) -> bool
fn eq(&self, other: &ModelRequest) -> bool
self and other values to be equal, and is used by ==.