跳至主要內容

自訂 API 路由

預設情況下,Mastra 會透過其伺服器自動公開已註冊的 Agent 和 Workflow。如需其他行為,你可以定義自己的 HTTP 路由。

路由可使用輔助函數 registerApiRoute(),此函數由 @mastra/core/server 提供。路由可以與 Mastra 實例放在同一個檔案,但分開放置有助保持設定簡潔。

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

export const mastra = new Mastra({
server: {
apiRoutes: [
registerApiRoute('/my-custom-route', {
method: 'GET',
handler: async c => {
const mastra = c.get('mastra')
const agent = await mastra.getAgent('my-agent')

return c.json({ message: 'Custom route' })
},
}),
],
},
})

註冊後,你可以從伺服器根路徑存取自訂路由。例如:

curl http://localhost:4111/my-custom-route

每個路由的 handler 都會接收 Hono Context。你可以在 handler 中存取 Mastra 實例,以取得或呼叫 Agent 和 Workflow。

中介軟件
中介軟件 的直接連結

如要加入路由專用的中介軟件,請在呼叫 registerApiRoute() 時傳入 middleware array。

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

export const mastra = new Mastra({
server: {
apiRoutes: [
registerApiRoute('/my-custom-route', {
method: 'GET',
middleware: [
async (c, next) => {
console.log(`${c.req.method} ${c.req.url}`)
await next()
},
],
handler: async c => {
return c.json({ message: 'Custom route with middleware' })
},
}),
],
},
})

OpenAPI 文件
OpenAPI 文件 的直接連結

自訂路由可以包含 OpenAPI metadata,並與 Mastra 伺服器路由一同顯示在 Swagger UI 中。你可以在 /api/openapi.json 存取 OpenAPI 規格,當中會列出自訂路由和內置路由。請傳入包含標準 OpenAPI operation 欄位的 openapi 選項。

src/mastra/index.ts
import { Mastra } from '@mastra/core'
import { registerApiRoute } from '@mastra/core/server'
import { z } from 'zod'

export const mastra = new Mastra({
server: {
apiRoutes: [
registerApiRoute('/items/:itemId', {
method: 'GET',
openapi: {
summary: 'Get item by ID',
description: 'Retrieves a single item by its unique identifier',
tags: ['Items'],
parameters: [
{
name: 'itemId',
in: 'path',
required: true,
description: 'The item ID',
schema: { type: 'string' },
},
],
responses: {
200: {
description: 'Item found',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
id: { type: 'string' },
name: { type: 'string' },
},
},
},
},
},
404: {
description: 'Item not found',
},
},
},
handler: async c => {
const itemId = c.req.param('itemId')
return c.json({ id: itemId, name: 'Example Item' })
},
}),
],
},
})

使用 Zod schema
使用 Zod schema 的直接連結

產生 OpenAPI 文件時,openapi 設定中的 Zod schema 會轉換成 JSON Schema:

src/mastra/index.ts
import { Mastra } from '@mastra/core'
import { registerApiRoute } from '@mastra/core/server'
import { z } from 'zod'

const ItemSchema = z.object({
id: z.string(),
name: z.string(),
price: z.number(),
})

const CreateItemSchema = z.object({
name: z.string().min(1),
price: z.number().positive(),
})

export const mastra = new Mastra({
server: {
apiRoutes: [
registerApiRoute('/items', {
method: 'POST',
openapi: {
summary: 'Create a new item',
tags: ['Items'],
requestBody: {
required: true,
content: {
'application/json': {
schema: CreateItemSchema,
},
},
},
responses: {
201: {
description: 'Item created',
content: {
'application/json': {
schema: ItemSchema,
},
},
},
},
},
handler: async c => {
const body = await c.req.json()
return c.json({ id: 'new-id', ...body }, 201)
},
}),
],
},
})

在 Swagger UI 中查看
在 Swagger UI 中查看 的直接連結

以開發模式(mastra dev)執行,或在 build 選項中設定 swaggerUI: true 時,你的自訂路由會顯示在 /swagger-ui 的 Swagger UI 中。

export const mastra = new Mastra({
server: {
build: {
swaggerUI: true, // Enable in production builds
},
apiRoutes: [
// Your routes...
],
},
})

身份驗證
身份驗證 的直接連結

在 Mastra 伺服器上設定身份驗證後,自訂 API 路由預設需要身份驗證。如要讓路由可供公開存取,請設定 requiresAuth: false

src/mastra/index.ts
import { Mastra } from '@mastra/core'
import { registerApiRoute } from '@mastra/core/server'
import { MastraJwtAuth } from '@mastra/auth'

export const mastra = new Mastra({
server: {
auth: new MastraJwtAuth({
secret: process.env.MASTRA_JWT_SECRET,
}),
apiRoutes: [
// Protected route (default behavior)
registerApiRoute('/protected-data', {
method: 'GET',
handler: async c => {
// Access authenticated user from request context
const user = c.get('requestContext').get('user')
return c.json({ message: 'Authenticated user', user })
},
}),

// Public route (no authentication required)
registerApiRoute('/webhooks/github', {
method: 'POST',
requiresAuth: false, // Explicitly opt out of authentication
handler: async c => {
const payload = await c.req.json()
// Process webhook without authentication
return c.json({ received: true })
},
}),
],
},
})

身份驗證行為
身份驗證行為 的直接連結

  • 未設定身份驗證:所有路由(內置和自訂)均為公開
  • 已設定身份驗證
    • Mastra 提供的路由(/api/agents/*/api/workflows/* 等)需要身份驗證
    • 自訂路由預設需要身份驗證
    • 自訂路由可以使用 requiresAuth: false 選擇停用身份驗證

存取用戶資料
存取用戶資料 的直接連結

請求通過身份驗證後,可以在請求 context 中取得 user 物件:

registerApiRoute('/user-profile', {
method: 'GET',
handler: async c => {
const requestContext = c.get('requestContext')
const user = requestContext.get('user')

return c.json({ user })
},
})

如需身份驗證 Provider 的詳細資料,請參閱身份驗證文件

用戶端中斷連線後繼續產生內容
用戶端中斷連線後繼續產生內容 的直接連結

chatRoute() 等內置串流輔助函數會將傳入請求的 AbortSignal 轉交給 agent.stream()。當瀏覽器中斷連線時應取消模型呼叫,這是合適的預設行為。

對於應在用戶端中斷連線時停止的自訂串流路由,請將 c.req.raw.signal 傳給 agent.stream() 等長時間執行的工作。當用戶端連線關閉時,Mastra 基於 Node 的 adapter 亦會停止讀取自訂路由的串流 Response body。並非由用戶端中斷連線引致的串流 response body 錯誤,仍會透過 adapter 的正常錯誤處理機制傳播。在 Hono 中,中斷連線的行為取決於 host runtime 是否將連線關閉事件轉交給 request.signal

src/mastra/index.ts
registerApiRoute('/stream', {
method: 'GET',
handler: async c => {
const stream = await agent.stream(prompt, {
abortSignal: c.req.raw.signal,
})

return stream.toTextStreamResponse()
},
})

如果你希望伺服器即使用戶端中斷連線後仍繼續產生內容並持久保存最終回應,請基於底層 MastraModelOutput 建立自訂路由。啟動 Agent 串流時不要轉交 c.req.raw.signal,然後在背景呼叫 consumeStream(),讓產生程序在伺服器端繼續執行。

src/mastra/index.ts
import {
createUIMessageStream,
createUIMessageStreamResponse,
InferUIMessageChunk,
UIMessage,
} from 'ai'
import { toAISdkStream } from '@mastra/ai-sdk'
import { Mastra } from '@mastra/core'
import { registerApiRoute } from '@mastra/core/server'

export const mastra = new Mastra({
server: {
apiRoutes: [
registerApiRoute('/chat/persist/:agentId', {
method: 'POST',
handler: async c => {
const { messages, memory } = await c.req.json()
const mastra = c.get('mastra')
const agent = mastra.getAgent(c.req.param('agentId'))

const stream = await agent.stream(messages, {
memory,
// Do not pass c.req.raw.signal if this route should keep running
// after the client disconnects.
})

void stream.consumeStream().catch(error => {
mastra.getLogger()?.error('Background stream consumption failed', { error })
})

const uiStream = createUIMessageStream({
originalMessages: messages,
execute: async ({ writer }) => {
for await (const part of toAISdkStream(stream, { from: 'agent' })) {
writer.write(part as InferUIMessageChunk<UIMessage>)
}
},
})

return createUIMessageStreamResponse({ stream: uiStream })
},
}),
],
},
})
備註

只有當你有意讓工作在 HTTP 用戶端離線後繼續執行,才使用此模式。如果你希望中斷連線時取消產生程序,請繼續使用 chatRoute(),或自行轉交請求的 AbortSignal