From 5f66f52a1e17ede9cf45b1e17f3c60f0ab09f763 Mon Sep 17 00:00:00 2001 From: Christian Rocha Date: Tue, 3 Mar 2026 11:38:37 -0700 Subject: [PATCH] fix(tools/fetch): cap fetch tool at 50K tokens This prevents the fetch tool from blowing through context windows. Prior to this the limit was 5MB, or about 390K tokens. For larger fetches, the agent is urged to use agentic_fetch, which performs the fetch in an isolated context window. --- internal/agent/tools/fetch.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/internal/agent/tools/fetch.go b/internal/agent/tools/fetch.go index 0129fc3a46d264007649be088d843c0ebbf76149..69bd5c3560fe0ac96d036354476e6797bcfccb5e 100644 --- a/internal/agent/tools/fetch.go +++ b/internal/agent/tools/fetch.go @@ -160,10 +160,16 @@ func NewFetchTool(permissions permission.Service, workingDir string, client *htt content = "\n\n" + body + "\n\n" } } + // maxFetchContentSize is the maximum size of content to return + // (200KB). This limit ensures content fits within model context + // windows. 200KB is about 50K tokens, which should leave more room + // for system prompts and conversation history. + const maxFetchContentSize = 200 * 1024 + // truncate content if it exceeds max read size - if int64(len(content)) > MaxReadSize { - content = content[:MaxReadSize] - content += fmt.Sprintf("\n\n[Content truncated to %d bytes]", MaxReadSize) + if len(content) > maxFetchContentSize { + content = content[:maxFetchContentSize] + content += fmt.Sprintf("\n\n[Content truncated to %d bytes. The original page was larger: consider using agentic_fetch for large pages.]", maxFetchContentSize) } return fantasy.NewTextResponse(content), nil