Skip to content

Fit search and scrape descriptions under Claude Code's 2,048-character cap, routing copy first - #436

Merged
rakshith48 merged 2 commits into
mainfrom
tool-description-budget
Sep 23, 2026
Merged

rakshith48 merged 2 commits into
mainfrom
tool-description-budget

Conversation

@rakshith48

@rakshith48 rakshith48 commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Claude Code truncates each tool description at 2,048 characters. On main the Alexandria copy starts at character 1,530 of 4,943 in firecrawl_search and 1,273 of 4,499 in firecrawl_scrape, so most of it never reaches the model. This PR puts the copy that changed agent behaviour in the AX runs first, and moves mechanics onto the parameters they describe.

main this PR
firecrawl_search 4,943 (Alexandria at 1,530) 1,747 (Alexandria at 259)
firecrawl_scrape 4,499 (Alexandria at 1,273) 1,465
/v2/mcp-search firecrawl_scrape ~3,350 < 1,500
server instructions, Alexandria paragraph starts at 1,454 starts at 709, ends inside 2,048

What stays in the first lines, and why

From the EXP-052/053/055/056 runs in firecrawl/agent-experience:

  • The noun "Alexandria" with its verticals. Naming the capability was the only thing that moved routing (9/11 provider-fit queries on both lanes vs 0–5/11). A tool rename did nothing, so firecrawl_find_tools is unchanged.
  • The sources opt-out. PR Alexandria routing copy: name the catalogue, keep search as the front door, make sources opt-out explicit #424's wording moved Codex from supplying sources on 291/291 searches to omitting it on roughly a third to half of calls. It stays on the sources parameter and now also sits in the search description's first lines.
  • Scrape reads first as "one URL, returns the page". EXP-055 found Codex sends single-page reads to Exa because Firecrawl's scrape tool reads as heavy. The scrape-first pointer to search stays; it is the only copy that reaches known-URL tasks.
  • Search stays the front door. firecrawl_find_tools still says "Prefer normal firecrawl_search".

Moved, not dropped

  • query: search operators. includeDomains / excludeDomains: their own descriptions. scrapeOptions: the maxAge note and "never provider tools".
  • alexandria: batch shape, version pinning, contract reading (required inputs, requiresOneOf, response.key, pagination), per-item errors, nextTool, access, and the terms flow.
  • requestId: retry rules and the error codes.
  • The firecrawl_feedback pointer stays in both the search and scrape descriptions, shortened.

Tests

New tests/mcp-description-budget.test.mjs (every full-surface tool ≤ 2,048; the Alexandria lead, sources opt-out and scrape-first pointer are present; scrape opens with the single-URL framing). The search-surface test checks every tool there ≤ 2,048. The smoke test checks the Alexandria paragraph, scrape-first rule and sources rule sit in the first 2,048 characters of the server instructions, and moved-text assertions now read the parameter descriptions. Suite 120/120. Version 3.25.4.

An AX sim comparing this build against main on the 11 provider-fit tester queries, both lanes, is running; results will be posted here.

🤖 Generated with Claude Code


Summary by cubic

Fits firecrawl_search and firecrawl_scrape descriptions under Claude Code's 2,048-character cap so the Alexandria routing copy reaches the model. The copy that changed agent behavior in the AX runs now leads each description; mechanics move onto the parameters they describe. firecrawl_search drops from 4,943 to 1,747 characters and firecrawl_scrape from 4,499 to 1,465.

  • The Alexandria lead (verticals, provider-over-scrape rule, sources opt-out) now sits in the search description's first lines; scrape opens with "Scrape one URL and return its content" and keeps the scrape-first pointer.
  • Query operators, domain filters, maxAge, retry rules, error codes, batch shape, and provider terms move onto the query, includeDomains, excludeDomains, scrapeOptions, alexandria, and requestId parameters.
  • Server instructions reorder the Alexandria paragraph ahead of the research and developer boilerplate so it lands inside the cap; those mechanics now live on the search description and requestId parameter instead.
  • Adds tests/helpers/description-budget.mjs with a shared cap constant and tests/mcp-description-budget.test.mjs; the search-surface and smoke tests pin every description under 2,048 characters and the routing copy inside the window. Suite passes 120/120; version bumped to 3.25.4.

Written for commit 88d7e1d. Summary will update on new commits.

Review in cubic

…r cap, routing copy first

Claude Code truncates each tool description at 2,048 characters. On main the Alexandria
copy started at character 1,530 of 4,943 (search) and 1,273 of 4,499 (scrape), so most
of it was cut. The copy that changed agent behaviour in the AX runs now leads each
description; mechanics move onto the parameters they describe.

- firecrawl_search (4,943 -> 1,747): what it does, then the Alexandria lead (verticals,
  when a provider beats scraping, the sources opt-out), then pointers. Operators move to
  query, the maxAge note to scrapeOptions, domain filters to their own parameters.
- firecrawl_scrape (4,499 -> 1,465): opens with 'Scrape one URL and return its content',
  keeps the scrape-first pointer, and points at the alexandria and requestId parameters,
  which now carry batching, contract reading, retries, error codes and provider terms.
  The duplicated Alexandria-mode paragraph is gone.
- /v2/mcp-search scrape (about 3,350 -> under 1,500): same treatment.
- Server instructions: the Alexandria routing paragraph moves ahead of the research and
  developer boilerplate so it sits inside the first 2,048 characters.
- Tests: every tool on both surfaces stays at or under 2,048; the Alexandria lead, the
  sources opt-out and the scrape-first pointer are pinned; moved-text assertions now
  read the parameter descriptions.
- Version 3.25.4.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 6 files

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread package.json
Comment thread tests/mcp-smoke.test.mjs Outdated
Comment thread src/index.ts
Comment thread tests/mcp-smoke.test.mjs Outdated
…s tests, document the instructions ordering trade-off

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 5 files (changes from recent commits).

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Requires human review: Auto-approval blocked by 1 unresolved issue from previous reviews.

Re-trigger cubic

@rakshith48

Copy link
Copy Markdown
Contributor Author

AX sim result (EXP-057): nothing broke. 11 provider-fit tester queries × Claude Code and Codex, prompt names Alexandria, main 55c1f99 vs this PR at 88d7e1d, 44 traces, digests verified on every trace.

main this PR
Claude: executed a provider 10/11 10/11
Codex: executed a provider 10/11 10/11
Codex: searches keeping Alexandria matches (sources omitted or incl. alexandria) 13/78 26/118
Codex: traces with at least one such search 9/11 11/11
Claude: searches keeping matches 5/17 7/21

Execution is identical per query in both lanes (the same ten execute; sodermalm-housing has no provider). All differences are within noise at n = 11; the named prompt saturates execution, so this is a non-inferiority check. Findings: firecrawl/agent-experience#845.

🤖 Generated with Claude Code

@Max17190 Max17190 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm!

@rakshith48
rakshith48 merged commit 0679784 into main Sep 23, 2026
2 checks passed
@rakshith48
rakshith48 deleted the tool-description-budget branch September 23, 2026 14:53
rakshith48 added a commit that referenced this pull request Sep 23, 2026
Scope keyless-unavailable tool pointers to authenticated sessions (stacked on #436)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants