[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6N402Y59433TGHH0YNANN18":3,"skill-same:01M6N402Y59433TGHH0YNANN18":81},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":22,"publishedAt":43,"linkOnly":44,"markdownContent":45,"markdownBody":46,"frontMatter":47,"refName":54,"commitSha":55,"skillDirectory":56,"forksCount":57,"repositoryHtmlUrl":58,"repositoryHomepageUrl":6,"ownerHtmlUrl":59,"ownerBlogUrl":6,"ownerDescription":60,"updatedAt":61,"install":62,"resources":74},"01M6N402Y59433TGHH0YNANN18","ydc-ai-sdk-integration",null,"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.","Kernel8901\u002Fai-agent-skills-classification","Kernel8901","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F72647553?v=4","01M6KV388J2H5PNC8D8P940BJD","01M6KV38CS5B3AY63RKZB410YM",7,"MIT","https:\u002F\u002Fgithub.com\u002FKernel8901\u002Fai-agent-skills-classification\u002Fblob\u002Fmain\u002F人工智能与大型语言模型\u002Fydc-ai-sdk-integration\u002FSKILL.md",[17],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],"ydc ai sdk integration","integration","ai sdk","sdk","applications","you","pnpm","web-search","vercel ai sdk","integrate","vercel","node","web search","Tools","Citations","developer","search","openai","yarn","ai agent","2026-11-10 10:12:30",false,"---\nname: ydc-ai-sdk-integration\ndescription: 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.\nlicense: MIT\ncompatibility: Requires Node.js 18+ and npm\u002Fbun\u002Fyarn\u002Fpnpm\nmetadata:\n  author: youdotcom-oss\n  category: sdk-integration\n  version: \"1.0.0\"\n  keywords: vercel,vercel-ai-sdk,ai-sdk,you.com,integration,anthropic,openai,web-search,content-extraction,livecrawl,citations\n---\n\n# Integrate AI SDK with You.com Tools\n\nInteractive workflow to add You.com tools to your Vercel AI SDK application using `@youdotcom-oss\u002Fai-sdk-plugin`.\n\n## Workflow\n\n1. **Ask: Package Manager**\n   * Which package manager? (npm, bun, yarn, pnpm)\n   * Install package using their choice:\n     ```bash\n     npm install @youdotcom-oss\u002Fai-sdk-plugin\n     # or bun add @youdotcom-oss\u002Fai-sdk-plugin\n     # or yarn add @youdotcom-oss\u002Fai-sdk-plugin\n     # or pnpm add @youdotcom-oss\u002Fai-sdk-plugin\n     ```\n\n2. **Ask: Environment Variable Name**\n   * Using standard `YDC_API_KEY`?\n   * Or custom name? (if custom, get the name)\n   * Have they set it in their environment?\n   * If NO: Guide them to get key from https:\u002F\u002Fyou.com\u002Fplatform\u002Fapi-keys\n\n3. **Ask: Which AI SDK Functions?**\n   * Do they use `generateText()`?\n   * Do they use `streamText()`?\n   * Both?\n\n4. **Ask: Existing Files or New Files?**\n   * EXISTING: Ask which file(s) to edit\n   * NEW: Ask where to create file(s) and what to name them\n\n5. **For Each File, Ask:**\n   * Which tools to add?\n     - `youSearch` (web search)\n     - `youExpress` (AI agent)\n     - `youContents` (content extraction)\n     - Multiple? (which combination?)\n   * Using `generateText()` or `streamText()` in this file?\n   * Which AI provider model? (to determine if stopWhen needed)\n\n6. **Reference Integration Examples**\n\n   See \"Integration Examples\" section below for complete code patterns:\n   * generateText() - Basic text generation with tools\n   * streamText() - Streaming responses with web frameworks (Next.js, Express, React)\n\n7. **Update\u002FCreate Files**\n\n   For each file:\n   * Reference integration examples (generateText or streamText based on their answer)\n   * Add import for selected tools\n   * If EXISTING file: Find their generateText\u002FstreamText call and add tools object\n   * If NEW file: Create file with example structure\n   * Tool invocation pattern based on env var name:\n     - Standard `YDC_API_KEY`: `youSearch()`\n     - Custom name: `youSearch({ apiKey: process.env.CUSTOM_NAME })`\n   * Add selected tools to tools object\n   * If streamText + Anthropic: Add stopWhen parameter\n\n## Integration Examples\n\n### generateText() - Basic Text Generation\n\n**Environment Variables Setup:**\n```typescript\nimport { anthropic } from '@ai-sdk\u002Fanthropic';\nimport { generateText } from 'ai';\nimport { youContents, youExpress, youSearch } from '@youdotcom-oss\u002Fai-sdk-plugin';\n\n\u002F\u002F Reads YDC_API_KEY from environment automatically\nconst result = await generateText({\n  model: anthropic('claude-sonnet-4-5-20250929'),\n  tools: {\n    search: youSearch(),\n  },\n  prompt: 'What are the latest developments in quantum computing?',\n});\n\nconsole.log(result.text);\n```\n\n**Multiple Tools:**\n```typescript\nconst result = await generateText({\n  model: anthropic('claude-sonnet-4-5-20250929'),\n  tools: {\n    search: youSearch(),      \u002F\u002F Web search with citations\n    agent: youExpress(),      \u002F\u002F AI answers with web context\n    extract: youContents(),   \u002F\u002F Content extraction from URLs\n  },\n  prompt: 'Research quantum computing and summarize the key papers',\n});\n```\n\n**Custom API Key:**\n```typescript\nconst result = await generateText({\n  model: anthropic('claude-sonnet-4-5-20250929'),\n  tools: {\n    search: youSearch({ apiKey: 'your-custom-key' }),\n  },\n  prompt: 'Your prompt here',\n});\n```\n\n**Complete Example:**\n```typescript\nimport { anthropic } from '@ai-sdk\u002Fanthropic';\nimport { generateText } from 'ai';\nimport { youSearch } from '@youdotcom-oss\u002Fai-sdk-plugin';\n\nconst main = async () => {\n  try {\n    const result = await generateText({\n      model: anthropic('claude-sonnet-4-5-20250929'),\n      tools: {\n        search: youSearch(),\n      },\n      maxSteps: 5,\n      prompt: 'What are the latest developments in quantum computing?',\n    });\n\n    console.log('Generated text:', result.text);\n    console.log('\\nTool calls:', result.steps.flatMap(s => s.toolCalls));\n  } catch (error) {\n    console.error('Error:', error);\n    process.exit(1);\n  }\n};\n\nmain();\n```\n\n### streamText() - Streaming Responses\n\n**Basic Streaming with stopWhen Pattern:**\n```typescript\nimport { anthropic } from '@ai-sdk\u002Fanthropic';\nimport { streamText, type StepResult } from 'ai';\nimport { youSearch } from '@youdotcom-oss\u002Fai-sdk-plugin';\n\n\u002F\u002F CRITICAL: Always use stopWhen for Anthropic streaming\n\u002F\u002F Anthropic's SDK requires explicit stop conditions\nconst stepCountIs = (n: number) => (stepResult: StepResult\u003Cany>) =>\n  stepResult.stepNumber >= n;\n\nconst result = streamText({\n  model: anthropic('claude-sonnet-4-5-20250929'),\n  tools: { search: youSearch() },\n  stopWhen: stepCountIs(3),  \u002F\u002F Required for Anthropic\n  prompt: 'What are the latest AI developments?',\n});\n\n\u002F\u002F Consume stream\nfor await (const chunk of result.textStream) {\n  process.stdout.write(chunk);\n}\n```\n\n**Next.js Integration (App Router):**\n```typescript\n\u002F\u002F app\u002Fapi\u002Fchat\u002Froute.ts\nimport { anthropic } from '@ai-sdk\u002Fanthropic';\nimport { streamText, type StepResult } from 'ai';\nimport { youSearch } from '@youdotcom-oss\u002Fai-sdk-plugin';\n\nconst stepCountIs = (n: number) => (stepResult: StepResult\u003Cany>) =>\n  stepResult.stepNumber >= n;\n\nexport async function POST(req: Request) {\n  const { prompt } = await req.json();\n\n  const result = streamText({\n    model: anthropic('claude-sonnet-4-5-20250929'),\n    tools: { search: youSearch() },\n    stopWhen: stepCountIs(5),\n    prompt,\n  });\n\n  return result.toDataStreamResponse();\n}\n```\n\n**Express.js Integration:**\n```typescript\n\u002F\u002F server.ts\nimport express from 'express';\nimport { anthropic } from '@ai-sdk\u002Fanthropic';\nimport { streamText, type StepResult } from 'ai';\nimport { youSearch } from '@youdotcom-oss\u002Fai-sdk-plugin';\n\nconst app = express();\napp.use(express.json());\n\nconst stepCountIs = (n: number) => (stepResult: StepResult\u003Cany>) =>\n  stepResult.stepNumber >= n;\n\napp.post('\u002Fapi\u002Fchat', async (req, res) => {\n  const { prompt } = req.body;\n\n  const result = streamText({\n    model: anthropic('claude-sonnet-4-5-20250929'),\n    tools: { search: youSearch() },\n    stopWhen: stepCountIs(5),\n    prompt,\n  });\n\n  res.setHeader('Content-Type', 'text\u002Fplain; charset=utf-8');\n  res.setHeader('Transfer-Encoding', 'chunked');\n\n  for await (const chunk of result.textStream) {\n    res.write(chunk);\n  }\n\n  res.end();\n});\n\napp.listen(3000);\n```\n\n**React Client (with Next.js):**\n```typescript\n\u002F\u002F components\u002FChat.tsx\n'use client';\n\nimport { useChat } from 'ai\u002Freact';\n\nexport default function Chat() {\n  const { messages, input, handleInputChange, handleSubmit } = useChat({\n    api: '\u002Fapi\u002Fchat',\n  });\n\n  return (\n    \u003Cdiv>\n      {messages.map(m => (\n        \u003Cdiv key={m.id}>\n          \u003Cstrong>{m.role}:\u003C\u002Fstrong> {m.content}\n        \u003C\u002Fdiv>\n      ))}\n\n      \u003Cform onSubmit={handleSubmit}>\n        \u003Cinput value={input} onChange={handleInputChange} \u002F>\n        \u003Cbutton type=\"submit\">Send\u003C\u002Fbutton>\n      \u003C\u002Fform>\n    \u003C\u002Fdiv>\n  );\n}\n```\n\n**Complete Streaming Example:**\n```typescript\nimport { anthropic } from '@ai-sdk\u002Fanthropic';\nimport { streamText, type StepResult } from 'ai';\nimport { youSearch } from '@youdotcom-oss\u002Fai-sdk-plugin';\n\nconst stepCountIs = (n: number) => (stepResult: StepResult\u003Cany>) =>\n  stepResult.stepNumber >= n;\n\nconst main = async () => {\n  try {\n    const result = streamText({\n      model: anthropic('claude-sonnet-4-5-20250929'),\n      tools: {\n        search: youSearch(),\n      },\n      stopWhen: stepCountIs(3),\n      prompt: 'What are the latest AI developments?',\n    });\n\n    \u002F\u002F Stream to stdout\n    console.log('Streaming response:\\n');\n    for await (const chunk of result.textStream) {\n      process.stdout.write(chunk);\n    }\n    console.log('\\n\\nDone!');\n  } catch (error) {\n    console.error('Error:', error);\n    process.exit(1);\n  }\n};\n\nmain();\n```\n\n## Tool Invocation Patterns\n\nBased on env var name from step 2:\n\n**Standard YDC_API_KEY:**\n```typescript\nimport { youSearch } from '@youdotcom-oss\u002Fai-sdk-plugin';\n\ntools: {\n  search: youSearch(),\n}\n```\n\n**Custom env var:**\n```typescript\nimport { youSearch } from '@youdotcom-oss\u002Fai-sdk-plugin';\n\nconst apiKey = process.env.THEIR_CUSTOM_NAME;\n\ntools: {\n  search: youSearch({ apiKey }),\n}\n```\n\n**Multiple tools with standard env var:**\n```typescript\nimport { youSearch, youExpress, youContents } from '@youdotcom-oss\u002Fai-sdk-plugin';\n\ntools: {\n  search: youSearch(),\n  agent: youExpress(),\n  extract: youContents(),\n}\n```\n\n**Multiple tools with custom env var:**\n```typescript\nimport { youSearch, youExpress, youContents } from '@youdotcom-oss\u002Fai-sdk-plugin';\n\nconst apiKey = process.env.THEIR_CUSTOM_NAME;\n\ntools: {\n  search: youSearch({ apiKey }),\n  agent: youExpress({ apiKey }),\n  extract: youContents({ apiKey }),\n}\n```\n\n## Available Tools\n\n### youSearch\nWeb and news search - model determines parameters (query, count, country, etc.)\n\n### youExpress\nAI agent with web context - model determines parameters (input, tools)\n\n### youContents\nWeb page content extraction - model determines parameters (urls, format)\n\n## Key Integration Patterns\n\nThe examples above demonstrate:\n* Import statements (AI SDK + provider + You.com tools)\n* Env var validation (optional for new files)\n* Tool configuration based on env var\n* generateText\u002FstreamText usage with tools\n* Result handling (especially textStream destructuring for streamText)\n* Anthropic streaming pattern (stopWhen: stepCountIs(3))\n* Web framework integration (Next.js, Express, React)\n\n## Implementation Checklist\n\nFor each file being updated\u002Fcreated:\n\n- [ ] Import added for selected tools\n- [ ] If custom env var: Variable declared with correct name\n- [ ] tools object added to generateText\u002FstreamText\n- [ ] Each selected tool invoked correctly:\n  - Standard env: `toolName()`\n  - Custom env: `toolName({ apiKey })`\n- [ ] If streamText: Destructured `const { textStream } = ...`\n- [ ] If Anthropic + streamText: Added `stopWhen: stepCountIs(3)`\n\nGlobal checklist:\n\n- [ ] Package installed with their package manager\n- [ ] Env var set in their environment\n- [ ] All files updated\u002Fcreated\n- [ ] Ready to test\n\n## Common Issues\n\n**Issue**: \"Cannot find module @youdotcom-oss\u002Fai-sdk-plugin\"\n**Fix**: Install with their package manager\n\n**Issue**: \"YDC_API_KEY (or custom name) environment variable is required\"\n**Fix**: Set in their environment (get key: https:\u002F\u002Fyou.com\u002Fplatform\u002Fapi-keys)\n\n**Issue**: \"Tool execution fails with 401\"\n**Fix**: Verify API key is valid\n\n**Issue**: \"Incomplete or missing response\"\n**Fix**: If using streamText, increase the step count. Start with 3 and iterate up as needed (see README troubleshooting)\n\n**Issue**: \"textStream is not iterable\"\n**Fix**: Destructure: `const { textStream } = streamText(...)`\n\n**Issue**: \"Custom env var not working\"\n**Fix**: Pass to each tool: `youSearch({ apiKey })`\n\n## Advanced: Tool Development Patterns\n\nFor developers creating custom AI SDK tools or contributing to @youdotcom-oss\u002Fai-sdk-plugin:\n\n### Tool Function Structure\n\nEach tool function follows this pattern:\n\n```typescript\nexport const youToolName = (config: YouToolsConfig = {}) => {\n  const apiKey = config.apiKey ?? process.env.YDC_API_KEY;\n\n  return tool({\n    description: 'Tool description for AI model',\n    inputSchema: ZodSchema,\n    execute: async (params) => {\n      if (!apiKey) {\n        throw new Error('YDC_API_KEY is required');\n      }\n\n      const response = await callApiUtility({\n        params,\n        YDC_API_KEY: apiKey,\n        getUserAgent,\n      });\n\n      \u002F\u002F Return raw API response for maximum flexibility\n      return response;\n    },\n  });\n};\n```\n\n### Input Schemas Enable Smart Queries\n\nAlways use schemas from `@youdotcom-oss\u002Fmcp`:\n\n```typescript\n\u002F\u002F ✅ Import from @youdotcom-oss\u002Fmcp\nimport { SearchQuerySchema } from '@youdotcom-oss\u002Fmcp';\n\nexport const youSearch = (config: YouToolsConfig = {}) => {\n  return tool({\n    description: '...',\n    inputSchema: SearchQuerySchema,  \u002F\u002F Enables AI to use all search parameters\n    execute: async (params) => { ... },\n  });\n};\n\n\u002F\u002F ❌ Don't duplicate or simplify schemas\nconst MySearchSchema = z.object({ query: z.string() });  \u002F\u002F Missing filters!\n```\n\n**Why this matters:**\n- Rich schemas enable AI to use advanced query parameters (filters, freshness, country, etc.)\n- AI can construct more intelligent queries based on user intent\n- Prevents duplicating schema definitions across packages\n- Ensures consistency with MCP server schemas\n\n### API Key Handling\n\nAlways provide environment variable fallback and validate before API calls:\n\n```typescript\n\u002F\u002F ✅ Automatic environment variable fallback\nconst apiKey = config.apiKey ?? process.env.YDC_API_KEY;\n\n\u002F\u002F ✅ Check API key in execute function\nexecute: async (params) => {\n  if (!apiKey) {\n    throw new Error('YDC_API_KEY is required');\n  }\n  const response = await callApi(...);\n}\n```\n\n### Response Format\n\nAlways return raw API response for maximum flexibility:\n\n```typescript\n\u002F\u002F ✅ Return raw API response\nexecute: async (params) => {\n  const response = await fetchSearchResults({\n    searchQuery: params,\n    YDC_API_KEY: apiKey,\n    getUserAgent,\n  });\n\n  return response;  \u002F\u002F Raw response for maximum flexibility\n}\n\n\u002F\u002F ❌ Don't format or transform responses\nreturn {\n  text: formatResponse(response),\n  data: response,\n};\n```\n\n**Why raw responses?**\n- Maximum flexibility for AI SDK to process results\n- No information loss from formatting\n- AI SDK handles presentation layer\n- Easier to debug (see actual API response)\n\n### Tool Descriptions\n\nWrite descriptions that guide AI behavior:\n\n```typescript\n\u002F\u002F ✅ Clear guidance for AI model\ndescription: '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.'\n\n\u002F\u002F ❌ Too brief\ndescription: 'Search the web'\n```\n\n## Additional Resources\n\n* Package README: https:\u002F\u002Fgithub.com\u002Fyoudotcom-oss\u002Fdx-toolkit\u002Ftree\u002Fmain\u002Fpackages\u002Fai-sdk-plugin\n* Vercel AI SDK Docs: https:\u002F\u002Fai-sdk.dev\u002Fdocs\n* You.com API: https:\u002F\u002Fyou.com\u002Fplatform\u002Fapi-keys\n","# Integrate AI SDK with You.com Tools\n\nInteractive workflow to add You.com tools to your Vercel AI SDK application using `@youdotcom-oss\u002Fai-sdk-plugin`.\n\n## Workflow\n\n1. **Ask: Package Manager**\n   * Which package manager? (npm, bun, yarn, pnpm)\n   * Install package using their choice:\n     ```bash\n     npm install @youdotcom-oss\u002Fai-sdk-plugin\n     # or bun add @youdotcom-oss\u002Fai-sdk-plugin\n     # or yarn add @youdotcom-oss\u002Fai-sdk-plugin\n     # or pnpm add @youdotcom-oss\u002Fai-sdk-plugin\n     ```\n\n2. **Ask: Environment Variable Name**\n   * Using standard `YDC_API_KEY`?\n   * Or custom name? (if custom, get the name)\n   * Have they set it in their environment?\n   * If NO: Guide them to get key from https:\u002F\u002Fyou.com\u002Fplatform\u002Fapi-keys\n\n3. **Ask: Which AI SDK Functions?**\n   * Do they use `generateText()`?\n   * Do they use `streamText()`?\n   * Both?\n\n4. **Ask: Existing Files or New Files?**\n   * EXISTING: Ask which file(s) to edit\n   * NEW: Ask where to create file(s) and what to name them\n\n5. **For Each File, Ask:**\n   * Which tools to add?\n     - `youSearch` (web search)\n     - `youExpress` (AI agent)\n     - `youContents` (content extraction)\n     - Multiple? (which combination?)\n   * Using `generateText()` or `streamText()` in this file?\n   * Which AI provider model? (to determine if stopWhen needed)\n\n6. **Reference Integration Examples**\n\n   See \"Integration Examples\" section below for complete code patterns:\n   * generateText() - Basic text generation with tools\n   * streamText() - Streaming responses with web frameworks (Next.js, Express, React)\n\n7. **Update\u002FCreate Files**\n\n   For each file:\n   * Reference integration examples (generateText or streamText based on their answer)\n   * Add import for selected tools\n   * If EXISTING file: Find their generateText\u002FstreamText call and add tools object\n   * If NEW file: Create file with example structure\n   * Tool invocation pattern based on env var name:\n     - Standard `YDC_API_KEY`: `youSearch()`\n     - Custom name: `youSearch({ apiKey: process.env.CUSTOM_NAME })`\n   * Add selected tools to tools object\n   * If streamText + Anthropic: Add stopWhen parameter\n\n## Integration Examples\n\n### generateText() - Basic Text Generation\n\n**Environment Variables Setup:**\n```typescript\nimport { anthropic } from '@ai-sdk\u002Fanthropic';\nimport { generateText } from 'ai';\nimport { youContents, youExpress, youSearch } from '@youdotcom-oss\u002Fai-sdk-plugin';\n\n\u002F\u002F Reads YDC_API_KEY from environment automatically\nconst result = await generateText({\n  model: anthropic('claude-sonnet-4-5-20250929'),\n  tools: {\n    search: youSearch(),\n  },\n  prompt: 'What are the latest developments in quantum computing?',\n});\n\nconsole.log(result.text);\n```\n\n**Multiple Tools:**\n```typescript\nconst result = await generateText({\n  model: anthropic('claude-sonnet-4-5-20250929'),\n  tools: {\n    search: youSearch(),      \u002F\u002F Web search with citations\n    agent: youExpress(),      \u002F\u002F AI answers with web context\n    extract: youContents(),   \u002F\u002F Content extraction from URLs\n  },\n  prompt: 'Research quantum computing and summarize the key papers',\n});\n```\n\n**Custom API Key:**\n```typescript\nconst result = await generateText({\n  model: anthropic('claude-sonnet-4-5-20250929'),\n  tools: {\n    search: youSearch({ apiKey: 'your-custom-key' }),\n  },\n  prompt: 'Your prompt here',\n});\n```\n\n**Complete Example:**\n```typescript\nimport { anthropic } from '@ai-sdk\u002Fanthropic';\nimport { generateText } from 'ai';\nimport { youSearch } from '@youdotcom-oss\u002Fai-sdk-plugin';\n\nconst main = async () => {\n  try {\n    const result = await generateText({\n      model: anthropic('claude-sonnet-4-5-20250929'),\n      tools: {\n        search: youSearch(),\n      },\n      maxSteps: 5,\n      prompt: 'What are the latest developments in quantum computing?',\n    });\n\n    console.log('Generated text:', result.text);\n    console.log('\\nTool calls:', result.steps.flatMap(s => s.toolCalls));\n  } catch (error) {\n    console.error('Error:', error);\n    process.exit(1);\n  }\n};\n\nmain();\n```\n\n### streamText() - Streaming Responses\n\n**Basic Streaming with stopWhen Pattern:**\n```typescript\nimport { anthropic } from '@ai-sdk\u002Fanthropic';\nimport { streamText, type StepResult } from 'ai';\nimport { youSearch } from '@youdotcom-oss\u002Fai-sdk-plugin';\n\n\u002F\u002F CRITICAL: Always use stopWhen for Anthropic streaming\n\u002F\u002F Anthropic's SDK requires explicit stop conditions\nconst stepCountIs = (n: number) => (stepResult: StepResult\u003Cany>) =>\n  stepResult.stepNumber >= n;\n\nconst result = streamText({\n  model: anthropic('claude-sonnet-4-5-20250929'),\n  tools: { search: youSearch() },\n  stopWhen: stepCountIs(3),  \u002F\u002F Required for Anthropic\n  prompt: 'What are the latest AI developments?',\n});\n\n\u002F\u002F Consume stream\nfor await (const chunk of result.textStream) {\n  process.stdout.write(chunk);\n}\n```\n\n**Next.js Integration (App Router):**\n```typescript\n\u002F\u002F app\u002Fapi\u002Fchat\u002Froute.ts\nimport { anthropic } from '@ai-sdk\u002Fanthropic';\nimport { streamText, type StepResult } from 'ai';\nimport { youSearch } from '@youdotcom-oss\u002Fai-sdk-plugin';\n\nconst stepCountIs = (n: number) => (stepResult: StepResult\u003Cany>) =>\n  stepResult.stepNumber >= n;\n\nexport async function POST(req: Request) {\n  const { prompt } = await req.json();\n\n  const result = streamText({\n    model: anthropic('claude-sonnet-4-5-20250929'),\n    tools: { search: youSearch() },\n    stopWhen: stepCountIs(5),\n    prompt,\n  });\n\n  return result.toDataStreamResponse();\n}\n```\n\n**Express.js Integration:**\n```typescript\n\u002F\u002F server.ts\nimport express from 'express';\nimport { anthropic } from '@ai-sdk\u002Fanthropic';\nimport { streamText, type StepResult } from 'ai';\nimport { youSearch } from '@youdotcom-oss\u002Fai-sdk-plugin';\n\nconst app = express();\napp.use(express.json());\n\nconst stepCountIs = (n: number) => (stepResult: StepResult\u003Cany>) =>\n  stepResult.stepNumber >= n;\n\napp.post('\u002Fapi\u002Fchat', async (req, res) => {\n  const { prompt } = req.body;\n\n  const result = streamText({\n    model: anthropic('claude-sonnet-4-5-20250929'),\n    tools: { search: youSearch() },\n    stopWhen: stepCountIs(5),\n    prompt,\n  });\n\n  res.setHeader('Content-Type', 'text\u002Fplain; charset=utf-8');\n  res.setHeader('Transfer-Encoding', 'chunked');\n\n  for await (const chunk of result.textStream) {\n    res.write(chunk);\n  }\n\n  res.end();\n});\n\napp.listen(3000);\n```\n\n**React Client (with Next.js):**\n```typescript\n\u002F\u002F components\u002FChat.tsx\n'use client';\n\nimport { useChat } from 'ai\u002Freact';\n\nexport default function Chat() {\n  const { messages, input, handleInputChange, handleSubmit } = useChat({\n    api: '\u002Fapi\u002Fchat',\n  });\n\n  return (\n    \u003Cdiv>\n      {messages.map(m => (\n        \u003Cdiv key={m.id}>\n          \u003Cstrong>{m.role}:\u003C\u002Fstrong> {m.content}\n        \u003C\u002Fdiv>\n      ))}\n\n      \u003Cform onSubmit={handleSubmit}>\n        \u003Cinput value={input} onChange={handleInputChange} \u002F>\n        \u003Cbutton type=\"submit\">Send\u003C\u002Fbutton>\n      \u003C\u002Fform>\n    \u003C\u002Fdiv>\n  );\n}\n```\n\n**Complete Streaming Example:**\n```typescript\nimport { anthropic } from '@ai-sdk\u002Fanthropic';\nimport { streamText, type StepResult } from 'ai';\nimport { youSearch } from '@youdotcom-oss\u002Fai-sdk-plugin';\n\nconst stepCountIs = (n: number) => (stepResult: StepResult\u003Cany>) =>\n  stepResult.stepNumber >= n;\n\nconst main = async () => {\n  try {\n    const result = streamText({\n      model: anthropic('claude-sonnet-4-5-20250929'),\n      tools: {\n        search: youSearch(),\n      },\n      stopWhen: stepCountIs(3),\n      prompt: 'What are the latest AI developments?',\n    });\n\n    \u002F\u002F Stream to stdout\n    console.log('Streaming response:\\n');\n    for await (const chunk of result.textStream) {\n      process.stdout.write(chunk);\n    }\n    console.log('\\n\\nDone!');\n  } catch (error) {\n    console.error('Error:', error);\n    process.exit(1);\n  }\n};\n\nmain();\n```\n\n## Tool Invocation Patterns\n\nBased on env var name from step 2:\n\n**Standard YDC_API_KEY:**\n```typescript\nimport { youSearch } from '@youdotcom-oss\u002Fai-sdk-plugin';\n\ntools: {\n  search: youSearch(),\n}\n```\n\n**Custom env var:**\n```typescript\nimport { youSearch } from '@youdotcom-oss\u002Fai-sdk-plugin';\n\nconst apiKey = process.env.THEIR_CUSTOM_NAME;\n\ntools: {\n  search: youSearch({ apiKey }),\n}\n```\n\n**Multiple tools with standard env var:**\n```typescript\nimport { youSearch, youExpress, youContents } from '@youdotcom-oss\u002Fai-sdk-plugin';\n\ntools: {\n  search: youSearch(),\n  agent: youExpress(),\n  extract: youContents(),\n}\n```\n\n**Multiple tools with custom env var:**\n```typescript\nimport { youSearch, youExpress, youContents } from '@youdotcom-oss\u002Fai-sdk-plugin';\n\nconst apiKey = process.env.THEIR_CUSTOM_NAME;\n\ntools: {\n  search: youSearch({ apiKey }),\n  agent: youExpress({ apiKey }),\n  extract: youContents({ apiKey }),\n}\n```\n\n## Available Tools\n\n### youSearch\nWeb and news search - model determines parameters (query, count, country, etc.)\n\n### youExpress\nAI agent with web context - model determines parameters (input, tools)\n\n### youContents\nWeb page content extraction - model determines parameters (urls, format)\n\n## Key Integration Patterns\n\nThe examples above demonstrate:\n* Import statements (AI SDK + provider + You.com tools)\n* Env var validation (optional for new files)\n* Tool configuration based on env var\n* generateText\u002FstreamText usage with tools\n* Result handling (especially textStream destructuring for streamText)\n* Anthropic streaming pattern (stopWhen: stepCountIs(3))\n* Web framework integration (Next.js, Express, React)\n\n## Implementation Checklist\n\nFor each file being updated\u002Fcreated:\n\n- [ ] Import added for selected tools\n- [ ] If custom env var: Variable declared with correct name\n- [ ] tools object added to generateText\u002FstreamText\n- [ ] Each selected tool invoked correctly:\n  - Standard env: `toolName()`\n  - Custom env: `toolName({ apiKey })`\n- [ ] If streamText: Destructured `const { textStream } = ...`\n- [ ] If Anthropic + streamText: Added `stopWhen: stepCountIs(3)`\n\nGlobal checklist:\n\n- [ ] Package installed with their package manager\n- [ ] Env var set in their environment\n- [ ] All files updated\u002Fcreated\n- [ ] Ready to test\n\n## Common Issues\n\n**Issue**: \"Cannot find module @youdotcom-oss\u002Fai-sdk-plugin\"\n**Fix**: Install with their package manager\n\n**Issue**: \"YDC_API_KEY (or custom name) environment variable is required\"\n**Fix**: Set in their environment (get key: https:\u002F\u002Fyou.com\u002Fplatform\u002Fapi-keys)\n\n**Issue**: \"Tool execution fails with 401\"\n**Fix**: Verify API key is valid\n\n**Issue**: \"Incomplete or missing response\"\n**Fix**: If using streamText, increase the step count. Start with 3 and iterate up as needed (see README troubleshooting)\n\n**Issue**: \"textStream is not iterable\"\n**Fix**: Destructure: `const { textStream } = streamText(...)`\n\n**Issue**: \"Custom env var not working\"\n**Fix**: Pass to each tool: `youSearch({ apiKey })`\n\n## Advanced: Tool Development Patterns\n\nFor developers creating custom AI SDK tools or contributing to @youdotcom-oss\u002Fai-sdk-plugin:\n\n### Tool Function Structure\n\nEach tool function follows this pattern:\n\n```typescript\nexport const youToolName = (config: YouToolsConfig = {}) => {\n  const apiKey = config.apiKey ?? process.env.YDC_API_KEY;\n\n  return tool({\n    description: 'Tool description for AI model',\n    inputSchema: ZodSchema,\n    execute: async (params) => {\n      if (!apiKey) {\n        throw new Error('YDC_API_KEY is required');\n      }\n\n      const response = await callApiUtility({\n        params,\n        YDC_API_KEY: apiKey,\n        getUserAgent,\n      });\n\n      \u002F\u002F Return raw API response for maximum flexibility\n      return response;\n    },\n  });\n};\n```\n\n### Input Schemas Enable Smart Queries\n\nAlways use schemas from `@youdotcom-oss\u002Fmcp`:\n\n```typescript\n\u002F\u002F ✅ Import from @youdotcom-oss\u002Fmcp\nimport { SearchQuerySchema } from '@youdotcom-oss\u002Fmcp';\n\nexport const youSearch = (config: YouToolsConfig = {}) => {\n  return tool({\n    description: '...',\n    inputSchema: SearchQuerySchema,  \u002F\u002F Enables AI to use all search parameters\n    execute: async (params) => { ... },\n  });\n};\n\n\u002F\u002F ❌ Don't duplicate or simplify schemas\nconst MySearchSchema = z.object({ query: z.string() });  \u002F\u002F Missing filters!\n```\n\n**Why this matters:**\n- Rich schemas enable AI to use advanced query parameters (filters, freshness, country, etc.)\n- AI can construct more intelligent queries based on user intent\n- Prevents duplicating schema definitions across packages\n- Ensures consistency with MCP server schemas\n\n### API Key Handling\n\nAlways provide environment variable fallback and validate before API calls:\n\n```typescript\n\u002F\u002F ✅ Automatic environment variable fallback\nconst apiKey = config.apiKey ?? process.env.YDC_API_KEY;\n\n\u002F\u002F ✅ Check API key in execute function\nexecute: async (params) => {\n  if (!apiKey) {\n    throw new Error('YDC_API_KEY is required');\n  }\n  const response = await callApi(...);\n}\n```\n\n### Response Format\n\nAlways return raw API response for maximum flexibility:\n\n```typescript\n\u002F\u002F ✅ Return raw API response\nexecute: async (params) => {\n  const response = await fetchSearchResults({\n    searchQuery: params,\n    YDC_API_KEY: apiKey,\n    getUserAgent,\n  });\n\n  return response;  \u002F\u002F Raw response for maximum flexibility\n}\n\n\u002F\u002F ❌ Don't format or transform responses\nreturn {\n  text: formatResponse(response),\n  data: response,\n};\n```\n\n**Why raw responses?**\n- Maximum flexibility for AI SDK to process results\n- No information loss from formatting\n- AI SDK handles presentation layer\n- Easier to debug (see actual API response)\n\n### Tool Descriptions\n\nWrite descriptions that guide AI behavior:\n\n```typescript\n\u002F\u002F ✅ Clear guidance for AI model\ndescription: '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.'\n\n\u002F\u002F ❌ Too brief\ndescription: 'Search the web'\n```\n\n## Additional Resources\n\n* Package README: https:\u002F\u002Fgithub.com\u002Fyoudotcom-oss\u002Fdx-toolkit\u002Ftree\u002Fmain\u002Fpackages\u002Fai-sdk-plugin\n* Vercel AI SDK Docs: https:\u002F\u002Fai-sdk.dev\u002Fdocs\n* You.com API: https:\u002F\u002Fyou.com\u002Fplatform\u002Fapi-keys\n",{"name":5,"license":14,"metadata":48,"description":7,"compatibility":53},{"author":49,"version":50,"category":51,"keywords":52},"youdotcom-oss","1.0.0","sdk-integration","vercel,vercel-ai-sdk,ai-sdk,you.com,integration,anthropic,openai,web-search,content-extraction,livecrawl,citations","Requires Node.js 18+ and npm\u002Fbun\u002Fyarn\u002Fpnpm","main","f4cb2d49f7667e79ef7804f50396d5aaffdf1f56","人工智能与大型语言模型\u002Fydc-ai-sdk-integration",1,"https:\u002F\u002Fgithub.com\u002FKernel8901\u002Fai-agent-skills-classification","https:\u002F\u002Fgithub.com\u002FKernel8901","a little little little dobe in life but science geek","2026-04-05 16:43:56",{"source":8,"skillName":5,"commands":63,"prompt":72,"zipAvailable":73},[64,67,70],{"tool":65,"command":66},"npx","npx skills add Kernel8901\u002Fai-agent-skills-classification --skill ydc-ai-sdk-integration",{"tool":68,"command":69},"bunx","bunx skills add Kernel8901\u002Fai-agent-skills-classification --skill ydc-ai-sdk-integration",{"tool":29,"command":71},"pnpm dlx skills add Kernel8901\u002Fai-agent-skills-classification --skill ydc-ai-sdk-integration","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FKernel8901\u002Fai-agent-skills-classification\u002Fblob\u002Fmain\u002F人工智能与大型语言模型\u002Fydc-ai-sdk-integration\u002FSKILL.md",true,[75],{"path":76,"resourceType":77,"resourceTypeDesc":78,"sizeBytes":79,"sourceHtmlUrl":80},"_meta.json","REFERENCE","参考文档",324,"https:\u002F\u002Fgithub.com\u002FKernel8901\u002Fai-agent-skills-classification\u002Fblob\u002Fmain\u002F人工智能与大型语言模型\u002Fydc-ai-sdk-integration\u002F_meta.json",[82,106,138,149,159,189],{"skillNo":83,"name":84,"nameZh":6,"description":85,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":86,"categories":87,"keywords":88,"publishedAt":43},"01M6Q5R6WZ06RRB9RQTW54B34B","zyfai","Earn yield on any Ethereum wallet on Base, Arbitrum, and Plasma. Use when a user wants passive DeFi yield on their funds. Deploys a non-custodial subaccount (Safe) linked to their EOA, enables automated yield optimization, and lets them deposit\u002Fwithdraw anytime.","https:\u002F\u002Fgithub.com\u002FKernel8901\u002Fai-agent-skills-classification\u002Fblob\u002Fmain\u002F金融\u002Fzyfai-sdk\u002FSKILL.md",[],[84,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105],"safe","ethereum","defi","Optimization","user","use","Wallet","base","deposit","withdraw","yield","arbitrum","non-custodial","passive","defi yield","earn","yield optimization",{"skillNo":107,"name":108,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":109,"categories":110,"keywords":120,"publishedAt":43},"01M6Q5R337B5JSNER4P4YS03TN","zerion-api","https:\u002F\u002Fgithub.com\u002FKernel8901\u002Fai-agent-skills-classification\u002Fblob\u002Fmain\u002F金融\u002Fzerion-api\u002FSKILL.md",[111,116,119],{"categoryNo":112,"categoryName":113,"taxonomyType":114,"taxonomyTypeDesc":115},"01JBSEEDCAT000000000000010","后端与接口","SCENARIO","使用场景",{"categoryNo":117,"categoryName":118,"taxonomyType":114,"taxonomyTypeDesc":115},"01JBSEEDCAT000000000000023","Skill与智能体开发",{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},[121,122,123,124,125,126,127,91,128,95,129,130,131,132,133,134,135,136,137],"api","zerion api","zerion","MCP","mcp server","server","blockchain","transactions","crypto wallet","crypto","evm","solana","query","across","positions","token","prices",{"skillNo":139,"name":140,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":141,"categories":142,"keywords":146,"publishedAt":43},"01M6Q5QZFYTDAZMZ27BN5VZXAR","zerion-api-skill","https:\u002F\u002Fgithub.com\u002FKernel8901\u002Fai-agent-skills-classification\u002Fblob\u002Fmain\u002F金融\u002Fzerion-api-skill\u002FSKILL.md",[143,144,145],{"categoryNo":112,"categoryName":113,"taxonomyType":114,"taxonomyTypeDesc":115},{"categoryNo":117,"categoryName":118,"taxonomyType":114,"taxonomyTypeDesc":115},{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},[121,147,148,122,123,124,125,126,127,91,128,95,130,131,132,133,134,135,136,137],"api skill","zerion api skill",{"skillNo":150,"name":151,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":152,"categories":153,"keywords":157,"publishedAt":43},"01M6Q5QW17QW98RA3FE45E4RD8","zerion-api-mcp","https:\u002F\u002Fgithub.com\u002FKernel8901\u002Fai-agent-skills-classification\u002Fblob\u002Fmain\u002F金融\u002Fzerion-api-mcp\u002FSKILL.md",[154,155,156],{"categoryNo":112,"categoryName":113,"taxonomyType":114,"taxonomyTypeDesc":115},{"categoryNo":117,"categoryName":118,"taxonomyType":114,"taxonomyTypeDesc":115},{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},[124,121,158,122,123,125,126,91,128,95,129,130,131,132,133,134,135,136,137],"zerion api mcp",{"skillNo":160,"name":161,"nameZh":6,"description":162,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":163,"categories":164,"keywords":168,"publishedAt":43},"01M6Q5QQYZB7A501BDEQWKGSJT","yahoo-finance-forex","Fetches real-time FOREX news and market data from Yahoo Finance for major currency pairs (EUR\u002FUSD, GBP\u002FUSD, USD\u002FJPY, etc.). Analyzes sentiment and provides trading context.","https:\u002F\u002Fgithub.com\u002FKernel8901\u002Fai-agent-skills-classification\u002Fblob\u002Fmain\u002F金融\u002Fyahoo-finance-forex\u002FSKILL.md",[165],{"categoryNo":166,"categoryName":167,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000040","财务",[169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188],"finance","yahoo finance","forex","yahoo","yahoo finance forex","github","https","sentiment","real-time","python3","install","Market","usd","news","time","currency","gbp","pip","market data","for",{"skillNo":190,"name":191,"nameZh":6,"description":192,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":193,"categories":194,"keywords":196,"publishedAt":43},"01M6Q5QM6VS84WZVM7BKXXPF32","yahoo-finance","This skill should be used when the user asks to \"get stock prices\", \"check stock quotes\", \"look up earnings\", \"get financial data\", \"find trending stocks\", or needs stock market data from Yahoo Finance.","https:\u002F\u002Fgithub.com\u002FKernel8901\u002Fai-agent-skills-classification\u002Fblob\u002Fmain\u002F金融\u002Fyahoo-finance-cli\u002FSKILL.md",[195],{"categoryNo":166,"categoryName":167,"taxonomyType":20,"taxonomyTypeDesc":21},[169,170,172,197,198,199,200,201,202,180,203,204,205,206,207,208,209,210,137,187],"cli","homebrew","find","check","brew","up","local","get","stock","link","trending","sf","quotes","ln"]