TanStack AI version
v0.34.0
Framework/Library version
@tanstack/ai-anthropic: 0.15.7
Describe the bug and the steps to reproduce it
Anthropic web_search results do not seem to be preserved correctly across turns when using @tanstack/ai with @tanstack/ai-anthropic.
I have a minimal repro comparing the same two-turn conversation implemented in two ways:
- Directly with the official Anthropic SDK.
- With TanStack AI using
chat(...) and StreamProcessor.
The first turn asks Claude to use web_search.
The second turn asks Claude to list the exact sources from the previous turn.
The official Anthropic SDK version works as expected: the second turn can still see the previous web_search evidence and returns the source URLs.
The TanStack AI version does not: after processing the first streamed response with StreamProcessor and passing processor.getMessages() into the second turn, Claude says it cannot see the previous web search evidence.
Repro
Anthropic SDK baseline
import "dotenv/config";
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
const firstUserMessage =
"Use the web_search tool now. Find two current web sources about the defense drone market. Answer with only the source names or URLs and one sentence about what each source says.";
const secondUserMessage =
"Using only the web search evidence from the previous turn, list the exact source names or URLs you relied on. If you cannot see the previous web search evidence, say exactly: I cannot see the previous web search evidence.";
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
async function main() {
const messages: Anthropic.MessageParam[] = [
{
role: "user",
content: firstUserMessage,
},
];
const firstResponse = await runTurn(messages);
messages.push({
role: "assistant",
content: firstResponse.content,
});
messages.push({
role: "user",
content: secondUserMessage,
});
const secondResponse = await runTurn(messages);
messages.push({
role: "assistant",
content: secondResponse.content,
});
process.stdout.write(`${JSON.stringify(messages, null, 2)}\n`);
}
async function runTurn(messages: Anthropic.MessageParam[]) {
return client.messages.create({
model: "claude-opus-4-7",
max_tokens: 8000,
output_config: {
effort: "medium",
},
thinking: {
display: "summarized",
type: "adaptive",
},
messages,
tools: [
{
name: "web_search",
type: "web_search_20250305",
allowed_callers: ["direct"],
max_uses: 2,
},
],
});
}
Output:
[
{
"role": "user",
"content": "Use the web_search tool now. Find two current web sources about the defense drone market. Answer with only the source names or URLs and one sentence about what each source says."
},
// ...
{
"role": "user",
"content": "Using only the web search evidence from the previous turn, list the exact source names or URLs you relied on. If you cannot see the previous web search evidence, say exactly: I cannot see the previous web search evidence."
},
{
"role": "assistant",
"content": [
{
"type": "text",
"text": "1. https://www.marketsandmarkets.com/Market-Reports/military-drone-market-221577711.html\n2. https://www.globenewswire.com/news-release/2026/03/05/3250316/0/en/Defense-Drone-Market-Accelerates-Toward-40B-Opportunity-as-Autonomous-Warfare-Redefines-Modern-Battlefields.html"
}
]
}
]
TanStack AI repro
import "dotenv/config";
import { chat, maxIterations, StreamProcessor } from "@tanstack/ai";
import { anthropicText } from "@tanstack/ai-anthropic";
import { webSearchTool } from "@tanstack/ai-anthropic/tools";
const firstUserMessage =
"Use the web_search tool now. Find two current web sources about the defense drone market. Answer with only the source names or URLs and one sentence about what each source says.";
const secondUserMessage =
"Using only the web search evidence from the previous turn, list the exact source names or URLs you relied on. If you cannot see the previous web search evidence, say exactly: I cannot see the previous web search evidence.";
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
async function main() {
const firstTurnMessages = await runTurn([
{
role: "user",
content: firstUserMessage,
},
]);
const secondTurnMessages = await runTurn([
...firstTurnMessages,
{
role: "user",
content: secondUserMessage,
},
]);
process.stdout.write(`${JSON.stringify(secondTurnMessages, null, 2)}\n`);
}
async function runTurn(messages) {
const stream = chat({
adapter: anthropicText("claude-opus-4-7"),
agentLoopStrategy: maxIterations(4),
messages,
modelOptions: {
max_tokens: 8000,
output_config: {
effort: "medium",
},
thinking: {
display: "summarized",
type: "adaptive",
},
},
threadId: "repro-anthropic-web-search-thinking",
tools: [
webSearchTool({
name: "web_search",
type: "web_search_20250305",
allowed_callers: ["direct"],
max_uses: 2,
}),
],
});
const processor = new StreamProcessor({
initialMessages: messages,
});
for await (const chunk of stream) {
processor.processChunk(chunk);
}
processor.finalizeStream();
return processor.getMessages();
}
Output:
[
{
"role": "user",
"content": "Use the web_search tool now. Find two current web sources about the defense drone market. Answer with only the source names or URLs and one sentence about what each source says."
},
{
"id": "anthropic-1782373873430-b5f734ksle6",
"role": "assistant",
"parts": [
{
"type": "thinking",
"content": "The user wants me to perform a web search for them.",
"stepId": "anthropic-1782373874356-g9gt9druvmk",
"signature": "Eu4BCmMIDxgCKkBUlYA6s9gsfrmpEy9a28XiiB70GEVcmrkFocHZDw049VlPz4RA1bnST1D2u6dinTUyg/S09i0zPyvNbtqrF8F9Mg9jbGF1ZGUtb3B1cy00LTc4AEIIdGhpbmtpbmcSDK/3+XSxaLdc7AIvWhoM2nGQGAen5DDL/8SoIjDrLCzrc4Z6Hhdsj3pgbGsITSCHd+Aw4NIrR54ukP4ISt0F/HyvqnG9SoFl2yZc9zkqOQ14/QXETrqcsv2W/I6lZFeDXzRvGqZubfWOZX1SdaUnrOaFMEvxrMQ1hBjFC83WJAEVZ6ZrbxdRWBgB"
},
{
"type": "text",
"content": "Here are two current sources on the defense drone market:\n\n1. **MarketsandMarkets** (marketsandmarkets.com) — Valued the global military drones market at USD 34.85 billion in 2026, projecting it to reach USD 109.22 billion by 2031 at a 25.7% CAGR, with procurement volume growing from 16,157 units in 2026 to 26,544 units by 2031.\n\n2. **Global Market Insights** (gminsights.com) — Reports the market growing from USD 20.7 billion in 2026 to USD 39.4 billion in 2031 and USD 66.5 billion in 2035 at a 13.8% CAGR, driven by escalating global defense expenditure, geopolitical tensions, and technological advancements in autonomous systems."
}
],
"createdAt": "2026-06-25T07:51:15.175Z"
},
{
"role": "user",
"content": "Using only the web search evidence from the previous turn, list the exact source names or URLs you relied on. If you cannot see the previous web search evidence, say exactly: I cannot see the previous web search evidence."
},
{
"id": "anthropic-1782373886138-j3es62eubsm",
"role": "assistant",
"parts": [
{
"type": "text",
"content": "I cannot see the previous web search evidence."
}
],
"createdAt": "2026-06-25T07:51:26.173Z"
}
]
Expected behavior
The messages returned by StreamProcessor.getMessages() should preserve Anthropic web_search result blocks in a form that can be reused in a later turn.
The second TanStack AI turn should be able to see the same previous web search evidence that the official Anthropic SDK preserves.
Actual behavior
The second TanStack AI turn cannot see the previous web_search evidence.
The equivalent official Anthropic SDK script preserves the evidence and works correctly.
Your Minimal, Reproducible Example - (Sandbox Highly Recommended)
See the minimal repro scripts in the issue description below.
Screenshots or Videos (Optional)
No response
Do you intend to try to help solve this bug with your own PR?
No, because I do not know how
Terms & Code of Conduct
TanStack AI version
v0.34.0
Framework/Library version
@tanstack/ai-anthropic: 0.15.7
Describe the bug and the steps to reproduce it
Anthropic
web_searchresults do not seem to be preserved correctly across turns when using@tanstack/aiwith@tanstack/ai-anthropic.I have a minimal repro comparing the same two-turn conversation implemented in two ways:
chat(...)andStreamProcessor.The first turn asks Claude to use
web_search.The second turn asks Claude to list the exact sources from the previous turn.
The official Anthropic SDK version works as expected: the second turn can still see the previous
web_searchevidence and returns the source URLs.The TanStack AI version does not: after processing the first streamed response with
StreamProcessorand passingprocessor.getMessages()into the second turn, Claude says it cannot see the previous web search evidence.Repro
Anthropic SDK baseline
Output:
[ { "role": "user", "content": "Use the web_search tool now. Find two current web sources about the defense drone market. Answer with only the source names or URLs and one sentence about what each source says." }, // ... { "role": "user", "content": "Using only the web search evidence from the previous turn, list the exact source names or URLs you relied on. If you cannot see the previous web search evidence, say exactly: I cannot see the previous web search evidence." }, { "role": "assistant", "content": [ { "type": "text", "text": "1. https://www.marketsandmarkets.com/Market-Reports/military-drone-market-221577711.html\n2. https://www.globenewswire.com/news-release/2026/03/05/3250316/0/en/Defense-Drone-Market-Accelerates-Toward-40B-Opportunity-as-Autonomous-Warfare-Redefines-Modern-Battlefields.html" } ] } ]TanStack AI repro
Output:
[ { "role": "user", "content": "Use the web_search tool now. Find two current web sources about the defense drone market. Answer with only the source names or URLs and one sentence about what each source says." }, { "id": "anthropic-1782373873430-b5f734ksle6", "role": "assistant", "parts": [ { "type": "thinking", "content": "The user wants me to perform a web search for them.", "stepId": "anthropic-1782373874356-g9gt9druvmk", "signature": "Eu4BCmMIDxgCKkBUlYA6s9gsfrmpEy9a28XiiB70GEVcmrkFocHZDw049VlPz4RA1bnST1D2u6dinTUyg/S09i0zPyvNbtqrF8F9Mg9jbGF1ZGUtb3B1cy00LTc4AEIIdGhpbmtpbmcSDK/3+XSxaLdc7AIvWhoM2nGQGAen5DDL/8SoIjDrLCzrc4Z6Hhdsj3pgbGsITSCHd+Aw4NIrR54ukP4ISt0F/HyvqnG9SoFl2yZc9zkqOQ14/QXETrqcsv2W/I6lZFeDXzRvGqZubfWOZX1SdaUnrOaFMEvxrMQ1hBjFC83WJAEVZ6ZrbxdRWBgB" }, { "type": "text", "content": "Here are two current sources on the defense drone market:\n\n1. **MarketsandMarkets** (marketsandmarkets.com) — Valued the global military drones market at USD 34.85 billion in 2026, projecting it to reach USD 109.22 billion by 2031 at a 25.7% CAGR, with procurement volume growing from 16,157 units in 2026 to 26,544 units by 2031.\n\n2. **Global Market Insights** (gminsights.com) — Reports the market growing from USD 20.7 billion in 2026 to USD 39.4 billion in 2031 and USD 66.5 billion in 2035 at a 13.8% CAGR, driven by escalating global defense expenditure, geopolitical tensions, and technological advancements in autonomous systems." } ], "createdAt": "2026-06-25T07:51:15.175Z" }, { "role": "user", "content": "Using only the web search evidence from the previous turn, list the exact source names or URLs you relied on. If you cannot see the previous web search evidence, say exactly: I cannot see the previous web search evidence." }, { "id": "anthropic-1782373886138-j3es62eubsm", "role": "assistant", "parts": [ { "type": "text", "content": "I cannot see the previous web search evidence." } ], "createdAt": "2026-06-25T07:51:26.173Z" } ]Expected behavior
The messages returned by
StreamProcessor.getMessages()should preserve Anthropicweb_searchresult blocks in a form that can be reused in a later turn.The second TanStack AI turn should be able to see the same previous web search evidence that the official Anthropic SDK preserves.
Actual behavior
The second TanStack AI turn cannot see the previous
web_searchevidence.The equivalent official Anthropic SDK script preserves the evidence and works correctly.
Your Minimal, Reproducible Example - (Sandbox Highly Recommended)
See the minimal repro scripts in the issue description below.
Screenshots or Videos (Optional)
No response
Do you intend to try to help solve this bug with your own PR?
No, because I do not know how
Terms & Code of Conduct