From 2477a18be3f2e133b2bbfacde32a6a400d9daf2d Mon Sep 17 00:00:00 2001 From: jh-block Date: Tue, 10 Feb 2026 11:17:06 +0100 Subject: [PATCH] Fix duplicated output in Code Mode by filtering content by audience The shell tool returns two Content::text items: one for the assistant and one for the user. For short outputs both contain identical text. The callback in code_execution_extension was joining all text content without filtering by audience, causing the output to appear twice. Filter to only include content targeted at the assistant (or with no audience restriction) before joining text results. --- crates/goose/src/agents/code_execution_extension.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/crates/goose/src/agents/code_execution_extension.rs b/crates/goose/src/agents/code_execution_extension.rs index cb91eb389d..d6e8381a9b 100644 --- a/crates/goose/src/agents/code_execution_extension.rs +++ b/crates/goose/src/agents/code_execution_extension.rs @@ -7,7 +7,7 @@ use pctx_code_mode::model::{CallbackConfig, ExecuteInput, GetFunctionDetailsInpu use pctx_code_mode::{CallbackRegistry, CodeMode}; use rmcp::model::{ CallToolRequestParams, CallToolResult, Content, Implementation, InitializeResult, JsonObject, - ListToolsResult, ProtocolVersion, RawContent, ServerCapabilities, Tool as McpTool, + ListToolsResult, ProtocolVersion, RawContent, Role, ServerCapabilities, Tool as McpTool, ToolAnnotations, ToolsCapability, }; use schemars::{schema_for, JsonSchema}; @@ -272,9 +272,16 @@ fn create_tool_callback( if let Some(sc) = &result.structured_content { Ok(serde_json::to_value(sc).unwrap_or(Value::Null)) } else { + // Filter to assistant-audience or no-audience content, + // skipping user-only content to avoid duplicated output let text: String = result .content .iter() + .filter(|c| { + c.audience().is_none_or(|audiences| { + audiences.is_empty() || audiences.contains(&Role::Assistant) + }) + }) .filter_map(|c| match &c.raw { RawContent::Text(t) => Some(t.text.clone()), _ => None,