| name | ydc-ai-sdk-integration |
| description | Integrate Vercel AI SDK applications with You.com tools (web search, AI agent, content extraction). Use when developer mentions AI SDK, Vercel AI SDK, generateText, streamText, or You.com integration with AI SDK. |
| license | MIT |
| compatibility | Requires Node.js 18+ and npm/bun/yarn/pnpm |
| metadata | {"author":"youdotcom-oss","category":"sdk-integration","version":"1.0.0","keywords":"vercel,vercel-ai-sdk,ai-sdk,you.com,integration,anthropic,openai,web-search,content-extraction,livecrawl,citations"} |
Integrate AI SDK with You.com Tools
Interactive workflow to add You.com tools to your Vercel AI SDK application using @youdotcom-oss/ai-sdk-plugin.
Workflow
-
Ask: Package Manager
-
Ask: Environment Variable Name
- Using standard
YDC_API_KEY?
- Or custom name? (if custom, get the name)
- Have they set it in their environment?
- If NO: Guide them to get key from https://you.com/platform/api-keys
-
Ask: Which AI SDK Functions?
- Do they use
generateText()?
- Do they use
streamText()?
- Both?
-
Ask: Existing Files or New Files?
- EXISTING: Ask which file(s) to edit
- NEW: Ask where to create file(s) and what to name them
-
For Each File, Ask:
- Which tools to add?
youSearch (web search)
youExpress (AI agent)
youContents (content extraction)
- Multiple? (which combination?)
- Using
generateText() or streamText() in this file?
- Which AI provider model? (to determine if stopWhen needed)
-
Reference Integration Examples
See "Integration Examples" section below for complete code patterns:
- generateText() - Basic text generation with tools
- streamText() - Streaming responses with web frameworks (Next.js, Express, React)
-
Update/Create Files
For each file:
- Reference integration examples (generateText or streamText based on their answer)
- Add import for selected tools
- If EXISTING file: Find their generateText/streamText call and add tools object
- If NEW file: Create file with example structure
- Tool invocation pattern based on env var name:
- Standard
YDC_API_KEY: youSearch()
- Custom name:
youSearch({ apiKey: process.env.CUSTOM_NAME })
- Add selected tools to tools object
- If streamText + Anthropic: Add stopWhen parameter
Integration Examples
generateText() - Basic Text Generation
Environment Variables Setup:
import { anthropic } from '@ai-sdk/anthropic';
import { generateText } from 'ai';
import { youContents, youExpress, youSearch } from '@youdotcom-oss/ai-sdk-plugin';
const result = await generateText({
model: anthropic('claude-sonnet-4-5-20250929'),
tools: {
search: youSearch(),
},
prompt: 'What are the latest developments in quantum computing?',
});
console.log(result.text);
Multiple Tools:
const result = await generateText({
model: anthropic('claude-sonnet-4-5-20250929'),
tools: {
search: youSearch(),
agent: youExpress(),
extract: youContents(),
},
prompt: 'Research quantum computing and summarize the key papers',
});
Custom API Key:
const result = await generateText({
model: anthropic('claude-sonnet-4-5-20250929'),
tools: {
search: youSearch({ apiKey: 'your-custom-key' }),
},
prompt: 'Your prompt here',
});
Complete Example:
import { anthropic } from '@ai-sdk/anthropic';
import { generateText } from 'ai';
import { youSearch } from '@youdotcom-oss/ai-sdk-plugin';
const main = async () => {
try {
const result = await generateText({
model: anthropic('claude-sonnet-4-5-20250929'),
tools: {
search: youSearch(),
},
maxSteps: 5,
prompt: 'What are the latest developments in quantum computing?',
});
console.log('Generated text:', result.text);
console.log('\nTool calls:', result.steps.flatMap(s => s.toolCalls));
} catch (error) {
console.error('Error:', error);
process.exit(1);
}
};
main();
streamText() - Streaming Responses
Basic Streaming with stopWhen Pattern:
import { anthropic } from '@ai-sdk/anthropic';
import { streamText, type StepResult } from 'ai';
import { youSearch } from '@youdotcom-oss/ai-sdk-plugin';
const stepCountIs = (n: number) => (stepResult: StepResult<any>) =>
stepResult.stepNumber >= n;
const result = streamText({
model: anthropic('claude-sonnet-4-5-20250929'),
tools: { search: youSearch() },
stopWhen: stepCountIs(3),
prompt: 'What are the latest AI developments?',
});
for await (const chunk of result.textStream) {
process.stdout.write(chunk);
}
Next.js Integration (App Router):
import { anthropic } from '@ai-sdk/anthropic';
import { streamText, type StepResult } from 'ai';
import { youSearch } from '@youdotcom-oss/ai-sdk-plugin';
const stepCountIs = (n: number) => (stepResult: StepResult<any>) =>
stepResult.stepNumber >= n;
export async function POST(req: Request) {
const { prompt } = await req.json();
const result = streamText({
model: anthropic('claude-sonnet-4-5-20250929'),
tools: { search: youSearch() },
stopWhen: stepCountIs(5),
prompt,
});
return result.toDataStreamResponse();
}
Express.js Integration:
import express from 'express';
import { anthropic } from '@ai-sdk/anthropic';
import { streamText, type StepResult } from 'ai';
import { youSearch } from '@youdotcom-oss/ai-sdk-plugin';
const app = express();
app.use(express.json());
const stepCountIs = (n: number) => (stepResult: StepResult<any>) =>
stepResult.stepNumber >= n;
app.post('/api/chat', async (req, res) => {
const { prompt } = req.body;
const result = streamText({
model: anthropic('claude-sonnet-4-5-20250929'),
tools: { search: youSearch() },
stopWhen: stepCountIs(5),
prompt,
});
res.setHeader('Content-Type', 'text/plain; charset=utf-8');
res.setHeader('Transfer-Encoding', );
( chunk result.) {
res.(chunk);
}
res.();
});
app.();
React Client (with Next.js):
'use client';
import { useChat } from 'ai/react';
export default function Chat() {
const { messages, input, handleInputChange, handleSubmit } = useChat({
api: '/api/chat',
});
return (
<div>
{messages.map(m => (
<div key={m.id}>
<strong>{m.role}:</strong> {m.content}
</div>
))}
<form onSubmit={handleSubmit}>
<input value={input} onChange={handleInputChange} />
<button type="submit">Send</button>
</form>
</div>
);
}
Complete Streaming Example:
import { anthropic } from '@ai-sdk/anthropic';
import { streamText, type StepResult } from 'ai';
import { youSearch } from '@youdotcom-oss/ai-sdk-plugin';
const stepCountIs = (n: number) => (stepResult: StepResult<any>) =>
stepResult.stepNumber >= n;
const main = async () => {
try {
const result = streamText({
model: anthropic('claude-sonnet-4-5-20250929'),
tools: {
search: youSearch(),
},
stopWhen: stepCountIs(3),
prompt: 'What are the latest AI developments?',
});
console.log('Streaming response:\n');
for await (const chunk of result.textStream) {
process.stdout.write(chunk);
}
.();
} (error) {
.(, error);
process.();
}
};
();
Tool Invocation Patterns
Based on env var name from step 2:
Standard YDC_API_KEY:
import { youSearch } from '@youdotcom-oss/ai-sdk-plugin';
tools: {
search: youSearch(),
}
Custom env var:
import { youSearch } from '@youdotcom-oss/ai-sdk-plugin';
const apiKey = process.env.THEIR_CUSTOM_NAME;
tools: {
search: youSearch({ apiKey }),
}
Multiple tools with standard env var:
import { youSearch, youExpress, youContents } from '@youdotcom-oss/ai-sdk-plugin';
tools: {
search: youSearch(),
agent: youExpress(),
extract: youContents(),
}
Multiple tools with custom env var:
import { youSearch, youExpress, youContents } from '@youdotcom-oss/ai-sdk-plugin';
const apiKey = process.env.THEIR_CUSTOM_NAME;
tools: {
search: youSearch({ apiKey }),
agent: youExpress({ apiKey }),
extract: youContents({ apiKey }),
}
Available Tools
youSearch
Web and news search - model determines parameters (query, count, country, etc.)
youExpress
AI agent with web context - model determines parameters (input, tools)
youContents
Web page content extraction - model determines parameters (urls, format)
Key Integration Patterns
The examples above demonstrate:
- Import statements (AI SDK + provider + You.com tools)
- Env var validation (optional for new files)
- Tool configuration based on env var
- generateText/streamText usage with tools
- Result handling (especially textStream destructuring for streamText)
- Anthropic streaming pattern (stopWhen: stepCountIs(3))
- Web framework integration (Next.js, Express, React)
Implementation Checklist
For each file being updated/created:
Global checklist:
Common Issues
Issue: "Cannot find module @youdotcom-oss/ai-sdk-plugin"
Fix: Install with their package manager
Issue: "YDC_API_KEY (or custom name) environment variable is required"
Fix: Set in their environment (get key: https://you.com/platform/api-keys)
Issue: "Tool execution fails with 401"
Fix: Verify API key is valid
Issue: "Incomplete or missing response"
Fix: If using streamText, increase the step count. Start with 3 and iterate up as needed (see README troubleshooting)
Issue: "textStream is not iterable"
Fix: Destructure: const { textStream } = streamText(...)
Issue: "Custom env var not working"
Fix: Pass to each tool: youSearch({ apiKey })
Advanced: Tool Development Patterns
For developers creating custom AI SDK tools or contributing to @youdotcom-oss/ai-sdk-plugin:
Tool Function Structure
Each tool function follows this pattern:
export const youToolName = (config: YouToolsConfig = {}) => {
const apiKey = config.apiKey ?? process.env.YDC_API_KEY;
return tool({
description: 'Tool description for AI model',
inputSchema: ZodSchema,
execute: async (params) => {
if (!apiKey) {
throw new Error('YDC_API_KEY is required');
}
const response = await callApiUtility({
params,
YDC_API_KEY: apiKey,
getUserAgent,
});
return response;
},
});
};
Input Schemas Enable Smart Queries
Always use schemas from @youdotcom-oss/mcp:
import { SearchQuerySchema } from '@youdotcom-oss/mcp';
export const youSearch = (config: YouToolsConfig = {}) => {
return tool({
description: '...',
inputSchema: SearchQuerySchema,
execute: async (params) => { ... },
});
};
const MySearchSchema = z.object({ query: z.string() });
Why this matters:
- Rich schemas enable AI to use advanced query parameters (filters, freshness, country, etc.)
- AI can construct more intelligent queries based on user intent
- Prevents duplicating schema definitions across packages
- Ensures consistency with MCP server schemas
API Key Handling
Always provide environment variable fallback and validate before API calls:
const apiKey = config.apiKey ?? process.env.YDC_API_KEY;
execute: async (params) => {
if (!apiKey) {
throw new Error('YDC_API_KEY is required');
}
const response = await callApi(...);
}
Response Format
Always return raw API response for maximum flexibility:
execute: async (params) => {
const response = await fetchSearchResults({
searchQuery: params,
YDC_API_KEY: apiKey,
getUserAgent,
});
return response;
}
return {
text: formatResponse(response),
data: response,
};
Why raw responses?
- Maximum flexibility for AI SDK to process results
- No information loss from formatting
- AI SDK handles presentation layer
- Easier to debug (see actual API response)
Tool Descriptions
Write descriptions that guide AI behavior:
description: 'Search the web for current information, news, articles, and content using You.com. Returns web results with snippets and news articles. Use this when you need up-to-date information or facts from the internet.'
description: 'Search the web'
Additional Resources