oxi_agent/agent_loop/config.rs
1//! Agent loop configuration types
2
3/// Configuration for an [`crate::AgentLoop`] instance.
4#[derive(Clone)]
5pub struct AgentLoopConfig {
6 /// Model identifier in `provider/model` format.
7 pub model_id: String,
8 /// Optional system prompt prepended to every request.
9 pub system_prompt: Option<String>,
10 /// Sampling temperature (0.0 – 2.0).
11 pub temperature: f32,
12 /// Maximum tokens the model may generate per request.
13 pub max_tokens: u32,
14 /// Whether tool calls run in parallel or sequentially.
15 pub tool_execution: ToolExecutionMode,
16 /// Compaction strategy for managing context window usage.
17 pub compaction_strategy: oxi_ai::CompactionStrategy,
18 /// Approximate context window size in tokens.
19 pub context_window: usize,
20 /// Optional instruction injected into the compaction prompt.
21 pub compaction_instruction: Option<String>,
22 /// Optional session identifier for logging and tracing.
23 pub session_id: Option<String>,
24 /// Optional transport override (e.g. "sse", "stdio").
25 pub transport: Option<String>,
26 /// Whether to trigger compaction before the first turn.
27 pub compact_on_start: bool,
28 /// Optional cap on retry back-off delay (milliseconds).
29 pub max_retry_delay_ms: Option<u64>,
30 /// Enable automatic retry on retryable assistant errors.
31 pub auto_retry_enabled: bool,
32 /// Maximum number of auto-retry attempts.
33 pub auto_retry_max_attempts: usize,
34 /// Base delay in milliseconds for auto-retry exponential back-off.
35 pub auto_retry_base_delay_ms: u64,
36 /// API key override for the provider.
37 ///
38 /// When set, this is injected into [`oxi_ai::StreamOptions`] so the
39 /// provider uses it instead of an environment variable.
40 pub api_key: Option<String>,
41 /// Working directory for file tools. Defaults to current directory if None.
42 pub workspace_dir: Option<std::path::PathBuf>,
43 /// Per-provider options for fine-grained control.
44 ///
45 /// Passed through to [`oxi_ai::StreamOptions::provider_options`] so the
46 /// provider can read provider-specific settings.
47 pub provider_options: Option<oxi_ai::ProviderOptions>,
48
49 /// Async hook invoked after context compaction completes.
50 ///
51 /// Unlike the `Compaction` event in the `Fn` callback, this hook is
52 /// async and its future is awaited within the agent loop. Errors are
53 /// logged at WARN level but don't fail the loop.
54 ///
55 /// Use this for side effects that require async I/O (e.g., persisting
56 /// compaction summaries to a memory store) without resorting to
57 /// `tokio::spawn` fire-and-forget.
58 pub on_compaction: Option<CompactionHook>,
59 /// Snapshot store for hashline edit mode.
60 pub snapshot_store: Option<Arc<dyn oxi_hashline::SnapshotStore>>,
61 /// Memory backend for memory tools.
62 pub memory: Option<Arc<dyn crate::tools::MemoryBackend>>,
63 /// URL resolver for internal protocol schemes.
64 pub url_resolver: Option<Arc<dyn crate::tools::UrlResolver>>,
65 /// Todo state provider for the `todo` tool.
66 pub todo: Option<Arc<dyn crate::tools::TodoStateProvider>>,
67 /// Agent pool for Hub display.
68 pub agent_pool: Option<Arc<dyn crate::tools::AgentPoolProvider>>,
69 /// LSP provider for the `lsp` tool.
70 pub lsp: Option<Arc<dyn crate::tools::LspProvider>>,
71 /// TTSR engine for stream rule checking.
72 pub ttsr_engine: Option<Arc<crate::agent_loop::ttsr::TtsrEngine>>,
73}
74
75impl Default for AgentLoopConfig {
76 fn default() -> Self {
77 Self {
78 model_id: String::new(),
79 system_prompt: None,
80 temperature: 0.7,
81 max_tokens: 4096,
82 tool_execution: ToolExecutionMode::Parallel,
83 compaction_strategy: oxi_ai::CompactionStrategy::default(),
84 context_window: 128_000,
85 compaction_instruction: None,
86 session_id: None,
87 transport: None,
88 compact_on_start: false,
89 max_retry_delay_ms: None,
90 auto_retry_enabled: false,
91 auto_retry_max_attempts: 3,
92 auto_retry_base_delay_ms: 2000,
93 api_key: None,
94 workspace_dir: None,
95 provider_options: None,
96 on_compaction: None,
97 snapshot_store: None,
98 memory: None,
99 url_resolver: None,
100 todo: None,
101 agent_pool: None,
102 lsp: None,
103 ttsr_engine: None,
104 }
105 }
106}
107
108// Re-export ToolExecutionMode from crate::config to avoid duplicate definitions.
109pub use crate::config::ToolExecutionMode;
110
111use crate::AgentToolResult;
112use crate::compaction::CompactedContext;
113use anyhow::{Error, Result};
114use serde_json::Value;
115use std::future::Future;
116use std::pin::Pin;
117use std::sync::Arc;
118
119/// Async hook invoked after context compaction completes.
120///
121/// Receives the [`CompactedContext`] and returns a `Result<()>` future.
122/// The future is awaited within the agent loop, so async operations
123/// (memory storage, logging, etc.) are safe here.
124///
125/// # Example
126///
127/// ```ignore
128/// let config = AgentLoopConfig {
129/// on_compaction: Some(Arc::new(|ctx: CompactedContext| {
130/// let summary = ctx.summary.clone();
131/// Box::pin(async move {
132/// memory_store.save(summary).await
133/// })
134/// })),
135/// ..Default::default()
136/// };
137/// ```
138pub type CompactionHook =
139 Arc<dyn Fn(CompactedContext) -> Pin<Box<dyn Future<Output = Result<()>> + Send>> + Send + Sync>;
140
141/// Hook invoked before each tool call; may return an override result.
142pub type BeforeToolCallHook = Arc<
143 dyn Fn(
144 &str,
145 &Value,
146 ) -> Pin<Box<dyn Future<Output = Result<Option<AgentToolResult>, Error>> + Send>>
147 + Send
148 + Sync,
149>;
150
151/// Hook invoked after each tool call; may return a modified result.
152pub type AfterToolCallHook = Arc<
153 dyn Fn(
154 &str,
155 &AgentToolResult,
156 ) -> Pin<Box<dyn Future<Output = Result<Option<AgentToolResult>, Error>> + Send>>
157 + Send
158 + Sync,
159>;
160
161// MAX_RETRIES and BACKOFF_BASE_SECS are now defined in crate::stream_retry
162// and re-exported from crate::agent_loop::retry.
163pub use crate::stream_retry::{BACKOFF_BASE_SECS, MAX_RETRIES};