{
  "schemaVersion": "1.0",
  "item": {
    "slug": "ydc-ai-sdk-integration",
    "name": "Integrate You.com web tools with Vercel AI SDK",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/EdwardIrby/ydc-ai-sdk-integration",
    "canonicalUrl": "https://clawhub.ai/EdwardIrby/ydc-ai-sdk-integration",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/ydc-ai-sdk-integration",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=ydc-ai-sdk-integration",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "SKILL.md"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/ydc-ai-sdk-integration"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/ydc-ai-sdk-integration",
    "agentPageUrl": "https://openagent3.xyz/skills/ydc-ai-sdk-integration/agent",
    "manifestUrl": "https://openagent3.xyz/skills/ydc-ai-sdk-integration/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/ydc-ai-sdk-integration/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Integrate AI SDK with You.com Tools",
        "body": "Interactive workflow to add You.com tools to your Vercel AI SDK application using @youdotcom-oss/ai-sdk-plugin."
      },
      {
        "title": "Workflow",
        "body": "Ask: Package Manager\n\nWhich package manager? (npm, bun, yarn, pnpm)\nInstall package using their choice:\nnpm install @youdotcom-oss/ai-sdk-plugin\n# or bun add @youdotcom-oss/ai-sdk-plugin\n# or yarn add @youdotcom-oss/ai-sdk-plugin\n# or pnpm add @youdotcom-oss/ai-sdk-plugin\n\n\n\n\n\nAsk: Environment Variable Name\n\nUsing standard YDC_API_KEY?\nOr custom name? (if custom, get the name)\nHave they set it in their environment?\nIf NO: Guide them to get key from https://you.com/platform/api-keys\n\n\n\nAsk: Which AI SDK Functions?\n\nDo they use generateText()?\nDo they use streamText()?\nBoth?\n\n\n\nAsk: Existing Files or New Files?\n\nEXISTING: Ask which file(s) to edit\nNEW: Ask where to create file(s) and what to name them\n\n\n\nFor Each File, Ask:\n\nWhich tools to add?\n\nyouSearch (web search)\nyouExpress (AI agent)\nyouContents (content extraction)\nMultiple? (which combination?)\n\n\nUsing generateText() or streamText() in this file?\nWhich AI provider model? (to determine if stopWhen needed)\n\n\n\nReference Integration Examples\nSee \"Integration Examples\" section below for complete code patterns:\n\ngenerateText() - Basic text generation with tools\nstreamText() - Streaming responses with web frameworks (Next.js, Express, React)\n\n\n\nUpdate/Create Files\nFor each file:\n\nReference integration examples (generateText or streamText based on their answer)\nAdd import for selected tools\nIf EXISTING file: Find their generateText/streamText call and add tools object\nIf NEW file: Create file with example structure\nTool invocation pattern based on env var name:\n\nStandard YDC_API_KEY: youSearch()\nCustom name: youSearch({ apiKey: process.env.CUSTOM_NAME })\n\n\nAdd selected tools to tools object\nIf streamText + Anthropic: Add stopWhen parameter"
      },
      {
        "title": "generateText() - Basic Text Generation",
        "body": "Environment Variables Setup:\n\nimport { anthropic } from '@ai-sdk/anthropic';\nimport { generateText } from 'ai';\nimport { youContents, youExpress, youSearch } from '@youdotcom-oss/ai-sdk-plugin';\n\n// 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\nMultiple Tools:\n\nconst result = await generateText({\n  model: anthropic('claude-sonnet-4-5-20250929'),\n  tools: {\n    search: youSearch(),      // Web search with citations\n    agent: youExpress(),      // AI answers with web context\n    extract: youContents(),   // Content extraction from URLs\n  },\n  prompt: 'Research quantum computing and summarize the key papers',\n});\n\nCustom API Key:\n\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\nComplete Example:\n\nimport { anthropic } from '@ai-sdk/anthropic';\nimport { generateText } from 'ai';\nimport { youSearch } from '@youdotcom-oss/ai-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();"
      },
      {
        "title": "streamText() - Streaming Responses",
        "body": "Basic Streaming with stopWhen Pattern:\n\nimport { anthropic } from '@ai-sdk/anthropic';\nimport { streamText, type StepResult } from 'ai';\nimport { youSearch } from '@youdotcom-oss/ai-sdk-plugin';\n\n// CRITICAL: Always use stopWhen for Anthropic streaming\n// Anthropic's SDK requires explicit stop conditions\nconst stepCountIs = (n: number) => (stepResult: StepResult<any>) =>\n  stepResult.stepNumber >= n;\n\nconst result = streamText({\n  model: anthropic('claude-sonnet-4-5-20250929'),\n  tools: { search: youSearch() },\n  stopWhen: stepCountIs(3),  // Required for Anthropic\n  prompt: 'What are the latest AI developments?',\n});\n\n// Consume stream\nfor await (const chunk of result.textStream) {\n  process.stdout.write(chunk);\n}\n\nNext.js Integration (App Router):\n\n// app/api/chat/route.ts\nimport { anthropic } from '@ai-sdk/anthropic';\nimport { streamText, type StepResult } from 'ai';\nimport { youSearch } from '@youdotcom-oss/ai-sdk-plugin';\n\nconst stepCountIs = (n: number) => (stepResult: StepResult<any>) =>\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\nExpress.js Integration:\n\n// server.ts\nimport express from 'express';\nimport { anthropic } from '@ai-sdk/anthropic';\nimport { streamText, type StepResult } from 'ai';\nimport { youSearch } from '@youdotcom-oss/ai-sdk-plugin';\n\nconst app = express();\napp.use(express.json());\n\nconst stepCountIs = (n: number) => (stepResult: StepResult<any>) =>\n  stepResult.stepNumber >= n;\n\napp.post('/api/chat', 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/plain; 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\nReact Client (with Next.js):\n\n// components/Chat.tsx\n'use client';\n\nimport { useChat } from 'ai/react';\n\nexport default function Chat() {\n  const { messages, input, handleInputChange, handleSubmit } = useChat({\n    api: '/api/chat',\n  });\n\n  return (\n    <div>\n      {messages.map(m => (\n        <div key={m.id}>\n          <strong>{m.role}:</strong> {m.content}\n        </div>\n      ))}\n\n      <form onSubmit={handleSubmit}>\n        <input value={input} onChange={handleInputChange} />\n        <button type=\"submit\">Send</button>\n      </form>\n    </div>\n  );\n}\n\nComplete Streaming Example:\n\nimport { anthropic } from '@ai-sdk/anthropic';\nimport { streamText, type StepResult } from 'ai';\nimport { youSearch } from '@youdotcom-oss/ai-sdk-plugin';\n\nconst stepCountIs = (n: number) => (stepResult: StepResult<any>) =>\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    // 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();"
      },
      {
        "title": "Tool Invocation Patterns",
        "body": "Based on env var name from step 2:\n\nStandard YDC_API_KEY:\n\nimport { youSearch } from '@youdotcom-oss/ai-sdk-plugin';\n\ntools: {\n  search: youSearch(),\n}\n\nCustom env var:\n\nimport { youSearch } from '@youdotcom-oss/ai-sdk-plugin';\n\nconst apiKey = process.env.THEIR_CUSTOM_NAME;\n\ntools: {\n  search: youSearch({ apiKey }),\n}\n\nMultiple tools with standard env var:\n\nimport { youSearch, youExpress, youContents } from '@youdotcom-oss/ai-sdk-plugin';\n\ntools: {\n  search: youSearch(),\n  agent: youExpress(),\n  extract: youContents(),\n}\n\nMultiple tools with custom env var:\n\nimport { youSearch, youExpress, youContents } from '@youdotcom-oss/ai-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}"
      },
      {
        "title": "youSearch",
        "body": "Web and news search - model determines parameters (query, count, country, etc.)"
      },
      {
        "title": "youExpress",
        "body": "AI agent with web context - model determines parameters (input, tools)"
      },
      {
        "title": "youContents",
        "body": "Web page content extraction - model determines parameters (urls, format)"
      },
      {
        "title": "Key Integration Patterns",
        "body": "The examples above demonstrate:\n\nImport statements (AI SDK + provider + You.com tools)\nEnv var validation (optional for new files)\nTool configuration based on env var\ngenerateText/streamText usage with tools\nResult handling (especially textStream destructuring for streamText)\nAnthropic streaming pattern (stopWhen: stepCountIs(3))\nWeb framework integration (Next.js, Express, React)"
      },
      {
        "title": "Implementation Checklist",
        "body": "For each file being updated/created:\n\nImport added for selected tools\n If custom env var: Variable declared with correct name\n tools object added to generateText/streamText\n Each selected tool invoked correctly:\n\nStandard env: toolName()\nCustom env: toolName({ apiKey })\n\n\n If streamText: Destructured const { textStream } = ...\n If Anthropic + streamText: Added stopWhen: stepCountIs(3)\n\nGlobal checklist:\n\nPackage installed with their package manager\n Env var set in their environment\n All files updated/created\n Ready to test"
      },
      {
        "title": "Common Issues",
        "body": "Issue: \"Cannot find module @youdotcom-oss/ai-sdk-plugin\"\nFix: Install with their package manager\n\nIssue: \"YDC_API_KEY (or custom name) environment variable is required\"\nFix: Set in their environment (get key: https://you.com/platform/api-keys)\n\nIssue: \"Tool execution fails with 401\"\nFix: Verify API key is valid\n\nIssue: \"Incomplete or missing response\"\nFix: If using streamText, increase the step count. Start with 3 and iterate up as needed (see README troubleshooting)\n\nIssue: \"textStream is not iterable\"\nFix: Destructure: const { textStream } = streamText(...)\n\nIssue: \"Custom env var not working\"\nFix: Pass to each tool: youSearch({ apiKey })"
      },
      {
        "title": "Advanced: Tool Development Patterns",
        "body": "For developers creating custom AI SDK tools or contributing to @youdotcom-oss/ai-sdk-plugin:"
      },
      {
        "title": "Tool Function Structure",
        "body": "Each tool function follows this pattern:\n\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      // Return raw API response for maximum flexibility\n      return response;\n    },\n  });\n};"
      },
      {
        "title": "Input Schemas Enable Smart Queries",
        "body": "Always use schemas from @youdotcom-oss/mcp:\n\n// ✅ Import from @youdotcom-oss/mcp\nimport { SearchQuerySchema } from '@youdotcom-oss/mcp';\n\nexport const youSearch = (config: YouToolsConfig = {}) => {\n  return tool({\n    description: '...',\n    inputSchema: SearchQuerySchema,  // Enables AI to use all search parameters\n    execute: async (params) => { ... },\n  });\n};\n\n// ❌ Don't duplicate or simplify schemas\nconst MySearchSchema = z.object({ query: z.string() });  // Missing filters!\n\nWhy this matters:\n\nRich schemas enable AI to use advanced query parameters (filters, freshness, country, etc.)\nAI can construct more intelligent queries based on user intent\nPrevents duplicating schema definitions across packages\nEnsures consistency with MCP server schemas"
      },
      {
        "title": "API Key Handling",
        "body": "Always provide environment variable fallback and validate before API calls:\n\n// ✅ Automatic environment variable fallback\nconst apiKey = config.apiKey ?? process.env.YDC_API_KEY;\n\n// ✅ 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}"
      },
      {
        "title": "Response Format",
        "body": "Always return raw API response for maximum flexibility:\n\n// ✅ 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;  // Raw response for maximum flexibility\n}\n\n// ❌ Don't format or transform responses\nreturn {\n  text: formatResponse(response),\n  data: response,\n};\n\nWhy raw responses?\n\nMaximum flexibility for AI SDK to process results\nNo information loss from formatting\nAI SDK handles presentation layer\nEasier to debug (see actual API response)"
      },
      {
        "title": "Tool Descriptions",
        "body": "Write descriptions that guide AI behavior:\n\n// ✅ 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// ❌ Too brief\ndescription: 'Search the web'"
      },
      {
        "title": "Additional Resources",
        "body": "Package README: https://github.com/youdotcom-oss/dx-toolkit/tree/main/packages/ai-sdk-plugin\nVercel AI SDK Docs: https://ai-sdk.dev/docs\nYou.com API: https://you.com/platform/api-keys"
      }
    ],
    "body": "Integrate AI SDK with You.com Tools\n\nInteractive workflow to add You.com tools to your Vercel AI SDK application using @youdotcom-oss/ai-sdk-plugin.\n\nWorkflow\n\nAsk: Package Manager\n\nWhich package manager? (npm, bun, yarn, pnpm)\nInstall package using their choice:\nnpm install @youdotcom-oss/ai-sdk-plugin\n# or bun add @youdotcom-oss/ai-sdk-plugin\n# or yarn add @youdotcom-oss/ai-sdk-plugin\n# or pnpm add @youdotcom-oss/ai-sdk-plugin\n\n\nAsk: Environment Variable Name\n\nUsing standard YDC_API_KEY?\nOr custom name? (if custom, get the name)\nHave they set it in their environment?\nIf NO: Guide them to get key from https://you.com/platform/api-keys\n\nAsk: Which AI SDK Functions?\n\nDo they use generateText()?\nDo they use streamText()?\nBoth?\n\nAsk: Existing Files or New Files?\n\nEXISTING: Ask which file(s) to edit\nNEW: Ask where to create file(s) and what to name them\n\nFor Each File, Ask:\n\nWhich tools to add?\nyouSearch (web search)\nyouExpress (AI agent)\nyouContents (content extraction)\nMultiple? (which combination?)\nUsing generateText() or streamText() in this file?\nWhich AI provider model? (to determine if stopWhen needed)\n\nReference Integration Examples\n\nSee \"Integration Examples\" section below for complete code patterns:\n\ngenerateText() - Basic text generation with tools\nstreamText() - Streaming responses with web frameworks (Next.js, Express, React)\n\nUpdate/Create Files\n\nFor each file:\n\nReference integration examples (generateText or streamText based on their answer)\nAdd import for selected tools\nIf EXISTING file: Find their generateText/streamText call and add tools object\nIf NEW file: Create file with example structure\nTool invocation pattern based on env var name:\nStandard YDC_API_KEY: youSearch()\nCustom name: youSearch({ apiKey: process.env.CUSTOM_NAME })\nAdd selected tools to tools object\nIf streamText + Anthropic: Add stopWhen parameter\nIntegration Examples\ngenerateText() - Basic Text Generation\n\nEnvironment Variables Setup:\n\nimport { anthropic } from '@ai-sdk/anthropic';\nimport { generateText } from 'ai';\nimport { youContents, youExpress, youSearch } from '@youdotcom-oss/ai-sdk-plugin';\n\n// 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\nMultiple Tools:\n\nconst result = await generateText({\n  model: anthropic('claude-sonnet-4-5-20250929'),\n  tools: {\n    search: youSearch(),      // Web search with citations\n    agent: youExpress(),      // AI answers with web context\n    extract: youContents(),   // Content extraction from URLs\n  },\n  prompt: 'Research quantum computing and summarize the key papers',\n});\n\n\nCustom API Key:\n\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\nComplete Example:\n\nimport { anthropic } from '@ai-sdk/anthropic';\nimport { generateText } from 'ai';\nimport { youSearch } from '@youdotcom-oss/ai-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\nstreamText() - Streaming Responses\n\nBasic Streaming with stopWhen Pattern:\n\nimport { anthropic } from '@ai-sdk/anthropic';\nimport { streamText, type StepResult } from 'ai';\nimport { youSearch } from '@youdotcom-oss/ai-sdk-plugin';\n\n// CRITICAL: Always use stopWhen for Anthropic streaming\n// Anthropic's SDK requires explicit stop conditions\nconst stepCountIs = (n: number) => (stepResult: StepResult<any>) =>\n  stepResult.stepNumber >= n;\n\nconst result = streamText({\n  model: anthropic('claude-sonnet-4-5-20250929'),\n  tools: { search: youSearch() },\n  stopWhen: stepCountIs(3),  // Required for Anthropic\n  prompt: 'What are the latest AI developments?',\n});\n\n// Consume stream\nfor await (const chunk of result.textStream) {\n  process.stdout.write(chunk);\n}\n\n\nNext.js Integration (App Router):\n\n// app/api/chat/route.ts\nimport { anthropic } from '@ai-sdk/anthropic';\nimport { streamText, type StepResult } from 'ai';\nimport { youSearch } from '@youdotcom-oss/ai-sdk-plugin';\n\nconst stepCountIs = (n: number) => (stepResult: StepResult<any>) =>\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\nExpress.js Integration:\n\n// server.ts\nimport express from 'express';\nimport { anthropic } from '@ai-sdk/anthropic';\nimport { streamText, type StepResult } from 'ai';\nimport { youSearch } from '@youdotcom-oss/ai-sdk-plugin';\n\nconst app = express();\napp.use(express.json());\n\nconst stepCountIs = (n: number) => (stepResult: StepResult<any>) =>\n  stepResult.stepNumber >= n;\n\napp.post('/api/chat', 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/plain; 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\nReact Client (with Next.js):\n\n// components/Chat.tsx\n'use client';\n\nimport { useChat } from 'ai/react';\n\nexport default function Chat() {\n  const { messages, input, handleInputChange, handleSubmit } = useChat({\n    api: '/api/chat',\n  });\n\n  return (\n    <div>\n      {messages.map(m => (\n        <div key={m.id}>\n          <strong>{m.role}:</strong> {m.content}\n        </div>\n      ))}\n\n      <form onSubmit={handleSubmit}>\n        <input value={input} onChange={handleInputChange} />\n        <button type=\"submit\">Send</button>\n      </form>\n    </div>\n  );\n}\n\n\nComplete Streaming Example:\n\nimport { anthropic } from '@ai-sdk/anthropic';\nimport { streamText, type StepResult } from 'ai';\nimport { youSearch } from '@youdotcom-oss/ai-sdk-plugin';\n\nconst stepCountIs = (n: number) => (stepResult: StepResult<any>) =>\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    // 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\nTool Invocation Patterns\n\nBased on env var name from step 2:\n\nStandard YDC_API_KEY:\n\nimport { youSearch } from '@youdotcom-oss/ai-sdk-plugin';\n\ntools: {\n  search: youSearch(),\n}\n\n\nCustom env var:\n\nimport { youSearch } from '@youdotcom-oss/ai-sdk-plugin';\n\nconst apiKey = process.env.THEIR_CUSTOM_NAME;\n\ntools: {\n  search: youSearch({ apiKey }),\n}\n\n\nMultiple tools with standard env var:\n\nimport { youSearch, youExpress, youContents } from '@youdotcom-oss/ai-sdk-plugin';\n\ntools: {\n  search: youSearch(),\n  agent: youExpress(),\n  extract: youContents(),\n}\n\n\nMultiple tools with custom env var:\n\nimport { youSearch, youExpress, youContents } from '@youdotcom-oss/ai-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\nAvailable Tools\nyouSearch\n\nWeb and news search - model determines parameters (query, count, country, etc.)\n\nyouExpress\n\nAI agent with web context - model determines parameters (input, tools)\n\nyouContents\n\nWeb page content extraction - model determines parameters (urls, format)\n\nKey Integration Patterns\n\nThe examples above demonstrate:\n\nImport statements (AI SDK + provider + You.com tools)\nEnv var validation (optional for new files)\nTool configuration based on env var\ngenerateText/streamText usage with tools\nResult handling (especially textStream destructuring for streamText)\nAnthropic streaming pattern (stopWhen: stepCountIs(3))\nWeb framework integration (Next.js, Express, React)\nImplementation Checklist\n\nFor each file being updated/created:\n\n Import added for selected tools\n If custom env var: Variable declared with correct name\n tools object added to generateText/streamText\n Each selected tool invoked correctly:\nStandard env: toolName()\nCustom 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/created\n Ready to test\nCommon Issues\n\nIssue: \"Cannot find module @youdotcom-oss/ai-sdk-plugin\" Fix: Install with their package manager\n\nIssue: \"YDC_API_KEY (or custom name) environment variable is required\" Fix: Set in their environment (get key: https://you.com/platform/api-keys)\n\nIssue: \"Tool execution fails with 401\" Fix: Verify API key is valid\n\nIssue: \"Incomplete or missing response\" Fix: If using streamText, increase the step count. Start with 3 and iterate up as needed (see README troubleshooting)\n\nIssue: \"textStream is not iterable\" Fix: Destructure: const { textStream } = streamText(...)\n\nIssue: \"Custom env var not working\" Fix: Pass to each tool: youSearch({ apiKey })\n\nAdvanced: Tool Development Patterns\n\nFor developers creating custom AI SDK tools or contributing to @youdotcom-oss/ai-sdk-plugin:\n\nTool Function Structure\n\nEach tool function follows this pattern:\n\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      // Return raw API response for maximum flexibility\n      return response;\n    },\n  });\n};\n\nInput Schemas Enable Smart Queries\n\nAlways use schemas from @youdotcom-oss/mcp:\n\n// ✅ Import from @youdotcom-oss/mcp\nimport { SearchQuerySchema } from '@youdotcom-oss/mcp';\n\nexport const youSearch = (config: YouToolsConfig = {}) => {\n  return tool({\n    description: '...',\n    inputSchema: SearchQuerySchema,  // Enables AI to use all search parameters\n    execute: async (params) => { ... },\n  });\n};\n\n// ❌ Don't duplicate or simplify schemas\nconst MySearchSchema = z.object({ query: z.string() });  // Missing filters!\n\n\nWhy this matters:\n\nRich schemas enable AI to use advanced query parameters (filters, freshness, country, etc.)\nAI can construct more intelligent queries based on user intent\nPrevents duplicating schema definitions across packages\nEnsures consistency with MCP server schemas\nAPI Key Handling\n\nAlways provide environment variable fallback and validate before API calls:\n\n// ✅ Automatic environment variable fallback\nconst apiKey = config.apiKey ?? process.env.YDC_API_KEY;\n\n// ✅ 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\nResponse Format\n\nAlways return raw API response for maximum flexibility:\n\n// ✅ 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;  // Raw response for maximum flexibility\n}\n\n// ❌ Don't format or transform responses\nreturn {\n  text: formatResponse(response),\n  data: response,\n};\n\n\nWhy raw responses?\n\nMaximum flexibility for AI SDK to process results\nNo information loss from formatting\nAI SDK handles presentation layer\nEasier to debug (see actual API response)\nTool Descriptions\n\nWrite descriptions that guide AI behavior:\n\n// ✅ 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// ❌ Too brief\ndescription: 'Search the web'\n\nAdditional Resources\nPackage README: https://github.com/youdotcom-oss/dx-toolkit/tree/main/packages/ai-sdk-plugin\nVercel AI SDK Docs: https://ai-sdk.dev/docs\nYou.com API: https://you.com/platform/api-keys"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/EdwardIrby/ydc-ai-sdk-integration",
    "publisherUrl": "https://clawhub.ai/EdwardIrby/ydc-ai-sdk-integration",
    "owner": "EdwardIrby",
    "version": "1.0.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/ydc-ai-sdk-integration",
    "downloadUrl": "https://openagent3.xyz/downloads/ydc-ai-sdk-integration",
    "agentUrl": "https://openagent3.xyz/skills/ydc-ai-sdk-integration/agent",
    "manifestUrl": "https://openagent3.xyz/skills/ydc-ai-sdk-integration/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/ydc-ai-sdk-integration/agent.md"
  }
}