AI SDK UI Master
Expert skill for AI SDK UI (v6), ai package, and ai-elements in AgentStack with Mastra backend.
Stack Overview
Package Version Purpose
ai
^6.0.97 UIMessage, parts, createUIMessageStream, createUIMessageStreamResponse, type guards
@ai-sdk/react
^3.0.99 useChat hook
@mastra/ai-sdk
^1.0.5 toAISdkStream, chatRoute, networkRoute, workflowRoute
ai-elements local 50+ components in src/components/ai-elements/
Key File Map
Purpose Location
Chat provider app/chat/providers/chat-context.tsx
Chat types app/chat/providers/chat-context-types.ts
Message rendering app/chat/components/chat-messages.tsx
Stream conversion lib/client-stream-to-ai-sdk.ts
API chat route app/api/chat/route.ts
MastraClient lib/mastra-client.ts
Agent config app/chat/config/agents.ts
Base ai-elements (library components)
Reusable building blocks in src/components/ai-elements/ — not in tools/ or custom/ .
Category Location Reference
Conversation & Messaging src/components/ai-elements/
Base: conversation-messaging
Code & Development src/components/ai-elements/
Base: code-development
Reasoning & Debugging src/components/ai-elements/
Base: reasoning-debugging
Input & Controls src/components/ai-elements/
Base: input-controls
Visualization & Canvas src/components/ai-elements/
Base: visualization-canvas
Media & Audio src/components/ai-elements/
Base: media-audio
Agent & Tool (base) src/components/ai-elements/ — Tool, ToolHeader, ToolContent, etc. Base: agent-tool
Other (base) src/components/ai-elements/ — loader, context, sources, plan, … Base: other
Custom tool UIs (project-specific)
Mastra tool result renderers in src/components/ai-elements/tools/ . They use base ai-elements (e.g. tool.tsx ).
What Location Reference
Custom tool UIs ↔ Mastra src/components/ai-elements/tools/
Part 3: Custom tool UIs
Backend → toolName → UI table — Backend → stream toolName → UI mapping
Other project-specific src/components/ai-elements/custom/
Part 4: Other project-specific (custom/)
Tool name → UI: Stream toolName is matched in app/chat/components/agent-tools.tsx ; custom UIs live in src/components/ai-elements/tools/ . Fallback uses base Tool /ToolHeader /ToolContent from tool.tsx . Types from ai-elements/tools/types.ts via InferUITool<typeof mastraTool> .
Mastra Backend (one reference per subdirectory)
Purpose Location Reference
Mastra entry src/mastra/index.ts
mastra-reference.md
Agents (31+) src/mastra/agents/
mastra-reference.md
Tools (60+) src/mastra/tools/
mastra-reference.md
Networks (13) src/mastra/networks/
mastra-reference.md
Workflows (15+) src/mastra/workflows/
mastra-reference.md
Config src/mastra/config/
mastra-reference.md
A2A coordination src/mastra/a2a/
mastra-reference.md
MCP server src/mastra/mcp/
mastra-reference.md
Evals/scorers src/mastra/evals/
mastra-reference.md
Services src/mastra/services/
mastra-reference.md
Data src/mastra/data/
mastra-reference.md
Policy src/mastra/policy/
mastra-reference.md
Transport Pattern
Chat connects directly to Mastra API (NEXT_PUBLIC_MASTRA_API_URL , default http://localhost:4111 ). Do not use MastraClient for chat streaming.
import { useChat } from '@ai-sdk/react' import { DefaultChatTransport } from 'ai' import { RequestContext, MASTRA_RESOURCE_ID_KEY, MASTRA_THREAD_ID_KEY } from '@mastra/core/request-context'
const MASTRA_API_URL = process.env.NEXT_PUBLIC_MASTRA_API_URL ?? 'http://localhost:4111'
const transport = new DefaultChatTransport({
api: ${MASTRA_API_URL}/chat/${selectedAgent},
prepareSendMessagesRequest({ messages: outgoingMessages }) {
const last = outgoingMessages[outgoingMessages.length - 1]
const textPart = last?.parts?.find((p): p is TextUIPart => p.type === 'text')
const requestContext = new RequestContext()
requestContext.set(MASTRA_RESOURCE_ID_KEY, resourceId)
requestContext.set(MASTRA_THREAD_ID_KEY, threadId)
return {
body: {
id: selectedAgent,
messages: outgoingMessages,
memory: { thread: threadId, resource: resourceId },
resourceId,
data: { agentId: selectedAgent, threadId, input: textPart?.text ?? '' },
requestContext,
},
}
}, })
const { messages, sendMessage, stop, status } = useChat({ transport })
UIMessage Parts (AI SDK v6)
Use message.parts , not message.content . Each part has a type discriminator.
Part Type Type Guard Purpose
text
isTextUIPart
Text content
reasoning
isReasoningUIPart
Thinking/reasoning
tool-* / dynamic-tool
isToolUIPart / isToolOrDynamicToolUIPart
Tool invocations
file
isFileUIPart
Attachments
source-url / source-document
— Citations
data
isDataUIPart
Structured data
import { isTextUIPart, isReasoningUIPart, isToolOrDynamicToolUIPart, isFileUIPart, isDataUIPart, } from 'ai'
const textPart = message.parts?.find(isTextUIPart) const content = textPart?.text ?? ''
const tools = message.parts?.filter(isToolOrDynamicToolUIPart) const fileParts = message.parts?.filter(isFileUIPart)
AI Elements Integration Map
Component File AI Elements Used
chat-messages.tsx
Conversation, Message, CodeBlock, Attachments, AudioPlayer, Transcription, Image
agent-reasoning.tsx
Reasoning, ReasoningTrigger, ReasoningContent
agent-chain-of-thought.tsx
ChainOfThought, ChainOfThoughtHeader, ChainOfThoughtContent, ChainOfThoughtStep
agent-tools.tsx
Tool, ToolHeader, ToolInput, ToolOutput
agent-sources.tsx
Sources, SourcesTrigger, SourcesContent, Source
agent-artifact.tsx
Artifact, ArtifactHeader, ArtifactContent, ArtifactActions, ArtifactCode
agent-sandbox.tsx
Sandbox, FileTree, Terminal, TestResults, SchemaDisplay, StackTrace
agent-workflow.tsx
Canvas, Node, Edge, Panel
chat-input.tsx
PromptInput, SpeechInput, Context (token usage), ModelSelector
Import from @/src/components/ai-elements/<component> :
import { Message, MessageContent, MessageResponse } from '@/src/components/ai-elements/message' import { Reasoning, ReasoningTrigger, ReasoningContent } from '@/src/components/ai-elements/reasoning' import { Tool, ToolHeader, ToolInput, ToolOutput } from '@/src/components/ai-elements/tool'
Agent Config Features
agentConfig.features controls which agent-* components render. Check before rendering:
const { agentConfig } = useChatContext()
if (agentConfig.features.reasoning) { // Render AgentReasoning } if (agentConfig.features.tools) { // Render AgentTools } if (agentConfig.features.sources) { // Render AgentSources } if (agentConfig.features.artifacts) { // Render AgentArtifact }
See app/chat/config/agents.ts for full AgentFeatures schema.
Mastra Stream Conversion
Server-side (Next.js API routes)
import { toAISdkStream } from '@mastra/ai-sdk' import { createUIMessageStream, createUIMessageStreamResponse } from 'ai'
const stream = await agent.stream(messages, { threadId, resourceId, requestContext })
const uiStream = createUIMessageStream({ originalMessages: messages, execute: async ({ writer }) => { const aiStream = toAISdkStream(stream, { from: 'agent', sendReasoning: true, sendSources: true, }) for await (const value of aiStream) { await writer.write(value) } }, })
return createUIMessageStreamResponse({ stream: uiStream })
Mastra chatRoute config (src/mastra/index.ts)
chatRoute({ path: '/chat/:agentId', sendStart: true, sendFinish: true, sendReasoning: true, sendSources: true, })
MastraClient vs Direct Transport
Use Case Approach
Chat streaming DefaultChatTransport → Mastra API directly
Network streaming DefaultChatTransport → /network/:agentId
Workflow streaming DefaultChatTransport → /workflow/:workflowId
Dashboard (agents, workflows, traces, threads) MastraClient from lib/mastra-client.ts
Do not use MastraClient for chat/network/workflow streaming.
Anti-Patterns
-
Do not use MastraClient for chat streaming — use DefaultChatTransport.
-
Use message.parts not message.content — AI SDK v6 is parts-based.
-
Import type guards from ai — not custom implementations.
-
Check agentConfig.features before rendering agent-* components.
-
Use RequestContext for multi-tenancy (resourceId, threadId) in prepareSendMessagesRequest.
Quick Reference
ChatContext value (useChatContext)
-
messages , status , isLoading , error
-
sendMessage(text, files?) , stopGeneration() , clearMessages()
-
selectedAgent , agentConfig , selectAgent(id)
-
streamingContent , streamingReasoning , toolInvocations , sources
-
threadId , resourceId , setThreadId , setResourceId
-
webPreview , setWebPreview , checkpoints , createCheckpoint , restoreCheckpoint
Endpoints
-
Chat: ${MASTRA_API_URL}/chat/${agentId}
-
Network: ${MASTRA_API_URL}/network/${agentId}
-
Workflow: ${MASTRA_API_URL}/workflow/${workflowId}
Additional Resources
-
AI Elements (one ref per category): ai-elements-reference.md
-
Mastra backend (one ref per subdir): mastra-reference.md
-
Agent config, API routes: reference.md
-
Agent config schema: app/chat/config/agents.ts
-
app/api/mastra routes: agents, workflows, threads, traces, tools, vectors, memory