Skip to content

feat(anthropic): add search result blocks and custom content documents with native citations - #16740

Open
satotek wants to merge 4 commits into
vercel:mainfrom
satotek:feat/anthropic-search-result-blocks
Open

satotek wants to merge 4 commits into
vercel:mainfrom
satotek:feat/anthropic-search-result-blocks

Conversation

@satotek

@satotek satotek commented Jul 6, 2026

Copy link
Copy Markdown

Background

Anthropic's search result blocks (search_result content blocks) are generally available and let Claude cite specific passages from RAG results with the same citation quality as web search. The docs describe two ways to provide them — from tool calls ("the most powerful use case", enabling dynamic RAG) and as top-level message content — and note that they "eliminate the need for document-based workarounds". The AI SDK currently supports neither, so RAG applications fall back to exactly that workaround: document blocks injected as extra message content.

That workaround breaks down in turns that mix server tools and client tools: per Anthropic's mixed-turn rules, the follow-up user message must contain nothing except tool_result blocks, so any injected document block leaves a deferred web_search call unresolved and the request fails with a 400 (`web_search` tool use ... was found without a corresponding `web_search_tool_result` block). Search results inside the tool result avoid this entirely.

#11968 (credit to @lithdew) proposed file-part support for search results, but has been stuck in review and now conflicts with main after the provider file renames. This PR re-implements that scope on current main and additionally supports search results inside tool results.

Summary

This implements both methods from Anthropic's Search Results documentation:

  • Method 1 — search results from tool calls (new in this PR): tools return a content tool output (e.g. via toModelOutput) whose text parts carry providerOptions.anthropic.type: 'search_result' (source, title, optional content blocks, citations). The blocks are emitted inside the tool_result, which makes RAG tool output directly citable and works in mixed server-tool/client-tool turns. Options are validated with a zod schema; invalid options fall back to plain text with a warning instead of sending a malformed block.
  • Method 2 — search results as top-level content (scope of feat(anthropic): search result blocks and custom content documents #11968): file parts with the same provider options are emitted as search_result blocks in the user message.
  • Custom content documents: source: { type: 'content', content: [...] } sends pre-chunked text as a citable document block (content_block_location citations).
  • The new citation types search_result_location and content_block_location are parsed (response + streaming) and returned as source parts with provider metadata (citedText, source, searchResultIndex, startBlockIndex, endBlockIndex).
  • extractCitationDocuments excludes search result parts so document_index stays aligned: per the API contract, search results are counted separately via search_result_index "across all messages and tool results". Covered by an alignment test with mixed search results and documents.

Manual Verification

Verified end-to-end against the live Anthropic Messages API (via a Microsoft Foundry Anthropic endpoint, claude-sonnet-5):

  1. File part search result (generateText): response contained a search_result_location citation, returned as a source part with citedText / source / searchResultIndex / block range metadata. With two search results, search_result_index 0 and 1 were attributed correctly.
  2. Search results inside tool results (generateText + custom tool with toModelOutput): the model called the tool, the tool result carried search_result blocks, and the answer cited them natively (both included examples were run against the live API).
  3. Mixed server/client tool turn: the same RAG tool together with anthropic.tools.webSearch_20250305 in one request. The deferred web search resolved without a 400, and the final answer contained both url sources (web search) and document sources (tool-result search results).

pnpm test in packages/anthropic: 451 tests pass (node + edge).

Checklist

  • All commits are signed (PRs with unsigned commits cannot be merged)
  • Tests have been added / updated (for bug fixes / features)
  • Documentation has been added / updated (for bug fixes / features)
  • A patch changeset for relevant packages has been added (for bug fixes / features - run pnpm changeset in the project root)
  • I have reviewed this pull request (self-review)

Future Work

Related Issues

Supersedes #11968 (conflicts with main after the provider file renames; scope is included here). Related: #4497 (Anthropic Citations API support).

@mtucker

mtucker commented Jul 8, 2026

Copy link
Copy Markdown

👀 very interested in this functionality - we are currently patching the anthropic provider to support citing tool call results

@satotek

satotek commented Jul 29, 2026

Copy link
Copy Markdown
Author

I’ve merged the latest main branch, resolved the conflicts, and rerun the Anthropic tests and repository-wide checks. Everything passes.

We’re currently using this functionality through a local patch, so we’d really appreciate having it supported upstream.

I’d appreciate a review when you have a chance.

…ch-result-blocks

# Conflicts:
#	packages/anthropic/src/anthropic-api.ts
…t responses

Since inbound citations are now normalized onto text parts (`citations`), drop
the duplicate source-part mapping for `search_result_location` and
`content_block_location`. This PR now only adds sending search result blocks
(in tool results and as file parts) and custom content documents.

This branch has not been deployed

No deployments
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