vercel-ai-sdk-v5
1
总安装量
1
周安装量
#44203
全站排名
安装命令
npx skills add https://github.com/horuz-ai/claude-plugins --skill vercel-ai-sdk-v5
Agent 安装分布
openclaw
1
opencode
1
claude-code
1
Skill 文档
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 +
onToolCallhandler
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(notchats) - Foreign keys:
agentId(notchatId) - 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
- Tool part types are
tool-${toolName}not generictool-call - Data parts need
idfor reconciliation – same ID updates existing part - Transient parts only in
onData– never inmessage.parts sendStart: falsewhen using custom start – avoid duplicate start eventsresult.consumeStream()– call without await for disconnect handling