From b32dde8f01bcf7aaf33b6782b6497b24f43efcb2 Mon Sep 17 00:00:00 2001 From: rramprakash Date: Thu, 16 Jul 2026 12:25:01 +0530 Subject: [PATCH] fix(firecrawl): thread user query into summarizer prompt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The summarizer prompt asked the model to 'directly answer the user query' but never rendered the query — Firecrawl's /v2/search response, unlike Tavily's, doesn't echo the query back, so it was dropped when adapting the prompt. Every summarized result (the common path, since scrapeOptions requests markdown) was therefore a generic page summary instead of a query-focused one. Thread the query through search -> parseHTTPResponse -> buildFirecrawlResult -> getSummarizePrompt and restore the USER QUERY line, matching Tavily. Add a test asserting the query is present in the prompt. --- backend/pkg/tools/firecrawl.go | 15 +++++++++------ backend/pkg/tools/firecrawl_test.go | 14 +++++++++----- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/backend/pkg/tools/firecrawl.go b/backend/pkg/tools/firecrawl.go index 7a4f9cc5..5db5817b 100644 --- a/backend/pkg/tools/firecrawl.go +++ b/backend/pkg/tools/firecrawl.go @@ -201,10 +201,10 @@ func (f *firecrawl) search(ctx context.Context, query string, maxResults int) (s } defer resp.Body.Close() - return f.parseHTTPResponse(ctx, resp) + return f.parseHTTPResponse(ctx, query, resp) } -func (f *firecrawl) parseHTTPResponse(ctx context.Context, resp *http.Response) (string, error) { +func (f *firecrawl) parseHTTPResponse(ctx context.Context, query string, resp *http.Response) (string, error) { switch resp.StatusCode { case http.StatusOK: var respBody firecrawlSearchResult @@ -217,7 +217,7 @@ func (f *firecrawl) parseHTTPResponse(ctx context.Context, resp *http.Response) } return "", fmt.Errorf("request failed") } - return f.buildFirecrawlResult(ctx, &respBody), nil + return f.buildFirecrawlResult(ctx, query, &respBody), nil case http.StatusBadRequest: return "", fmt.Errorf("request is invalid") case http.StatusUnauthorized: @@ -247,7 +247,7 @@ func (f *firecrawl) parseHTTPResponse(ctx context.Context, resp *http.Response) } } -func (f *firecrawl) buildFirecrawlResult(ctx context.Context, result *firecrawlSearchResult) string { +func (f *firecrawl) buildFirecrawlResult(ctx context.Context, query string, result *firecrawlSearchResult) string { var writer strings.Builder writer.WriteString("# Links\n\n") @@ -264,7 +264,7 @@ func (f *firecrawl) buildFirecrawlResult(ctx context.Context, result *firecrawlS } if isMarkdownExists && f.summarizer != nil { - summarizePrompt, err := f.getSummarizePrompt(result) + summarizePrompt, err := f.getSummarizePrompt(query, result) if err != nil { writer.WriteString(f.getContentFromResults(result.Data.Web)) } else { @@ -305,10 +305,12 @@ type firecrawlPromptDoc struct { Markdown string } -func (f *firecrawl) getSummarizePrompt(result *firecrawlSearchResult) (string, error) { +func (f *firecrawl) getSummarizePrompt(query string, result *firecrawlSearchResult) (string, error) { templateText := ` TASK: Summarize web search results for the following user query: +USER QUERY: "{{.Query}}" + DATA: - tags contain web page content with attributes: id, title, url - Content may include HTML, structured data, tables, or plain text @@ -355,6 +357,7 @@ The summary MUST provide complete answers to the user's query, preserving all re } templateContext := map[string]any{ + "Query": query, "MaxLength": maxRawContentLength, "Results": docs, } diff --git a/backend/pkg/tools/firecrawl_test.go b/backend/pkg/tools/firecrawl_test.go index 9c9a8313..0d1d02da 100644 --- a/backend/pkg/tools/firecrawl_test.go +++ b/backend/pkg/tools/firecrawl_test.go @@ -329,7 +329,7 @@ func TestFirecrawlParseHTTPResponse_StatusAndDecodeErrors(t *testing.T) { StatusCode: tt.statusCode, Body: io.NopCloser(strings.NewReader(tt.body)), } - result, err := fc.parseHTTPResponse(t.Context(), resp) + result, err := fc.parseHTTPResponse(t.Context(), "test query", resp) if !tt.wantErr { if err != nil { @@ -358,6 +358,10 @@ func TestFirecrawlBuildResult_WithSummarizer(t *testing.T) { if !strings.Contains(prompt, "