Skip to main content

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}