跳至主要內容

使用 AI SDK UI

AI SDK UI 是一套 React 工具函式與元件庫,用於建構 AI 驅動的介面。本指南將說明如何使用 @mastra/ai-sdk,將 Mastra 輸出轉換為 AI SDK 相容格式,讓你能在前端使用其 hook 與元件。

備註

要從 AI SDK v4 遷移至 v5 嗎?請參閱遷移指南

提示

想查看更多範例嗎?請前往 Mastra 的 UI Dojo 或參閱 Next.js 快速入門指南

開始使用
「開始使用」的直接連結

安裝 @mastra/ai-sdk 套件,即可搭配使用 Mastra 與 AI SDK UI。@mastra/ai-sdk 提供自訂 API 路由及工具函式,能以 AI SDK 相容格式串流 Mastra Agent。其中包括聊天、Workflow 與網路路由 handler,以及用於 UI 整合的工具函式與匯出型別。

@mastra/ai-sdk 可與 AI SDK UI 的三個主要 hook 整合:useChat()useCompletion()useObject()

安裝所需套件以開始使用:

npm install @mastra/ai-sdk@latest @ai-sdk/react ai

現在可以按照下方的整合指南與操作方式進行!

整合指南
「整合指南」的直接連結

一般而言,你會先設定以 AI SDK 相容格式串流 Mastra 內容的 API 路由,再於 useChat() 等 AI SDK UI hook 中使用這些路由。請選擇下列其中一種方式:

設定好 API 路由後,即可在 useChat() hook 中使用。

Mastra 伺服器
「Mastra 伺服器」的直接連結

將 Mastra 作為獨立伺服器執行,並將前端(例如使用 Vite + React)連接至其 API 端點。這項作業會使用 Mastra 的自訂 API 路由功能。

資訊

Mastra 的 UI Dojo 就是此設定方式的範例。

你可以使用 chatRoute()workflowRoute()networkRoute() 建立 API 路由,以 AI SDK 相容格式串流 Mastra 內容。實作完成後,即可在 useChat() 中使用這些 API 路由。

此範例說明如何在 /chat 端點設定聊天路由,並使用 ID 為 weatherAgent 的 Agent。

src/mastra/index.ts
import { Mastra } from '@mastra/core'
import { chatRoute } from '@mastra/ai-sdk'

export const mastra = new Mastra({
server: {
apiRoutes: [
chatRoute({
path: '/chat',
agent: 'weatherAgent',
}),
],
},
})

你也可以使用動態 Agent 路由。詳情請參閱 chatRoute() 參考文件

不限框架
「不限框架」的直接連結

如果不想執行 Mastra 伺服器,而是使用 Next.js 或 Express 等框架,可以在自己的 API 路由 handler 中使用 handleChatStream()handleWorkflowStream()handleNetworkStream() 函式。

這些函式會傳回 ReadableStream,你可以使用 createUIMessageStreamResponse() 加以包裝。

AI SDK v6 相容性

不限框架的 handler 會保留現有的 AI SDK v5/預設行為。如果應用程式使用 AI SDK v6 型別,請傳入 version: 'v6'。若要讓 handleChatStream()handleNetworkStream() 獲得最佳 TypeScript 型別推論,請將 messages 以已安裝 ai 版本中的 UIMessage[] 傳入。

下列範例說明如何搭配 Next.js App Router 使用這些函式。

此範例說明如何在 /chat 端點設定聊天路由,並使用 ID 為 weatherAgent 的 Agent。

app/chat/route.ts
import { handleChatStream } from '@mastra/ai-sdk'
import { createUIMessageStreamResponse } from 'ai'
import { mastra } from '@/src/mastra'

export async function POST(req: Request) {
const params = await req.json()
const stream = await handleChatStream({
mastra,
agentId: 'weatherAgent',
params,
})
return createUIMessageStreamResponse({ stream })
}

useChat()
「usechat」的直接連結

無論是透過 Mastra 伺服器建立 API 路由,或使用自選框架,現在都可以在 useChat() hook 中使用 API 端點。

假設已在 /chat 設定使用氣象 Agent 的路由,就可以如下方所示向它提問。請務必設定正確的 api URL。

import { useChat } from '@ai-sdk/react'
import { useState } from 'react'
import { DefaultChatTransport } from 'ai'

export default function Chat() {
const [inputValue, setInputValue] = useState('')
const { messages, sendMessage } = useChat({
transport: new DefaultChatTransport({
api: 'http://localhost:4111/chat',
}),
})

const handleFormSubmit = (e: React.FormEvent) => {
e.preventDefault()
sendMessage({ text: inputValue })
}

return (
<div>
<pre>{JSON.stringify(messages, null, 2)}</pre>
<form onSubmit={handleFormSubmit}>
<input
value={inputValue}
onChange={e => setInputValue(e.target.value)}
placeholder="Name of the city"
/>
</form>
</div>
)
}

使用 prepareSendMessagesRequest 自訂傳送至聊天路由的請求,例如將額外組態傳入 Agent。

使用 Mastra Memory
「使用 Mastra Memory」的直接連結

當 Agent 已設定 memory 時,Mastra 會從伺服器上的儲存空間載入對話歷程。使用者端只需傳送新訊息,不要傳送完整對話歷程。

傳送完整歷程不僅重複,還可能造成訊息排序錯誤,因為使用者端時間戳記可能與資料庫中儲存的時間戳記衝突。

import { useChat } from '@ai-sdk/react'
import { DefaultChatTransport } from 'ai'

const { messages, sendMessage } = useChat({
transport: new DefaultChatTransport({
api: 'http://localhost:4111/chat/weatherAgent',
prepareSendMessagesRequest({ messages }) {
return {
body: {
messages: [messages[messages.length - 1]],
memory: {
thread: 'user-thread-123',
resource: 'user-123',
},
},
}
},
}),
})

請根據應用程式本身的狀態設定 memory.threadmemory.resource,例如 URL 參數、驗證 context 或資料庫。

如需瞭解 Mastra memory 如何載入及儲存訊息,請參閱訊息歷程

chatRoute()handleChatStream() 已支援 memory。請設定使用者端只傳送新訊息,並包含 thread 與 resource 識別碼。

useCompletion()
「usecompletion」的直接連結

useCompletion() hook 可處理前端與 Mastra Agent 之間的單回合補全,讓你能透過 HTTP 傳送 prompt 並接收串流回應。

前端可以如下所示:

app/page.tsx
import { useCompletion } from '@ai-sdk/react'

export default function Page() {
const { completion, input, handleInputChange, handleSubmit } = useCompletion({
api: '/api/completion',
})

return (
<form onSubmit={handleSubmit}>
<input name="prompt" value={input} onChange={handleInputChange} id="input" />
<button type="submit">Submit</button>
<div>{completion}</div>
</form>
)
}

選擇一種後端實作方式:

src/mastra/index.ts
import { Mastra } from '@mastra/core/mastra'
import { registerApiRoute } from '@mastra/core/server'
import { handleChatStream } from '@mastra/ai-sdk'
import { createUIMessageStreamResponse } from 'ai'

export const mastra = new Mastra({
server: {
apiRoutes: [
registerApiRoute('/completion', {
method: 'POST',
handler: async c => {
const { prompt } = await c.req.json()
const mastra = c.get('mastra')
const stream = await handleChatStream({
mastra,
agentId: 'weatherAgent',
params: {
messages: [
{
id: '1',
role: 'user',
parts: [
{
type: 'text',
text: prompt,
},
],
},
],
},
})

return createUIMessageStreamResponse({ stream })
},
}),
],
},
})

自訂 UI
「自訂 UI」的直接連結

自訂 UI(也稱為生成式 UI)讓你能根據 Mastra 串流的資料,轉譯自訂 React 元件。你可以為 Tool 輸出與 Workflow 進度建立視覺化元件,而不只是顯示原始文字或 JSON;其中也包括 Agent network 執行與自訂事件。

在下列情況使用自訂 UI:

  • 將 Tool 輸出轉譯為視覺化元件(例如以氣象卡片取代 JSON)
  • 使用狀態指示器顯示 Workflow step 進度
  • 透過逐步更新將 Agent network 執行過程視覺化
  • 在長時間執行的操作期間顯示進度指示器或狀態更新

資料 part 型別
「資料 part 型別」的直接連結

Mastra 會以訊息中的「part」將資料串流至前端。每個 part 都有 type,用來決定轉譯方式。@mastra/ai-sdk 套件會將 Mastra 串流轉換為 AI SDK 相容的 UI Message DataPart

資料 part 型別來源說明
tool-{toolKey}AI SDK 內建Tool 呼叫及其狀態:input-availableoutput-availableoutput-error
data-workflowworkflowRoute()包含 step 狀態與最終輸出的 Workflow 執行狀態快照
data-workflow-stepworkflowRoute()Workflow step 差異,包含已變更 step 的完整 payload
data-networknetworkRoute()包含依序排列之 step 與輸出的 Agent network 執行狀態
data-tool-agentTool 中的巢狀 Agent目前 step 仍在執行時的精簡巢狀 Agent 快照
data-tool-agent-stepTool 中的巢狀 Agent巢狀 step 完成時發出的完整巢狀 Agent step payload
data-tool-workflowTool 中的巢狀 Workflow從 Tool 的 execute() 中串流的 Workflow 輸出
data-tool-networkTool 中的巢狀 network從 Tool 的 execute() 中串流的 network 輸出
data-{custom}writer.custom()用於進度指示器、狀態更新等用途的自訂事件

轉譯 Tool 輸出
「轉譯 Tool 輸出」的直接連結

當 Agent 呼叫 Tool 時,AI SDK 會自動建立 tool-{toolKey} part。這些 part 包含 Tool 的狀態與輸出,可用來轉譯自訂元件。

Tool part 會依序經歷下列狀態:

  • input-streaming:正在串流 Tool 輸入(已啟用 Tool 呼叫串流時)
  • input-available:已使用完整輸入呼叫 Tool,正在等待執行
  • output-available:Tool 已執行完成並產生輸出
  • output-error:Tool 執行失敗

下列範例會將氣象 Tool 的輸出轉譯為自訂 WeatherCard 元件。

使用 outputSchema 定義 Tool,讓前端知道要轉譯的資料結構。

src/mastra/tools/weather-tool.ts
import { createTool } from '@mastra/core/tools'
import { z } from 'zod'

export const weatherTool = createTool({
id: 'get-weather',
description: 'Get current weather for a location',
inputSchema: z.object({
location: z.string().describe('The location to get the weather for'),
}),
outputSchema: z.object({
temperature: z.number(),
feelsLike: z.number(),
humidity: z.number(),
windSpeed: z.number(),
conditions: z.string(),
location: z.string(),
}),
execute: async inputData => {
const response = await fetch(
`https://api.weatherapi.com/v1/current.json?key=${process.env.WEATHER_API_KEY}&q=${inputData.location}`,
)
const data = await response.json()
return {
temperature: data.current.temp_c,
feelsLike: data.current.feelslike_c,
humidity: data.current.humidity,
windSpeed: data.current.wind_kph,
conditions: data.current.condition.text,
location: data.location.name,
}
},
})
提示

Tool part 型別遵循 tool-{toolKey} 模式,其中 toolKey 是向 Agent 註冊 Tool 時使用的 key。例如,如果將 Tool 註冊為 tools: { weatherTool },part 型別會是 tool-weatherTool

轉譯 Workflow 資料
「轉譯 Workflow 資料」的直接連結

使用 workflowRoute()handleWorkflowStream() 時,Mastra 會針對 Workflow 狀態快照發出 data-workflow part,並針對已變更 step 的完整 payload 發出 data-workflow-step part。如此可避免長時間執行的 Workflow 在每個中間快照中重複所有已完成 step 的輸出。

定義包含多個 step 的 Workflow,讓它在執行時發出 data-workflowdata-workflow-step part。

src/mastra/workflows/activities-workflow.ts
import { createStep, createWorkflow } from '@mastra/core/workflows'
import { z } from 'zod'

const fetchWeather = createStep({
id: 'fetch-weather',
inputSchema: z.object({
location: z.string(),
}),
outputSchema: z.object({
temperature: z.number(),
conditions: z.string(),
}),
execute: async ({ inputData }) => {
// Fetch weather data...
return { temperature: 22, conditions: 'Sunny' }
},
})

const planActivities = createStep({
id: 'plan-activities',
inputSchema: z.object({
temperature: z.number(),
conditions: z.string(),
}),
outputSchema: z.object({
activities: z.string(),
}),
execute: async ({ inputData, mastra }) => {
const agent = mastra?.getAgent('activityAgent')
const response = await agent?.generate(
`Suggest activities for ${inputData.conditions} weather at ${inputData.temperature}°C`,
)
return { activities: response?.text || '' }
},
})

export const activitiesWorkflow = createWorkflow({
id: 'activities-workflow',
inputSchema: z.object({
location: z.string(),
}),
outputSchema: z.object({
activities: z.string(),
}),
})
.then(fetchWeather)
.then(planActivities)

activitiesWorkflow.commit()

向 Mastra 註冊 Workflow,並透過 workflowRoute() 公開,以便將 Workflow 事件串流至前端。

src/mastra/index.ts
import { Mastra } from '@mastra/core'
import { workflowRoute } from '@mastra/ai-sdk'

export const mastra = new Mastra({
workflows: { activitiesWorkflow },
server: {
apiRoutes: [
workflowRoute({
path: '/workflow/activitiesWorkflow',
workflow: 'activitiesWorkflow',
}),
],
},
})

如需 Workflow 串流的詳細資訊,請參閱 Workflow 串流

轉譯 network 資料
「轉譯 network 資料」的直接連結

使用 networkRoute()handleNetworkStream() 時,Mastra 會發出包含 Agent network 執行狀態的 data-network part,其中包括呼叫了哪些 Agent 及其輸出。

向 Mastra 註冊 Agent,並透過 networkRoute() 公開路由 Agent,以便將 network 執行事件串流至前端。

src/mastra/index.ts
import { Mastra } from '@mastra/core'
import { networkRoute } from '@mastra/ai-sdk'

export const mastra = new Mastra({
agents: { routingAgent, researchAgent, weatherAgent },
server: {
apiRoutes: [
networkRoute({
path: '/network',
agent: 'routingAgent',
}),
],
},
})

如需 Agent network 的詳細資訊,請參閱 Agent Network

自訂事件
「自訂事件」的直接連結

在 Tool 的 execute() 函式中使用 writer.custom() 發出自訂資料 part。這適合用於進度指示器、狀態更新,或 Tool 執行期間的任何自訂 UI 更新。

自訂事件型別必須以 data- 開頭,才能被辨識為資料 part。

警告

你必須對 writer.custom() 呼叫使用 await,否則可能遇到 WritableStream is locked 錯誤。

在 Tool 的 execute() 函式中使用 writer.custom(),於不同執行階段發出以 data- 為前綴的自訂事件。

src/mastra/tools/task-tool.ts
import { createTool } from '@mastra/core/tools'
import { z } from 'zod'

export const taskTool = createTool({
id: 'process-task',
description: 'Process a task with progress updates',
inputSchema: z.object({
task: z.string().describe('The task to process'),
}),
outputSchema: z.object({
result: z.string(),
status: z.string(),
}),
execute: async (inputData, context) => {
const { task } = inputData

// Emit "in progress" custom event
await context?.writer?.custom({
type: 'data-tool-progress',
data: {
status: 'in-progress',
message: 'Gathering information...',
},
})

// Simulate work
await new Promise(resolve => setTimeout(resolve, 3000))

// Emit "done" custom event
await context?.writer?.custom({
type: 'data-tool-progress',
data: {
status: 'done',
message: `Successfully processed "${task}"`,
},
})

return {
result: `Task "${task}" has been completed successfully!`,
status: 'completed',
}
},
})

Tool 串流
「Tool 串流」的直接連結

Tool 也能使用 context.writer.write() 串流資料,以提供較低階的控制,或直接將 Agent 串流 pipe 至 Tool 的 writer。詳情請參閱 Tool 串流

範例
「範例」的直接連結

如需自訂 UI 模式的即時範例,請前往 Mastra 的 UI Dojo。該儲存庫包含以下實作:

操作方式
「操作方式」的直接連結

串流轉換
「串流轉換」的直接連結

若要手動將 Mastra 串流轉換為 AI SDK 相容格式,請使用 toAISdkStream() 工具函式。如需具體使用模式,請參閱範例

toAISdkStream() 會保留現有的 AI SDK v5/預設行為。如果應用程式使用 AI SDK v6 型別,請傳入 version: 'v6'

import { toAISdkStream } from '@mastra/ai-sdk'

const v5Stream = toAISdkStream(mastraStream, { from: 'agent' })
const v6Stream = toAISdkStream(mastraStream, { from: 'agent', version: 'v6' })

載入歷史訊息
「載入歷史訊息」的直接連結

從 Mastra memory 載入訊息並顯示於聊天 UI 時,請使用 toAISdkV5Messages()toAISdkV4Messages(),將訊息轉換為適合 useChat()initialMessages 的 AI SDK 格式。

傳遞額外資料
「傳遞額外資料」的直接連結

sendMessage() 可讓你從前端將額外資料傳遞至 Mastra。接著可在伺服器上將此資料作為 RequestContext 使用。

以下是前端程式碼範例:

import { useChat } from '@ai-sdk/react'
import { useState } from 'react'
import { DefaultChatTransport } from 'ai'

export function ChatAdditional() {
const [inputValue, setInputValue] = useState('')
const { messages, sendMessage } = useChat({
transport: new DefaultChatTransport({
api: 'http://localhost:4111/chat-extra',
}),
})

const handleFormSubmit = (e: React.FormEvent) => {
e.preventDefault()
sendMessage(
{ text: inputValue },
{
body: {
data: {
userId: 'user123',
preferences: {
language: 'en',
temperature: 'celsius',
},
},
},
},
)
}

return (
<div>
<pre>{JSON.stringify(messages, null, 2)}</pre>
<form onSubmit={handleFormSubmit}>
<input
value={inputValue}
onChange={e => setInputValue(e.target.value)}
placeholder="Name of the city"
/>
</form>
</div>
)
}

使用下列任一範例實作後端。

如上方所示,將 chatRoute() 加入 Mastra 組態。接著加入伺服器層級的 middleware:

src/mastra/index.ts
import { Mastra } from '@mastra/core'

export const mastra = new Mastra({
server: {
middleware: [
async (c, next) => {
const requestContext = c.get('requestContext')

if (c.req.method === 'POST') {
const clonedReq = c.req.raw.clone()
const body = await clonedReq.json()

if (body?.data) {
for (const [key, value] of Object.entries(body.data)) {
requestContext.set(key, value)
}
}
}
await next()
},
],
},
})
資訊

你可以在 Tool 中透過 requestContext 參數存取此資料。詳情請參閱 Request Context 文件

由使用者核准 Workflow 暫停/繼續
「由使用者核准 Workflow 暫停/繼續」的直接連結

Workflow 可以暫停執行並等待使用者輸入,再繼續進行。這適合用於核准流程、確認,或任何 human-in-the-loop 情境。

此 Workflow 會使用:

  • suspendSchema / resumeSchema:定義暫停 payload 與繼續輸入的資料結構
  • suspend():暫停 Workflow 並將暫停 payload 傳送至 UI
  • resumeData:包含 Workflow 繼續執行時的使用者回應
  • bail():提早結束 Workflow(例如使用者拒絕時)

建立會暫停以等待核准的 Workflow step。該 step 會檢查 resumeData 以判斷是否正在繼續執行,並於第一次執行時呼叫 suspend()

src/mastra/workflows/approval-workflow.ts
import { createStep, createWorkflow } from '@mastra/core/workflows'
import { z } from 'zod'

const requestApproval = createStep({
id: 'request-approval',
inputSchema: z.object({ requestId: z.string(), summary: z.string() }),
outputSchema: z.object({
approved: z.boolean(),
requestId: z.string(),
approvedBy: z.string().optional(),
}),
resumeSchema: z.object({
approved: z.boolean(),
approverName: z.string().optional(),
}),
suspendSchema: z.object({
message: z.string(),
requestId: z.string(),
}),
execute: async ({ inputData, resumeData, suspend, bail }) => {
// User rejected - bail out
if (resumeData?.approved === false) {
return bail({ message: 'Request rejected' })
}
// User approved - continue
if (resumeData?.approved) {
return {
approved: true,
requestId: inputData.requestId,
approvedBy: resumeData.approverName || 'User',
}
}
// First execution - suspend and wait
return await suspend({
message: `Please approve: ${inputData.summary}`,
requestId: inputData.requestId,
})
},
})

export const approvalWorkflow = createWorkflow({
id: 'approval-workflow',
inputSchema: z.object({ requestId: z.string(), summary: z.string() }),
outputSchema: z.object({
approved: z.boolean(),
requestId: z.string(),
approvedBy: z.string().optional(),
}),
}).then(requestApproval)

approvalWorkflow.commit()

註冊 Workflow。暫停/繼續需要儲存空間才能持久保存狀態。

src/mastra/index.ts
import { Mastra } from '@mastra/core'
import { workflowRoute } from '@mastra/ai-sdk'
import { LibSQLStore } from '@mastra/libsql'

export const mastra = new Mastra({
workflows: { approvalWorkflow },
storage: new LibSQLStore({
id: 'mastra-storage',
url: 'file:../mastra.db',
}),
server: {
apiRoutes: [
workflowRoute({ path: '/workflow/approvalWorkflow', workflow: 'approvalWorkflow' }),
],
},
})

重點:

  • 可透過 step.suspendPayload 存取暫停 payload
  • 若要繼續,請在 request body 中傳送 runIdstep(step ID)及 resumeData
  • 必須設定儲存空間,暫停/繼續才能持久保存 Workflow 狀態

如需完整實作,請參閱 UI Dojo 中的 workflow-suspend-resume 範例

Tool 中的巢狀 Agent 串流
「Tool 中的巢狀 Agent 串流」的直接連結

Tool 可以在內部呼叫 Agent,並將 Agent 輸出串流回 UI。當巢狀 step 仍在執行時,這會建立精簡的 data-tool-agent 快照;巢狀 step 完成時,會建立 data-tool-agent-step part;巢狀執行完成時,則會建立一份完整的 data-tool-agent 快照。

此模式會使用:

  • context.mastra.getAgent():從 Tool 內取得 Agent 執行個體
  • agent.stream():串流 Agent 回應
  • stream.fullStream.pipeTo(context.writer):將 Agent 串流 pipe 至 Tool 的 writer

建立會呼叫 Agent,並將其串流 pipe 至 Tool writer 的 Tool。

src/mastra/tools/nested-agent-tool.ts
import { createTool } from '@mastra/core/tools'
import { z } from 'zod'

export const nestedAgentTool = createTool({
id: 'nested-agent-stream',
description: 'Analyze weather using a nested agent',
inputSchema: z.object({
city: z.string().describe('The city to analyze'),
}),
outputSchema: z.object({
summary: z.string(),
}),
execute: async (inputData, context) => {
const agent = context?.mastra?.getAgent('weatherAgent')
if (!agent) {
return { summary: 'Weather agent not available' }
}

const stream = await agent.stream(
`Analyze the weather in ${inputData.city} and provide a summary.`,
)

// Pipe the agent's stream to emit data-tool-agent parts
await stream.fullStream.pipeTo(context!.writer!)

return { summary: (await stream.text) ?? 'No summary available' }
},
})

建立使用此 Tool 的 Agent。

src/mastra/agents/forecast-agent.ts
import { Agent } from '@mastra/core/agent'
import { nestedAgentTool } from '../tools/nested-agent-tool'

export const forecastAgent = new Agent({
id: 'forecast-agent',
instructions: 'Use the nested-agent-stream tool when asked about weather.',
model: 'openai/gpt-5.6-sol',
tools: { nestedAgentTool },
})

重點:

  • fullStream pipe 至 context.writer 會建立 data-tool-agent part
  • 需要剛完成之巢狀 step 的完整 payload 時,請讀取 data-tool-agent-step
  • AgentDataPart 包含 id(位於 part 上)及 data.text(目前巢狀 Agent 的文字快照)
  • 串流完成後,Tool 仍會傳回自己的輸出

如需完整實作,請參閱 UI Dojo 中的 tool-nested-streams 範例

從 Workflow step 串流 Agent 文字
「從 Workflow step 串流 Agent 文字」的直接連結

Workflow step 可以將 Agent 串流 pipe 至 step 的 writer,即時串流 Agent 的文字輸出。如此一來,使用者就能在 Workflow 執行期間看到 Agent 的「思考」內容,而不必等待 step 完成。

此模式會使用:

  • Workflow step 中的 writer:將 Agent 的 fullStream pipe 至 step 的 writer
  • textdata-workflow part:前端在接收 step 進度的同時,也會接收串流文字

建立 Workflow step,透過 pipe 至 step 的 writer 來串流 Agent 回應。

src/mastra/workflows/weather-workflow.ts
import { createStep, createWorkflow } from '@mastra/core/workflows'
import { z } from 'zod'
import { weatherAgent } from '../agents/weather-agent'

const analyzeWeather = createStep({
id: 'analyze-weather',
inputSchema: z.object({ location: z.string() }),
outputSchema: z.object({ analysis: z.string(), location: z.string() }),
execute: async ({ inputData, writer }) => {
const response = await weatherAgent.stream(
`Analyze the weather in ${inputData.location} and provide insights.`,
)

// Pipe agent stream to step writer for real-time text streaming
await response.fullStream.pipeTo(writer)

return {
analysis: await response.text,
location: inputData.location,
}
},
})

const calculateScore = createStep({
id: 'calculate-score',
inputSchema: z.object({ analysis: z.string(), location: z.string() }),
outputSchema: z.object({ score: z.number(), summary: z.string() }),
execute: async ({ inputData }) => {
const score = inputData.analysis.includes('sunny') ? 85 : 50
return { score, summary: `Comfort score for ${inputData.location}: ${score}/100` }
},
})

export const weatherWorkflow = createWorkflow({
id: 'weather-workflow',
inputSchema: z.object({ location: z.string() }),
outputSchema: z.object({ score: z.number(), summary: z.string() }),
})
.then(analyzeWeather)
.then(calculateScore)

weatherWorkflow.commit()

使用 workflowRoute() 註冊 Workflow。文字串流預設為啟用。

src/mastra/index.ts
import { Mastra } from '@mastra/core'
import { workflowRoute } from '@mastra/ai-sdk'

export const mastra = new Mastra({
agents: { weatherAgent },
workflows: { weatherWorkflow },
server: {
apiRoutes: [workflowRoute({ path: '/workflow/weather', workflow: 'weatherWorkflow' })],
},
})

重點:

  • step 的 writer 可在 execute 函式中使用(不是透過 context
  • workflowRoute() 上的 includeTextStreamParts 預設為 true,因此文字預設會進行串流
  • 文字 part 會即時串流,而 data-workflow part 則會隨 step 狀態更新

如需完整實作,請參閱 UI Dojo 中的 workflow-agent-text-stream 範例

分支 Workflow 的多階段進度
「分支 Workflow 的多階段進度」的直接連結

對於具有條件式分支的 Workflow(例如快遞與標準配送),可以在自訂事件中加入識別碼,以追蹤不同分支的進度。

UI Dojo 範例會在事件資料中使用 stage 欄位,識別正在執行的分支(例如 "validation""standard-processing""express-processing")。前端會依此欄位將事件分組,顯示管線式進度 UI。

請參閱 UI Dojo 中的 branching-workflow.ts(後端)與 workflow-custom-events.tsx(前端)。

Agent network 中的進度指示器
「Agent network 中的進度指示器」的直接連結

使用 Agent network 時,可以從子 Agent 所使用的 Tool 發出自訂進度事件,以顯示目前使用中的 Agent。

UI Dojo 範例在事件資料中包含 stage 欄位,用來識別正在執行的子 Agent(例如 "report-generation""report-review")。前端會依此欄位將事件分組,並顯示各組的最新狀態。

請參閱 UI Dojo 中的 report-generation-tool.ts(後端)與 agent-network-custom-events.tsx(前端)。