open_agent/types/agent_options.rs
1/// Configuration for model requests, tool execution, and hooks.
2///
3/// Construct validated options with [`AgentOptions::builder`]. `Default` leaves the
4/// model and base URL empty without validation. Clones share tool handlers.
5/// `max_tokens` and `temperature` remain unset unless explicitly supplied.
6#[derive(Clone)]
7pub struct AgentOptions {
8 /// System prompt that defines the agent's behavior and personality.
9 ///
10 /// This is sent as the first message in the conversation to establish
11 /// context and instructions. Can be empty if no system-level guidance
12 /// is needed.
13 system_prompt: String,
14
15 /// Model identifier for the LLM to use (e.g., "qwen2.5-32b-instruct", "gpt-4").
16 ///
17 /// This must match a model available at the configured `base_url`.
18 /// Different models have varying capabilities for tool use, context
19 /// length, and response quality.
20 model: String,
21
22 /// API endpoint URL (e.g., "http://localhost:1234/v1").
23 ///
24 /// The wire format is chosen by `protocol`: `OpenAiChat` posts to
25 /// `{base_url}/chat/completions`, which local inference servers (LM Studio,
26 /// llama.cpp, vLLM) and most cloud providers support; `Anthropic` posts to
27 /// `{base_url}/messages`.
28 base_url: String,
29
30 /// API authentication key for the provider.
31 ///
32 /// Many local servers don't require authentication, so the default
33 /// "not-needed" is often sufficient. For cloud providers like OpenAI,
34 /// set this to your actual API key.
35 api_key: String,
36
37 /// Caller-supplied HTTP headers applied to every model request.
38 ///
39 /// These may override the protocol defaults, including authentication and content type.
40 /// Header names are matched case-insensitively when the builder replaces an earlier value.
41 headers: BTreeMap<String, String>,
42
43 /// Retained compatibility setting, stored but not enforced by the SDK.
44 ///
45 /// Use `max_tool_iterations` to limit automatic tool rounds. Applications must
46 /// limit conversation turns themselves.
47 max_turns: u32,
48
49 /// Maximum tokens the model should generate in a single response.
50 ///
51 /// `None` uses the provider's default. Lower values constrain response
52 /// length, which can be useful for cost control or ensuring concise answers.
53 /// Note this is separate from the model's context window size.
54 max_tokens: Option<u32>,
55
56 /// Optional sampling temperature. `None` omits the field and lets the server choose.
57 ///
58 /// The builder accepts 0.0 through 2.0; a provider may accept a narrower range or
59 /// reject the parameter entirely.
60 temperature: Option<f32>,
61
62 /// HTTP request timeout in seconds.
63 ///
64 /// Maximum time to wait for the API to respond. Applies per API call,
65 /// not to the entire conversation. Increase for slower models or when
66 /// expecting long responses.
67 timeout: u64,
68
69 /// Tools available for the agent to use during conversations.
70 ///
71 /// Tools are wrapped in `Arc` for efficient cloning. When the agent
72 /// receives a tool use request, it looks up the tool by name in this
73 /// vector. Empty by default.
74 tools: Vec<Arc<Tool>>,
75
76 /// Whether the SDK executes tool calls and continues until a text response or
77 /// the configured iteration limit. Defaults to manual execution.
78 auto_execute_tools: bool,
79
80 /// Maximum automatic tool rounds. One round may contain several tool calls.
81 max_tool_iterations: u32,
82
83 /// Whether reasoning is emitted separately from content; defaults to false.
84 ///
85 /// Reasoning never enters assistant text or conversation history.
86 include_reasoning: bool,
87
88 /// The wire protocol this endpoint speaks.
89 ///
90 /// Selects the request path, the auth header, the body shape and the streaming
91 /// vocabulary. Defaults to [`ApiProtocol::OpenAiChat`], which is what every endpoint the
92 /// SDK supported before 0.9.0 speaks, so an existing configuration keeps its behaviour.
93 protocol: ApiProtocol,
94
95 /// Hooks for prompt submission and automatic pre/post-tool execution.
96 hooks: Hooks,
97}
98
99/// Omits credentials and shows tool counts instead of handlers.
100impl std::fmt::Debug for AgentOptions {
101 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102 f.debug_struct("AgentOptions")
103 .field("system_prompt", &self.system_prompt)
104 .field("model", &self.model)
105 .field("base_url", &self.base_url)
106 // Mask API key to prevent credential leakage in logs
107 .field("api_key", &"***")
108 .field("max_turns", &self.max_turns)
109 .field("max_tokens", &self.max_tokens)
110 .field("temperature", &self.temperature)
111 .field("timeout", &self.timeout)
112 // Show tool count instead of trying to debug Arc<Tool> contents
113 .field("tools", &format!("{} tools", self.tools.len()))
114 .field("auto_execute_tools", &self.auto_execute_tools)
115 .field("max_tool_iterations", &self.max_tool_iterations)
116 .field("include_reasoning", &self.include_reasoning)
117 .field("protocol", &self.protocol)
118 .field("hooks", &self.hooks)
119 .finish()
120 }
121}
122
123/// Defaults with an empty model and base URL. Use the builder for runtime validation.
124impl Default for AgentOptions {
125 fn default() -> Self {
126 Self {
127 system_prompt: String::new(),
128 model: String::new(),
129 base_url: String::new(),
130 api_key: "not-needed".to_string(),
131 headers: BTreeMap::new(),
132 max_turns: 1,
133 max_tokens: None,
134 temperature: None,
135 timeout: 60,
136 tools: Vec::new(),
137 auto_execute_tools: false,
138 max_tool_iterations: 5,
139 hooks: Hooks::new(),
140 include_reasoning: false,
141 protocol: ApiProtocol::OpenAiChat,
142 }
143 }
144}
145
146impl AgentOptions {
147 /// Creates a builder that requires a model and base URL.
148 ///
149 /// See [`AgentOptionsBuilder`] for an example.
150 pub fn builder() -> AgentOptionsBuilder {
151 AgentOptionsBuilder::default()
152 }
153
154 /// Returns the system prompt.
155 pub fn system_prompt(&self) -> &str {
156 &self.system_prompt
157 }
158
159 /// Returns the model identifier.
160 pub fn model(&self) -> &str {
161 &self.model
162 }
163
164 /// Returns the base URL.
165 pub fn base_url(&self) -> &str {
166 &self.base_url
167 }
168
169 /// Returns the API key.
170 pub fn api_key(&self) -> &str {
171 &self.api_key
172 }
173
174 /// Returns the caller-supplied HTTP headers.
175 pub fn headers(&self) -> &BTreeMap<String, String> {
176 &self.headers
177 }
178
179 /// Returns the retained `max_turns` compatibility value.
180 ///
181 /// The SDK does not enforce it. Use [`max_tool_iterations`](Self::max_tool_iterations)
182 /// for automatic tool rounds and enforce conversation limits in your application.
183 pub fn max_turns(&self) -> u32 {
184 self.max_turns
185 }
186
187 /// Returns the maximum tokens setting.
188 pub fn max_tokens(&self) -> Option<u32> {
189 self.max_tokens
190 }
191
192 /// Returns the sampling temperature, or `None` when the server should choose.
193 pub fn temperature(&self) -> Option<f32> {
194 self.temperature
195 }
196
197 /// Returns the wire protocol this endpoint speaks.
198 pub fn protocol(&self) -> ApiProtocol {
199 self.protocol
200 }
201
202 /// Returns the HTTP timeout in seconds.
203 pub fn timeout(&self) -> u64 {
204 self.timeout
205 }
206
207 /// Returns a reference to the tools vector.
208 pub fn tools(&self) -> &[Arc<Tool>] {
209 &self.tools
210 }
211
212 /// Returns whether automatic tool execution is enabled.
213 pub fn auto_execute_tools(&self) -> bool {
214 self.auto_execute_tools
215 }
216
217 /// Returns the maximum tool execution iterations.
218 pub fn max_tool_iterations(&self) -> u32 {
219 self.max_tool_iterations
220 }
221
222 /// Returns a reference to the hooks configuration.
223 pub fn hooks(&self) -> &Hooks {
224 &self.hooks
225 }
226
227 /// Returns whether the reasoning channel is surfaced to the caller.
228 pub fn include_reasoning(&self) -> bool {
229 self.include_reasoning
230 }
231}