Vercel AI SDK
A news search tool for generateText, streamText and agents built with the Vercel AI SDK.
A tool over the HTTP API
A news search tool is one request to our API. Define it with tool() and give it to any model:
npm install ai zodimport { tool } from 'ai';
import { z } from 'zod';
type Result = { title: string; url: string; source: string | null; published_at: string | null; score: number; snippet: string | null };
export const newsSearch = tool({
description:
'Search recent news articles. Returns the title, URL, source, publication time and a relevance score (0–1) of each one.',
inputSchema: z.object({
query: z.string().describe('What to search for, in any language'),
days: z.number().int().min(1).max(365).optional().describe('Only articles from the last N days'),
}),
execute: async ({ query, days }) => {
const res = await fetch('https://api.typesearch.ai/v1/search', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.TYPESEARCH_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ query, days, mode: 'fast', max_results: 8 }),
});
if (!res.ok) throw new Error(`typesearch ${res.status}: ${await res.text()}`);
const { results } = (await res.json()) as { results: Result[] };
// Only what the model needs to answer and cite: fewer tokens in its context.
return results.map(({ title, url, source, published_at, score, snippet }) => ({ title, url, source, published_at, score, snippet }));
},
});import { generateText, stepCountIs } from 'ai';
import { newsSearch } from './news-search';
const { text } = await generateText({
model: 'anthropic/claude-sonnet-4.5',
tools: { newsSearch },
stopWhen: stepCountIs(5),
prompt: 'What changed in EU AI Act enforcement this week? Cite your sources.',
});streamText and agents take the same tool. The search runs in fast mode, $1.40 per 1,000 searches;
change it to 'normal' to have the top results read before they’re ranked ($2.20). Every parameter is
in the API reference.
Tips
- Keep the result small. Return the fields the model cites, as above: a full response has more than it needs.
- Let the model choose the time window.
daysin the schema lets it ask for today’s news or the last month’s, depending on the question. - Threshold on
score. It’s a calibrated probability: filter out results under0.5before the model sees them if your prompts need only what’s clearly on topic.