molo_agent/agent/config.rs
1//! Agent construction configuration: an aggregate of optional behaviors.
2//!
3//! Required dependencies (Provider / ToolRegistry / system_prompt) go
4//! through constructor parameters, while optional behaviors go through
5//! [`AgentConfig`] — the same pattern as
6//! [`ModelOptions`](crate::provider::ModelOptions): all fields optional +
7//! `Default`.
8
9use crate::provider::ModelOptions;
10use serde::{Deserialize, Serialize};
11
12/// Optional behavior configuration for an Agent.
13///
14/// Kept separate from the required parameters (Provider / ToolRegistry /
15/// system_prompt): the required ones define what the Agent is made of, while
16/// the optional ones are behavioral parameters for how it runs.
17///
18/// # Examples
19///
20/// Adjust the tool-round limit and model parameters (temperature, etc.):
21///
22/// ```
23/// # extern crate molo_agent as molo;
24/// use molo::agent::{AgentConfig, ReActAgent};
25/// use molo::provider::{FakeProvider, FakeReply, ModelOptions};
26/// use molo::tool::ToolRegistry;
27///
28/// let config = AgentConfig::default()
29/// .with_max_tool_rounds(20)
30/// .with_max_structured_retries(5)
31/// .with_options(ModelOptions {
32/// temperature: Some(0.2),
33/// ..Default::default()
34/// });
35///
36/// let agent = ReActAgent::new(
37/// FakeProvider::new([FakeReply::Text("Hello".into())]),
38/// ToolRegistry::new(),
39/// "",
40/// )
41/// .with_config(config);
42/// ```
43#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
44#[serde(default)]
45#[non_exhaustive]
46pub struct AgentConfig {
47 /// Maximum number of rounds in which the model requests tools; if it
48 /// still hasn't answered directly when this is reached, the run fails
49 /// ([`AgentError::TooManyToolRounds`](crate::agent::AgentError)).
50 /// Prevents the model from getting stuck requesting tools in a loop.
51 /// Default: 10.
52 pub(crate) max_tool_rounds: usize,
53 /// Maximum number of retries after structured output validation fails;
54 /// if it still fails when this is reached, the run fails
55 /// ([`AgentError::StructuredRetriesExhausted`](crate::agent::AgentError)).
56 /// Counted **independently** of the tool-round limit (each failure mode
57 /// has its own clear error semantics). Default: 3.
58 pub(crate) max_structured_retries: usize,
59 /// Model parameters carried on every round of conversation (temperature /
60 /// max_tokens / extra parameters);
61 /// `Default` = all empty, using the vendor defaults.
62 pub(crate) options: ModelOptions,
63}
64
65impl Default for AgentConfig {
66 fn default() -> Self {
67 Self {
68 max_tool_rounds: 10,
69 max_structured_retries: 3,
70 options: ModelOptions::default(),
71 }
72 }
73}
74
75impl AgentConfig {
76 /// Constructs a config with default values.
77 pub fn new() -> Self {
78 Self::default()
79 }
80
81 /// Maximum tool-call rounds before a run fails.
82 pub fn max_tool_rounds(&self) -> usize {
83 self.max_tool_rounds
84 }
85
86 /// Returns a config with an updated tool-round limit.
87 pub fn with_max_tool_rounds(mut self, max_tool_rounds: usize) -> Self {
88 self.max_tool_rounds = max_tool_rounds;
89 self
90 }
91
92 /// Maximum structured-output validation retries before a run fails.
93 pub fn max_structured_retries(&self) -> usize {
94 self.max_structured_retries
95 }
96
97 /// Returns a config with an updated structured-output retry limit.
98 pub fn with_max_structured_retries(mut self, max_structured_retries: usize) -> Self {
99 self.max_structured_retries = max_structured_retries;
100 self
101 }
102
103 /// Model options sent on each provider request unless a run overrides them.
104 pub fn options(&self) -> &ModelOptions {
105 &self.options
106 }
107
108 /// Returns a config with updated model options.
109 pub fn with_options(mut self, options: ModelOptions) -> Self {
110 self.options = options;
111 self
112 }
113}