diff --git a/crates/arc-agent/src/config.rs b/crates/arc-agent/src/config.rs index ab9255774..64358c1f1 100644 --- a/crates/arc-agent/src/config.rs +++ b/crates/arc-agent/src/config.rs @@ -17,6 +17,9 @@ pub struct SessionConfig { pub reasoning_effort: Option, pub tool_output_limits: HashMap, pub tool_line_limits: HashMap, + /// Override the provider's default max_tokens when set. + /// Node-level attribute takes priority over the model catalog default. + pub max_tokens: Option, pub enable_loop_detection: bool, pub loop_detection_window: usize, pub max_subagent_depth: usize, @@ -45,6 +48,7 @@ impl std::fmt::Debug for SessionConfig { &self.default_command_timeout_ms, ) .field("max_command_timeout_ms", &self.max_command_timeout_ms) + .field("max_tokens", &self.max_tokens) .field("reasoning_effort", &self.reasoning_effort) .field("tool_output_limits", &self.tool_output_limits) .field("tool_line_limits", &self.tool_line_limits) @@ -73,6 +77,7 @@ impl Default for SessionConfig { max_tool_rounds_per_input: 200, default_command_timeout_ms: 10_000, max_command_timeout_ms: 600_000, + max_tokens: None, reasoning_effort: None, tool_output_limits: HashMap::new(), tool_line_limits: HashMap::new(), diff --git a/crates/arc-agent/src/session.rs b/crates/arc-agent/src/session.rs index 1de97ac8c..31a706395 100644 --- a/crates/arc-agent/src/session.rs +++ b/crates/arc-agent/src/session.rs @@ -622,8 +622,9 @@ impl Session { response_format: None, temperature: None, top_p: None, - max_tokens: arc_llm::catalog::get_model_info(self.provider_profile.model()) - .and_then(|m| m.max_output), + max_tokens: self.config.max_tokens.or_else(|| + arc_llm::catalog::get_model_info(self.provider_profile.model()) + .and_then(|m| m.max_output)), stop_sequences: None, reasoning_effort: self.config.reasoning_effort.clone(), metadata: None, diff --git a/crates/arc-llm/src/providers/anthropic.rs b/crates/arc-llm/src/providers/anthropic.rs index 77124388c..138794118 100644 --- a/crates/arc-llm/src/providers/anthropic.rs +++ b/crates/arc-llm/src/providers/anthropic.rs @@ -1066,7 +1066,7 @@ fn build_api_request( let api_request = ApiRequest { model: request.model.clone(), messages: api_messages, - max_tokens: request.max_tokens.unwrap_or(4096), + max_tokens: request.max_tokens.unwrap_or(16384), system: system_value, temperature: request.temperature, top_p: request.top_p, diff --git a/crates/arc-workflows/src/cli/backend.rs b/crates/arc-workflows/src/cli/backend.rs index 04975bdaf..b25646861 100644 --- a/crates/arc-workflows/src/cli/backend.rs +++ b/crates/arc-workflows/src/cli/backend.rs @@ -59,6 +59,7 @@ impl AgentBackend { let mut profile = self.build_profile(); let config = SessionConfig { + max_tokens: node.max_tokens(), reasoning_effort: Some(node.reasoning_effort().to_string()), ..SessionConfig::default() }; @@ -131,7 +132,8 @@ impl CodergenBackend for AgentBackend { .map(String::from) .or_else(|| Some(self.provider.as_str().to_string())); - let max_tokens = arc_llm::catalog::get_model_info(model).and_then(|m| m.max_output); + let max_tokens = node.max_tokens().or_else(|| + arc_llm::catalog::get_model_info(model).and_then(|m| m.max_output)); let request = arc_llm::types::Request { model: model.to_string(), diff --git a/crates/arc-workflows/src/graph/types.rs b/crates/arc-workflows/src/graph/types.rs index 3d440a830..d9fb8ff09 100644 --- a/crates/arc-workflows/src/graph/types.rs +++ b/crates/arc-workflows/src/graph/types.rs @@ -205,7 +205,12 @@ impl Node { self.str_attr("llm_provider") } - #[must_use] + #[must_use] + pub fn max_tokens(&self) -> Option { + self.int_attr("max_tokens").filter(|&v| v > 0) + } + + #[must_use] pub fn reasoning_effort(&self) -> &str { self.str_attr("reasoning_effort").unwrap_or("high") }