Smithery Logo
MCPsSkillsDocsPricing
Login
Smithery Logo

Give agents more agency

Resources

DocumentationPrivacy PolicySystem Status

Company

PricingAboutBlog

Connect

© 2026 Smithery. All rights reserved.

    horuz-ai

    vercel-ai-sdk-v5

    horuz-ai/vercel-ai-sdk-v5
    AI & ML
    1

    About

    SKILL.md

    Install

    Install via Skills CLI

    or add to your agent
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    ├─
    ├─
    └─

    About

    Expert-level Vercel AI SDK v5 patterns for production chatbots...

    SKILL.md

    Vercel AI SDK v5

    Production patterns for AI chatbots with persistence, generative UI, and streaming.

    Quick Reference

    Need Reference
    Database schema & persistence references/persistence.md
    Tools & generative UI references/tools-and-generative-ui.md
    Custom data streaming references/streaming.md
    Type definitions references/types.md
    Anthropic + reasoning references/anthropic-config.md
    Working examples cookbook/ directory

    Core Architecture

    Message Flow

    Client (useChat) → API Route (streamText) → DB (Drizzle)
         ↑                    ↓
         └── UIMessageStream ←┘
    

    Key Imports

    // Core
    import { streamText, convertToModelMessages, UIMessage } from 'ai'
    import { createUIMessageStream, createUIMessageStreamResponse } from 'ai'
    
    // Client
    import { useChat } from '@ai-sdk/react'
    import { DefaultChatTransport } from 'ai'
    
    // Provider
    import { anthropic } from '@ai-sdk/anthropic'
    

    Decision Tree

    Streaming Response Type

    • Simple text streaming → streamText().toUIMessageStreamResponse()
    • Need custom data parts → createUIMessageStream() + writer.write()
    • Need both → createUIMessageStream() + writer.merge(result.toUIMessageStream())

    Tool Execution Location

    • Has server-side data/secrets → Server tool with execute
    • Needs client confirmation → Client tool (no execute) + addToolOutput
    • Auto-runs on client → Client tool + onToolCall handler

    Data Attachment

    • Message-level info (tokens, model, timestamps) → messageMetadata
    • Dynamic content in message → Data parts with writer.write()
    • Temporary status (not persisted) → Transient data parts

    Naming Convention

    This skill uses agents instead of chats for all database tables, routes, and methods:

    • Table: agents (not chats)
    • Foreign keys: agentId (not chatId)
    • Actions: createAgent(), loadAgent(), deleteAgent()

    File Organization

    Follow feature-based architecture:

    features/
    └── agents/
        ├── data/
        │   └── get-agent.ts
        ├── actions/
        │   └── create-agent.ts
        ├── types/
        │   └── message.ts
        └── components/
            ├── server/
            │   └── agent-messages.tsx
            └── client/
                └── chat-input.tsx
    
    db/
    ├── schema.ts      # Table definitions
    ├── relations.ts   # Drizzle relations
    └── actions.ts     # DB operations (upsert, load, delete)
    

    Essential Patterns

    1. Send Only Last Message

    // Client
    transport: new DefaultChatTransport({
      api: '/api/agent',
      prepareSendMessagesRequest: ({ messages, id }) => ({
        body: { message: messages.at(-1), agentId: id }
      })
    })
    
    // Server: Load history, append new message
    const previous = await loadAgent(agentId)
    const messages = [...previous, message]
    

    2. Persist on Finish

    return result.toUIMessageStreamResponse({
      originalMessages: messages,
      onFinish: async ({ messages }) => {
        await upsertMessages({ agentId, messages })
      }
    })
    

    3. Handle Disconnects

    const result = streamText({ ... })
    result.consumeStream() // No await - ensures completion even on disconnect
    return result.toUIMessageStreamResponse({ ... })
    

    4. Type-Safe Tools

    const tools = { myTool: tool({ ... }) } satisfies ToolSet
    type MyTools = InferUITools<typeof tools>
    type MyUIMessage = UIMessage<MyMetadata, MyDataParts, MyTools>
    

    Common Gotchas

    1. Tool part types are tool-${toolName} not generic tool-call
    2. Data parts need id for reconciliation - same ID updates existing part
    3. Transient parts only in onData - never in message.parts
    4. sendStart: false when using custom start - avoid duplicate start events
    5. result.consumeStream() - call without await for disconnect handling
    Recommended Servers
    Browser tool
    Browser tool
    Nimble MCP Server
    Nimble MCP Server
    ScrapeGraph AI Integration Server
    ScrapeGraph AI Integration Server
    Repository
    horuz-ai/claude-plugins
    Files