Skip to content

fix(citation): give fetch results citation labels - #1045

Merged
miurla merged 2 commits into
mainfrom
fix/fetch-citation-labels-20260926
Sep 26, 2026
Merged

miurla merged 2 commits into
mainfrom
fix/fetch-citation-labels-20260926

Conversation

@miurla

@miurla miurla commented Sep 25, 2026

Copy link
Copy Markdown
Owner

Problem

Answers built only from a fetch tool call cite labels that do not exist (for example [1](#S0)). No result in the conversation carries such a label, so the citation renders as a dead in-page anchor instead of linking to the fetched page.

Root cause

Citation labels were stamped only on search results. lib/tools/fetch.ts returned results with title, content and url but no label on every path (regular, Jina Reader, Tavily extract), and nextCitationLabelNumber / extractCitationMaps only walked tool-search parts. The prompts make citations mandatory and describe the target only as the search result's label, so a turn that fetched a user-provided URL had nothing to cite and the model guessed a label in the S<n> shape.

Fix

  • lib/utils/citation.ts: add createCitationLabelAllocator, a synchronous block allocator shared by the tools of one turn. nextCitationLabelNumber and extractCitationMaps now include tool-fetch outputs, so fetch labels seed later turns and resolve to the fetched URL (label map only, no toolCallId map for fetch). The existing ambiguous-label handling applies to labels from either tool.
  • lib/tools/fetch.ts: createFetchTool({ labelAllocator }) stamps labels on fetched results after retrieval succeeds. fetchTool is still exported for the type definitions.
  • lib/tools/search.ts: accepts the shared allocator, falling back to one built from labelSeed.
  • lib/agents/researcher.ts: one allocator from citationLabelSeed is passed to both search and fetch, so labels stay unique when a turn mixes them.
  • Prompts: "Each search result carries a label" now reads "Each search or fetch result carries a label".

Fixes #1043

Verification

  • Unit tests: fetch results carry labels from the allocator seed; a shared allocator gives non-overlapping blocks in both search-then-fetch and fetch-then-search order; nextCitationLabelNumber counts fetch labels; a fetch label resolves through processCitations to the fetched URL; the researcher passes one allocator to both tools.
  • bun lint, bun typecheck, bun format:check, bun run build, bun run test all pass.

Fetch results carried no label, so a turn that only fetched a URL had a
mandatory citation and nothing to cite, and the model invented S<n>
labels that rendered as dead anchors. Search and fetch now share one
label allocator per turn, fetch labels are counted when seeding the next
turn and resolved in the citation map, and the prompts say fetch results
carry labels too.

Fixes #1043
@vercel

vercel Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
morphic Ready Ready Preview Sep 25, 2026 6:45pm UTC

Request Review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-25T18:47:07.616246Z 05f9882 New commits
🔒 Security Review ✅ Completed 2026-09-25T18:48:49.474069Z 05f9882 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 911f8947e0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

- Prioritize recency when relevant and reference dates
- Your FIRST action for informational questions without URLs MUST be the \`search\` tool. Do not produce the final answer until at least one search has completed in this turn
- Citation integrity: Each search result carries a \`label\` field. Cite that label exactly as it appears on the result you used and never invent one
- Citation integrity: Each search or fetch result carries a \`label\` field. Cite that label exactly as it appears on the result you used and never invent one

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Label fixture fetch results to match the prompt

When the adaptive answer evaluation follows its Search → Fetch flow, run-answer-task.ts uses this prompt with createFixtureFetchTool, but that fixture returns the original unlabelled SearchFixture objects from evals/tasks/fixture-tools.ts. The model is therefore told that every fetched result has a label and must cite it exactly, while the eval tool supplies none, encouraging invented or missing citations and making experiment behavior diverge from production; stamp fixture fetch results with the same allocator/labels as the production fetch tool.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in the latest push: the fixture fetch tool now returns results carrying the same label the fixture search gave that document, so a citation of the fetched page resolves in the eval as in production.

@miurla
miurla merged commit 25d572a into main Sep 26, 2026
9 checks passed
@miurla
miurla deleted the fix/fetch-citation-labels-20260926 branch September 26, 2026 01:29

This branch was successfully deployed

1 active deployment
Preview — 05f9882b Deployed Sep 25, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

automated Created by the automated daily pipeline

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fetch-only answers cite labels that do not exist because fetch results carry no citation label

1 participant