From fc9f1ec921564c15922e76715cbddcfd0d710abb Mon Sep 17 00:00:00 2001 From: Luca Martinetti Date: Sun, 1 Mar 2026 21:48:11 +0100 Subject: [PATCH] fix: return fetched content to LLM in web_fetch tool (#833) * fix: return fetched content to LLM in web_fetch tool WebFetchTool.Execute was setting ForLLM to a summary string ("Fetched N bytes from URL ...") instead of the actual extracted text. This meant the LLM never saw the page content and could not answer questions based on fetched web pages. Return the extracted text in ForLLM so the model can use it. Co-Authored-By: Claude Opus 4.6 * fix: put full JSON result in ForLLM, summary in ForUser Accept suggestion from afjcjsbx: the LLM should receive the full JSON result (including extracted text) while the user sees a short summary. Update tests to match the new field assignment. Co-Authored-By: Claude Opus 4.6 --------- Co-authored-by: Claude Opus 4.6 --- pkg/tools/web.go | 4 ++-- pkg/tools/web_test.go | 34 +++++++++++++++++----------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/pkg/tools/web.go b/pkg/tools/web.go index 0f7dafee9..bf9144f18 100644 --- a/pkg/tools/web.go +++ b/pkg/tools/web.go @@ -661,14 +661,14 @@ func (t *WebFetchTool) Execute(ctx context.Context, args map[string]any) *ToolRe resultJSON, _ := json.MarshalIndent(result, "", " ") return &ToolResult{ - ForLLM: fmt.Sprintf( + ForLLM: string(resultJSON), + ForUser: fmt.Sprintf( "Fetched %d bytes from %s (extractor: %s, truncated: %v)", len(text), urlStr, extractor, truncated, ), - ForUser: string(resultJSON), } } diff --git a/pkg/tools/web_test.go b/pkg/tools/web_test.go index db3c08ba6..84ec10d96 100644 --- a/pkg/tools/web_test.go +++ b/pkg/tools/web_test.go @@ -32,14 +32,14 @@ func TestWebTool_WebFetch_Success(t *testing.T) { t.Errorf("Expected success, got IsError=true: %s", result.ForLLM) } - // ForUser should contain the fetched content - if !strings.Contains(result.ForUser, "Test Page") { - t.Errorf("Expected ForUser to contain 'Test Page', got: %s", result.ForUser) + // ForLLM should contain the fetched content (full JSON result) + if !strings.Contains(result.ForLLM, "Test Page") { + t.Errorf("Expected ForLLM to contain 'Test Page', got: %s", result.ForLLM) } - // ForLLM should contain summary - if !strings.Contains(result.ForLLM, "bytes") && !strings.Contains(result.ForLLM, "extractor") { - t.Errorf("Expected ForLLM to contain summary, got: %s", result.ForLLM) + // ForUser should contain summary + if !strings.Contains(result.ForUser, "bytes") && !strings.Contains(result.ForUser, "extractor") { + t.Errorf("Expected ForUser to contain summary, got: %s", result.ForUser) } } @@ -68,9 +68,9 @@ func TestWebTool_WebFetch_JSON(t *testing.T) { t.Errorf("Expected success, got IsError=true: %s", result.ForLLM) } - // ForUser should contain formatted JSON - if !strings.Contains(result.ForUser, "key") && !strings.Contains(result.ForUser, "value") { - t.Errorf("Expected ForUser to contain JSON data, got: %s", result.ForUser) + // ForLLM should contain formatted JSON + if !strings.Contains(result.ForLLM, "key") && !strings.Contains(result.ForLLM, "value") { + t.Errorf("Expected ForLLM to contain JSON data, got: %s", result.ForLLM) } } @@ -159,9 +159,9 @@ func TestWebTool_WebFetch_Truncation(t *testing.T) { t.Errorf("Expected success, got IsError=true: %s", result.ForLLM) } - // ForUser should contain truncated content (not the full 20000 chars) + // ForLLM should contain truncated content (not the full 20000 chars) resultMap := make(map[string]any) - json.Unmarshal([]byte(result.ForUser), &resultMap) + json.Unmarshal([]byte(result.ForLLM), &resultMap) if text, ok := resultMap["text"].(string); ok { if len(text) > 1100 { // Allow some margin t.Errorf("Expected content to be truncated to ~1000 chars, got: %d", len(text)) @@ -237,14 +237,14 @@ func TestWebTool_WebFetch_HTMLExtraction(t *testing.T) { t.Errorf("Expected success, got IsError=true: %s", result.ForLLM) } - // ForUser should contain extracted text (without script/style tags) - if !strings.Contains(result.ForUser, "Title") && !strings.Contains(result.ForUser, "Content") { - t.Errorf("Expected ForUser to contain extracted text, got: %s", result.ForUser) + // ForLLM should contain extracted text (without script/style tags) + if !strings.Contains(result.ForLLM, "Title") && !strings.Contains(result.ForLLM, "Content") { + t.Errorf("Expected ForLLM to contain extracted text, got: %s", result.ForLLM) } - // Should NOT contain script or style tags - if strings.Contains(result.ForUser, "