Bump Anthropic max_tokens default and add per-node max_tokens override

Raise the Anthropic adapter fallback from 4096 to 16384 to prevent
truncation of large tool call JSON when the model isn't in the catalog.

Add max_tokens as a configurable DOT node attribute that flows through
SessionConfig to LLM requests, following the same pattern as
reasoning_effort. Priority: node attribute > catalog > provider default.

Ported from kilroy (danshapiro/kilroy) commits 99a5cd7 and 78fadad.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Bryan Helmkamp 2026-03-01 12:54:23 -05:00
parent a338f8a064
commit 1e07fc0b09
5 changed files with 18 additions and 5 deletions

View file

@ -17,6 +17,9 @@ pub struct SessionConfig {
pub reasoning_effort: Option<String>,
pub tool_output_limits: HashMap<String, usize>,
pub tool_line_limits: HashMap<String, usize>,
/// Override the provider's default max_tokens when set.
/// Node-level attribute takes priority over the model catalog default.
pub max_tokens: Option<i64>,
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(),

View file

@ -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,

View file

@ -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,

View file

@ -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(),

View file

@ -205,7 +205,12 @@ impl Node {
self.str_attr("llm_provider")
}
#[must_use]
#[must_use]
pub fn max_tokens(&self) -> Option<i64> {
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")
}