From c13aa86a74062b23c6989ae947f0f7788b6c7f94 Mon Sep 17 00:00:00 2001 From: Douwe Osinga Date: Wed, 19 Aug 2026 23:23:18 +0000 Subject: [PATCH] Disable thinking for tool call labels (#11207) --- Cargo.lock | 4 +- .../platform_extensions/orchestrator.rs | 1 + crates/goose/src/model_config.rs | 9 ++-- crates/goose/src/session/session_naming.rs | 1 + crates/goose/src/tool_call_labels.rs | 54 +++++++++++++------ deny.toml | 6 --- 6 files changed, 48 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3af3f96e6..a5af73bc6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5370,9 +5370,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.15" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155" +checksum = "a9f37a958b41b3b19ee2707c06439c0e9e547e847223eb791ecb0cb821c65e27" dependencies = [ "atomic-waker", "bytes", diff --git a/crates/goose/src/agents/platform_extensions/orchestrator.rs b/crates/goose/src/agents/platform_extensions/orchestrator.rs index b8e0852d0..52b41497d 100644 --- a/crates/goose/src/agents/platform_extensions/orchestrator.rs +++ b/crates/goose/src/agents/platform_extensions/orchestrator.rs @@ -362,6 +362,7 @@ impl OrchestratorClient { system, &[user_message], &[], + true, ) .await .map_err(|e| format!("LLM summarization failed: {}", e))?; diff --git a/crates/goose/src/model_config.rs b/crates/goose/src/model_config.rs index 5e66972d1..ea167bb87 100644 --- a/crates/goose/src/model_config.rs +++ b/crates/goose/src/model_config.rs @@ -122,8 +122,7 @@ fn one_shot_model_config(model_config: ModelConfig) -> ModelConfig { } /// Run a completion for a lightweight "fast" task (session naming, tool-call -/// labels, orchestrator routing) using the provider's fast model, falling back -/// to the supplied main `model_config` if the fast model errors. +/// labels, orchestrator routing) using the provider's fast model. pub async fn complete_fast( provider: &dyn Provider, model_config: &ModelConfig, @@ -131,6 +130,7 @@ pub async fn complete_fast( system: &str, messages: &[Message], tools: &[Tool], + fallback_to_main_model: bool, ) -> Result<(Message, ProviderUsage), ProviderError> { let fast_model_config = one_shot_model_config( get_fast_model(provider.get_name(), model_config) @@ -145,7 +145,10 @@ pub async fn complete_fast( .await { Ok(response) => Ok(response), - Err(e) if fast_model_config.model_name != model_config.model_name => { + Err(e) + if fallback_to_main_model + && fast_model_config.model_name != model_config.model_name => + { tracing::warn!( "Fast model {} failed with error: {}. Falling back to main model {}", fast_model_config.model_name, diff --git a/crates/goose/src/session/session_naming.rs b/crates/goose/src/session/session_naming.rs index 4e0f34d3e..192667165 100644 --- a/crates/goose/src/session/session_naming.rs +++ b/crates/goose/src/session/session_naming.rs @@ -158,6 +158,7 @@ pub(crate) async fn generate_session_name( &system, &[message], &[], + true, ) .await? }; diff --git a/crates/goose/src/tool_call_labels.rs b/crates/goose/src/tool_call_labels.rs index 9dd07f835..e878b9f4e 100644 --- a/crates/goose/src/tool_call_labels.rs +++ b/crates/goose/src/tool_call_labels.rs @@ -3,10 +3,8 @@ use crate::conversation::message::{ Message, MessageContent, ToolChainSummary, ToolRequest, TOOL_META_CHAIN_SUMMARY_KEY, TOOL_META_TITLE_KEY, }; -use crate::model_config::get_fast_model; use crate::providers::base::Provider; use crate::session::SessionManager; -use crate::session_context::with_session_id; use crate::utils::safe_truncate; use goose_providers::model::ModelConfig; use serde_json::json; @@ -41,13 +39,9 @@ pub(crate) async fn generate_tool_title( } let model_config = agent.model_config_for_session(session_id).await.ok()?; - let fast_model_config = get_fast_model(provider.get_name(), &model_config) - .await - .ok()? - .with_prompt_cache_disabled(); let title = generate_tool_title_with_provider( provider.as_ref(), - &fast_model_config, + &model_config, session_id, tool_request, ) @@ -84,14 +78,10 @@ pub(crate) async fn generate_tool_chain_summary( } let model_config = agent.model_config_for_session(session_id).await.ok()?; - let fast_model_config = get_fast_model(provider.get_name(), &model_config) - .await - .ok()? - .with_prompt_cache_disabled(); let chain_summary = ToolChainSummary { summary: generate_tool_chain_summary_with_provider( provider.as_ref(), - &fast_model_config, + &model_config, session_id, &steps, ) @@ -204,9 +194,14 @@ async fn complete_label( message: &Message, ) -> Option { for attempt in 0..LABEL_GENERATION_MAX_ATTEMPTS { - if let Ok((response, _)) = with_session_id( - Some(session_id.to_string()), - provider.complete(model_config, system_prompt, from_ref(message), &[]), + if let Ok((response, _)) = crate::model_config::complete_fast( + provider, + model_config, + session_id, + system_prompt, + from_ref(message), + &[], + false, ) .await { @@ -251,6 +246,7 @@ mod tests { outcomes: Mutex>>, calls: AtomicUsize, messages: Mutex>>, + model_configs: Mutex>, manages_own_context: bool, } @@ -260,6 +256,7 @@ mod tests { outcomes: Mutex::new(outcomes.into()), calls: AtomicUsize::new(0), messages: Mutex::new(Vec::new()), + model_configs: Mutex::new(Vec::new()), manages_own_context: false, } } @@ -269,6 +266,7 @@ mod tests { outcomes: Mutex::new(VecDeque::new()), calls: AtomicUsize::new(0), messages: Mutex::new(Vec::new()), + model_configs: Mutex::new(Vec::new()), manages_own_context: true, } } @@ -280,6 +278,10 @@ mod tests { fn first_user_message(&self) -> String { self.messages.lock().unwrap()[0][0].as_concat_text() } + + fn first_model_config(&self) -> ModelConfig { + self.model_configs.lock().unwrap()[0].clone() + } } #[async_trait] @@ -300,13 +302,17 @@ mod tests { async fn complete( &self, - _model_config: &ModelConfig, + model_config: &ModelConfig, _system: &str, messages: &[Message], _tools: &[Tool], ) -> Result<(Message, ProviderUsage), ProviderError> { self.calls.fetch_add(1, Ordering::SeqCst); self.messages.lock().unwrap().push(messages.to_vec()); + self.model_configs + .lock() + .unwrap() + .push(model_config.clone()); let outcome = self .outcomes .lock() @@ -412,6 +418,22 @@ mod tests { assert_eq!(provider.call_count(), 1); } + #[tokio::test] + async fn disables_thinking_for_title_generation() { + let provider = MockProvider::new(vec![Ok(Message::assistant().with_text("title"))]); + let request = tool_request(json!({})); + let model_config = ModelConfig::new("test-model") + .with_thinking_effort(goose_providers::thinking::ThinkingEffort::High); + + generate_tool_title_with_provider(&provider, &model_config, "session-1", &request) + .await; + + assert_eq!( + provider.first_model_config().thinking_effort(), + Some(goose_providers::thinking::ThinkingEffort::Off), + ); + } + #[tokio::test] async fn retries_once_after_empty_response() { let provider = MockProvider::new(vec![ diff --git a/deny.toml b/deny.toml index d4dff0d09..b1cfce4a2 100644 --- a/deny.toml +++ b/deny.toml @@ -10,10 +10,4 @@ ignore = [ # rsa: Marvin Attack timing sidechannel. No safe upgrade is available, and # the reachable path is through jsonwebtoken. "RUSTSEC-2023-0071", - - # quick-xml: duplicate-attribute and namespace-declaration allocation issues. - # Current paths are through docx-rs, umya-spreadsheet, and bat/plist, and their - # latest releases do not yet expose a quick-xml >= 0.41.0 upgrade path. - "RUSTSEC-2026-0194", - "RUSTSEC-2026-0195", ]