phi_agent/agent/builder.rs
1//! General-purpose AgentBuilder factory — provides default configuration
2//! shared across consumers.
3//!
4//! Returns a pre-configured AgentBuilder; callers then register tools and
5//! approval handlers on top.
6
7use std::sync::Arc;
8
9use agent_base::{AgentBuilder, ConsecutiveFailureRecovery, Language, ReasoningConfig, ReasoningEffort};
10
11use crate::agent::compression::SummarizingMiddleware;
12
13/// Returns an AgentBuilder with sensible defaults:
14/// - English
15/// - Medium reasoning effort
16/// - Thinking enabled
17/// - Consecutive failure recovery (default 3 retries)
18/// - Session limits (50 sessions / 100 turns per session / 50k per-message cap)
19/// - Per-run react-loop cap (200 iterations for one user input)
20/// - LLM-based context compression for long tool-heavy conversations
21///
22/// Callers are responsible for: registering tools, setting the approval
23/// handler, setting the system prompt, then calling `.build()`.
24pub fn base_agent_builder(llm_client: Arc<dyn agent_base::LlmClient>) -> AgentBuilder {
25 // Tool-output cap (default 4000 chars). Tune via PHI_MAX_TOOL_OUTPUT_CHARS for large
26 // outputs (HTML, base64 images, long lists). Truncated results carry an explicit
27 // "...(truncated)" suffix plus structured TruncationInfo from agent-base.
28 let max_tool_output_chars = match std::env::var("PHI_MAX_TOOL_OUTPUT_CHARS") {
29 Ok(value) => match value.trim().parse::<usize>() {
30 Ok(n) => n,
31 Err(_) => {
32 tracing::warn!(
33 value = %value,
34 "PHI_MAX_TOOL_OUTPUT_CHARS is not a valid integer; falling back to default 4000"
35 );
36 4000
37 }
38 },
39 Err(_) => 4000,
40 };
41
42 AgentBuilder::new(llm_client.clone())
43 .language(Language::En)
44 .reasoning(ReasoningConfig { effort: Some(ReasoningEffort::Medium), ..Default::default() })
45 .enable_thought(true)
46 .enable_thinking(true)
47 .max_sessions(50)
48 .max_turns_per_session(100)
49 .execution_max_turns(200)
50 .max_message_tokens(50_000)
51 .max_tool_output_chars(max_tool_output_chars)
52 .error_recovery(Arc::new(ConsecutiveFailureRecovery::new(3)))
53 // Summarise the earlier part of long conversations so per-call LLM context
54 // stays bounded (see compression.rs). Override via the returned builder, or
55 // build your own AgentBuilder to opt out.
56 .middleware(SummarizingMiddleware::new(llm_client))
57}