Skip to main content

rskit_agent/
config.rs

1//! Agent runtime configuration.
2
3use std::sync::Arc;
4use std::time::Duration;
5
6use rskit_hook::HookRegistry;
7use rskit_resilience::Policy;
8use rskit_tool::Registry;
9
10use crate::types::ContextStrategy;
11
12/// Configuration for an [`crate::Agent`].
13pub struct AgentConfig {
14    /// Optional tool registry.
15    pub tools: Option<Arc<Registry>>,
16    /// Optional hook registry for lifecycle events.
17    pub hooks: Option<Arc<HookRegistry>>,
18    /// System prompt prepended to every completion request.
19    pub system_prompt: String,
20    /// Maximum number of turns before the agent stops.
21    pub max_turns: u32,
22    /// Maximum cumulative token budget (input + output) across all turns.
23    pub max_tokens: usize,
24    /// Maximum wall-clock time for a run.
25    pub wall_clock: Duration,
26    /// Maximum logical tool calls. Retries count as one logical call.
27    pub max_tool_calls: u32,
28    /// Maximum concurrently scheduled tool calls.
29    pub tool_concurrency: usize,
30    /// Per-tool call timeout.
31    pub tool_timeout: Duration,
32    /// Optional resilience policy applied to tool executions.
33    pub policy: Option<Policy>,
34    /// Strategy for compacting context when it exceeds the provider's limit.
35    pub context_strategy: Option<Box<dyn ContextStrategy>>,
36    /// Model identifier to send with each completion request.
37    pub model: String,
38}
39
40impl AgentConfig {
41    /// Return this configuration as shared `GenAI` budget vocabulary.
42    #[must_use]
43    pub fn budget(&self) -> rskit_ai::Budget {
44        rskit_ai::Budget {
45            max_tokens: Some(self.max_tokens as u64),
46            max_calls: Some(u64::from(self.max_tool_calls)),
47            max_cost: None,
48            wall_clock: Some(self.wall_clock.as_secs()),
49        }
50    }
51}
52
53impl Default for AgentConfig {
54    fn default() -> Self {
55        Self {
56            tools: None,
57            hooks: None,
58            system_prompt: String::new(),
59            max_turns: 10,
60            max_tokens: 100_000,
61            wall_clock: Duration::from_mins(1),
62            max_tool_calls: 50,
63            tool_concurrency: 4,
64            tool_timeout: Duration::from_secs(30),
65            policy: None,
66            context_strategy: None,
67            model: String::new(),
68        }
69    }
70}
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75
76    #[test]
77    fn budget_maps_config_limits_to_shared_genai_vocabulary() {
78        let config = AgentConfig {
79            max_tokens: 4_096,
80            max_tool_calls: 7,
81            wall_clock: Duration::from_secs(45),
82            ..AgentConfig::default()
83        };
84
85        let budget = config.budget();
86
87        assert_eq!(budget.max_tokens, Some(4_096));
88        assert_eq!(budget.max_calls, Some(7));
89        assert_eq!(budget.wall_clock, Some(45));
90        // Cost is not derived from the runtime config and stays unset.
91        assert_eq!(budget.max_cost, None);
92    }
93}