跳至主要內容

自訂模型 Gateway

自訂模型 Gateway 讓你透過 MastraModelGatewayInterface 介面或 MastraModelGateway 基礎類別,實作私有或專用 LLM Provider 整合。

概覽
概覽 的直接連結

Gateway 會處理存取語言模型時的 Provider 專屬邏輯:

  • Provider 設定及模型探索
  • 驗證及 API 金鑰管理
  • 建構 API 端點 URL
  • 建立語言模型實例

建立自訂 Gateway 以支援:

  • 私有或企業 LLM 部署
  • 自訂驗證機制
  • 專用路由邏輯
  • 以唯一 ID 管理 Gateway 版本

建立自訂 Gateway
建立自訂 Gateway 的直接連結

如要使用純物件 Gateway,請實作 MastraModelGatewayInterface;如要使用基礎類別的預設值,則擴充 MastraModelGateway

import { type MastraModelGatewayInterface, type ProviderConfig } from '@mastra/core/llm'
import { createOpenAICompatible } from '@ai-sdk/openai-compatible-v5'

const myPrivateGateway: MastraModelGatewayInterface = {
id: 'private',
name: 'My Private Gateway',
async fetchProviders(): Promise<Record<string, ProviderConfig>> {
return {
'my-provider': {
name: 'My Provider',
models: ['openai/gpt-5.6-sol'],
apiKeyEnvVar: 'MY_API_KEY',
gateway: 'private',
url: 'https://api.myprovider.com/v1',
},
}
},
buildUrl() {
return 'https://api.myprovider.com/v1'
},
async getApiKey() {
return process.env.MY_API_KEY ?? ''
},
async resolveLanguageModel({ modelId, providerId, apiKey }) {
return createOpenAICompatible({
name: providerId,
apiKey,
baseURL: 'https://api.myprovider.com/v1',
}).chatModel(modelId)
},
}

以下範例擴充 MastraModelGateway 類別:

import { MastraModelGateway, type ProviderConfig } from '@mastra/core/llm'
import { createOpenAICompatible } from '@ai-sdk/openai-compatible-v5'
import type { LanguageModelV2 } from '@ai-sdk/provider-v5'

class MyPrivateGateway extends MastraModelGateway {
// Required: Unique identifier for the gateway
// This ID is used as the prefix for all providers from this gateway
readonly id = 'private'

// Required: Human-readable name
readonly name = 'My Private Gateway'

/**
* Fetch provider configurations from your gateway
* Returns a record of provider configurations
*/
async fetchProviders(): Promise<Record<string, ProviderConfig>> {
return {
'my-provider': {
name: 'My Provider',
models: ['openai/gpt-5.6-sol', 'anthropic/claude-sonnet-4-6'],
apiKeyEnvVar: 'MY_API_KEY',
gateway: this.id,
url: 'https://api.myprovider.com/v1',
},
}
}

/**
* Build the API URL for a model
* @param modelId - Full model ID (e.g., "private/my-provider/model-1")
* @param envVars - Environment variables (optional)
*/
buildUrl(modelId: string, envVars?: Record<string, string>): string {
return 'https://api.myprovider.com/v1'
}

/**
* Get the API key for authentication
* @param modelId - Full model ID
*/
async getApiKey(modelId: string): Promise<string> {
const apiKey = process.env.MY_API_KEY
if (!apiKey) {
throw new Error(`Missing MY_API_KEY environment variable`)
}
return apiKey
}

/**
* Create a language model instance
* @param args - Model ID, provider ID, and API key
*/
async resolveLanguageModel({
modelId,
providerId,
apiKey,
}: {
modelId: string
providerId: string
apiKey: string
}): Promise<LanguageModelV2> {
const baseURL = this.buildUrl(`${providerId}/${modelId}`)

return createOpenAICompatible({
name: providerId,
apiKey,
baseURL,
supportsStructuredOutputs: true,
}).chatModel(modelId)
}
}

由 Gateway 管理的驗證
由 Gateway 管理的驗證 的直接連結

當 Gateway 負責查找憑證時,請加入 resolveAuth。Mastra 會先使用此 hook,之後才後備呼叫 getApiKey()

const myPrivateGateway: MastraModelGatewayInterface = {
// ...gateway fields and methods
async resolveAuth() {
const apiKey = process.env.MY_API_KEY
return apiKey ? { apiKey, source: 'gateway' } : undefined
},
}

註冊自訂 Gateway
註冊自訂 Gateway 的直接連結

初始化期間
初始化期間 的直接連結

建立 Mastra 實例時,以記錄形式傳入 Gateway:

import { Mastra } from '@mastra/core'

const mastra = new Mastra({
gateways: {
myGateway: new MyPrivateGateway(),
anotherGateway: new AnotherGateway(),
},
})

初始化之後
初始化之後 的直接連結

使用 addGateway 動態加入 Gateway:

const mastra = new Mastra()

// Add with explicit key
mastra.addGateway(new MyPrivateGateway(), 'myGateway')

// Add using gateway's ID
mastra.addGateway(new MyPrivateGateway())
// Stored with key 'my-private-gateway' (the gateway's id)

使用自訂 Gateway
使用自訂 Gateway 的直接連結

以 Gateway ID 作為前綴,參照自訂 Gateway 的模型:

import { Agent } from '@mastra/core/agent'

const agent = new Agent({
id: 'my-agent',
name: 'My Agent',
instructions: 'You are a helpful assistant',
model: 'private/my-provider/openai/gpt-5.6-sol', // Uses MyPrivateGateway
})

mastra.addAgent(agent, 'myAgent')

建立 Agent 或使用模型時,Mastra 的模型路由器會根據模型 ID 自動選擇合適的 Gateway。Gateway ID 會作為前綴;如沒有相符的自訂 Gateway,則後備使用內置 Gateway。

TypeScript 自動完成
TypeScript 自動完成 的直接連結

在開發環境自動產生類型
在開發環境自動產生類型 的直接連結

在開發模式(MASTRA_DEV=true)運行時,Mastra 會自動為自訂 Gateway 產生 TypeScript 類型。

  1. 設定環境變數

    export MASTRA_DEV=true
  2. 註冊 Gateway

    const mastra = new Mastra({
    gateways: {
    myGateway: new MyPrivateGateway(),
    },
    })
  3. 自動產生類型

    • 加入 Gateway 時,Mastra 會與 GatewayRegistry 同步
    • 登錄會從自訂 Gateway 擷取 Provider
    • 系統會在 ~/.cache/mastra/ 重新產生 TypeScript 類型
    • IDE 會在數秒內載入新類型
  4. 現在可使用自動完成

    const agent = new Agent({
    model: 'my-gateway-id/my-provider/model-1', // Full autocomplete!
    })

運作方式
運作方式 的直接連結

GatewayRegistry 每小時執行一次同步,以:

  • 對所有已註冊 Gateway 呼叫 fetchProviders()
  • 產生 TypeScript 類型定義
  • 將類型寫入全域快取及項目的 dist/ 目錄
  • TypeScript 伺服器會自動載入變更
提示

首次加入 Gateway 時,產生類型可能需要數秒。之後的更新會每小時在背景執行。

手動產生類型的替代方法
手動產生類型的替代方法 的直接連結

如果你並非在開發模式運行,或需要立即更新類型:

選項 1:使用類型斷言(最簡單)

const agent = new Agent({
id: 'my-agent',
name: 'my-agent',
instructions: 'You are a helpful assistant',
model: 'private/my-provider/model-1' as any, // Bypass type checking
})

選項 2:建立自訂聯合類型(類型安全)

import type { ModelRouterModelId } from '@mastra/core/llm'

// Define your custom model IDs
type CustomModelId =
| 'private/my-provider/model-1'
| 'private/my-provider/model-2'
| 'private/my-provider/model-3'

// Combine with built-in models
type AllModelIds = ModelRouterModelId | CustomModelId

const agent = new Agent({
id: 'my-agent',
name: 'my-agent',
instructions: 'You are a helpful assistant',
model: 'private/my-provider/model-1' satisfies AllModelIds,
})

選項 3:全域擴充 ModelRouterModelId(進階)

// In a types.d.ts file in your project
// The import is required: it makes this file a module, so the block below
// merges into the existing types instead of replacing the module.
import '@mastra/core/llm'

declare module '@mastra/core/llm' {
interface ProviderModelsMap {
'my-provider': readonly ['model-1', 'model-2', 'model-3']
}
}

這會擴充內置類型以包含自訂模型,提供完整的自動完成支援。

Gateway 管理
Gateway 管理 的直接連結

getGateway(key)
getGateway(key) 的直接連結

以註冊金鑰擷取 Gateway:

const gateway = mastra.getGateway('myGateway')
console.log(gateway.name) // 'My Private Gateway'

getGatewayById(id)
getGatewayById(id) 的直接連結

以唯一 ID 擷取 Gateway:

const gateway = mastra.getGatewayById('my-private-gateway')
console.log(gateway.name) // 'My Private Gateway'

以下情況會適合使用:

  • Gateway 的明確 ID 與註冊金鑰不同
  • 需要跨不同實例按 ID 尋找 Gateway
  • 支援 Gateway 版本管理(例如 'gateway-v1''gateway-v2'

listGateways()
listGateways() 的直接連結

取得所有已註冊 Gateway:

const gateways = mastra.listGateways()
console.log(Object.keys(gateways)) // ['myGateway', 'anotherGateway']

Gateway 屬性
Gateway 屬性 的直接連結

必填
必填 的直接連結

屬性類型說明
idstringGateway 的唯一識別碼,用作模型字串的 Gateway 前綴
namestring便於閱讀的 Gateway 名稱

方法
方法 的直接連結

方法說明
fetchProviders()擷取 Provider 設定
buildUrl(modelId, envVars?)為模型建構 API URL
getApiKey(modelId)取得用於驗證的 API 金鑰
resolveLanguageModel(args)建立語言模型實例
getId()取得 Gateway ID(傳回 idname

Provider 設定
Provider 設定 的直接連結

fetchProviders() 方法會傳回 ProviderConfig 物件的記錄:

interface ProviderConfig {
name: string // Display name
models: string[] // Available model IDs
apiKeyEnvVar: string | string[] // Environment variable(s) for API key
gateway: string // Gateway identifier
url?: string // Optional API base URL
apiKeyHeader?: string // Optional custom auth header
docUrl?: string // Optional documentation URL
}

Gateway ID 與金鑰的分別
Gateway ID 與金鑰的分別 的直接連結

兩者的分別如下:

  • 金鑰:將 Gateway 加入 Mastra 時使用的註冊金鑰(記錄鍵)
  • ID:Gateway 的唯一識別碼(id 屬性;如未設定則使用 name
class VersionedGateway extends MastraModelGateway {
readonly id = 'my-gateway-v2' // Unique ID for versioning and prefixing
readonly name = 'My Gateway' // Display name
}

const mastra = new Mastra({
gateways: {
currentGateway: new VersionedGateway(), // Key: 'currentGateway'
},
})

// Retrieve by key
const byKey = mastra.getGateway('currentGateway')

// Retrieve by ID
const byId = mastra.getGatewayById('my-gateway-v2')

// Both return the same gateway
console.log(byKey === byId) // true

模型 ID 格式
模型 ID 格式 的直接連結

透過自訂 Gateway 存取的模型採用以下格式:

[gatewayId]/[provider]/[model]

範例:

  • private/my-provider/model-1

進階範例
進階範例 的直接連結

具備快取功能、以 token 為基礎的 Gateway:

class TokenGateway extends MastraModelGateway {
readonly id = 'token-gateway-v1'
readonly name = 'Token Gateway'

private tokenCache: Map<string, { token: string; expiresAt: number }> = new Map()

async fetchProviders(): Promise<Record<string, ProviderConfig>> {
const response = await fetch('https://api.gateway.com/providers')
const data = await response.json()

return {
provider: {
name: data.name,
models: data.models,
apiKeyEnvVar: 'GATEWAY_TOKEN',
gateway: this.id,
},
}
}

async buildUrl(modelId: string, envVars?: Record<string, string>): Promise<string> {
const token = await this.getApiKey(modelId)
const siteId = envVars?.SITE_ID || process.env.SITE_ID

const response = await fetch(`https://api.gateway.com/sites/${siteId}/token`, {
headers: { Authorization: `Bearer ${token}` },
})

const { url } = await response.json()
return url
}

async getApiKey(modelId: string): Promise<string> {
const cached = this.tokenCache.get(modelId)

if (cached && cached.expiresAt > Date.now()) {
return cached.token
}

const token = process.env.GATEWAY_TOKEN
if (!token) {
throw new Error('Missing GATEWAY_TOKEN')
}

// Cache token for 1 hour
this.tokenCache.set(modelId, {
token,
expiresAt: Date.now() + 3600000,
})

return token
}

async resolveLanguageModel({
modelId,
providerId,
apiKey,
}: {
modelId: string
providerId: string
apiKey: string
}): Promise<LanguageModelV2> {
const baseURL = await this.buildUrl(`${providerId}/${modelId}`)

return createOpenAICompatible({
name: providerId,
apiKey,
baseURL,
supportsStructuredOutputs: true,
}).chatModel(modelId)
}
}

錯誤處理
錯誤處理 的直接連結

為常見失敗情況提供清晰的錯誤訊息:

class RobustGateway extends MastraModelGateway {
// ... properties

async getApiKey(modelId: string): Promise<string> {
const apiKey = process.env.MY_API_KEY

if (!apiKey) {
throw new Error(
`Missing MY_API_KEY environment variable for model: ${modelId}. ` +
`Please set MY_API_KEY in your environment.`,
)
}

return apiKey
}

async buildUrl(modelId: string, envVars?: Record<string, string>): Promise<string> {
const baseUrl = envVars?.BASE_URL || process.env.BASE_URL

if (!baseUrl) {
throw new Error(
`No base URL configured for model: ${modelId}. ` +
`Set BASE_URL environment variable or pass it in envVars.`,
)
}

return baseUrl
}
}

測試自訂 Gateway
測試自訂 Gateway 的直接連結

測試結構範例:

import { describe, it, expect, beforeEach } from 'vitest'
import { Mastra } from '@mastra/core'

describe('MyPrivateGateway', () => {
beforeEach(() => {
process.env.MY_API_KEY = 'test-key'
})

it('should fetch providers', async () => {
const gateway = new MyPrivateGateway()
const providers = await gateway.fetchProviders()

expect(providers['my-provider']).toBeDefined()
expect(providers['my-provider'].models).toContain('model-1')
})

it('should integrate with Mastra', () => {
const mastra = new Mastra({
gateways: {
private: new MyPrivateGateway(),
},
})

const gateway = mastra.getGateway('private')
expect(gateway.name).toBe('My Private Gateway')
})

it('should resolve models by ID', () => {
const mastra = new Mastra({
gateways: {
key: new MyPrivateGateway(),
},
})

const gateway = mastra.getGatewayById('my-private-gateway')
expect(gateway).toBeDefined()
})
})

最佳實務
最佳實務 的直接連結

  1. 使用具描述性的 ID 管理版本:需要管理 Gateway 版本時,請設定明確的 id

    readonly id = 'my-gateway-v1';
  2. 妥善處理錯誤:擲出具描述性且可採取行動的錯誤訊息

  3. 快取高成本操作:適時快取 token、URL 或 Provider 設定

  4. 驗證環境變數:在 getApiKeybuildUrl 檢查必要環境變數

  5. 為 Gateway 撰寫文件:加入 JSDoc 註解,說明 Gateway 的用途及設定

  6. 遵循命名慣例:為 Provider 及模型使用清晰一致的命名

  7. 處理非同步操作:網絡請求及 I/O 操作使用 async/await

  8. 全面測試:為所有 Gateway 方法編寫單元測試

在 Studio 只顯示自訂 Gateway
在 Studio 只顯示自訂 Gateway 的直接連結

Studio 預設會列出所有外部模型 Provider(例如 OpenAI、Anthropic 及 Gemini),以及你註冊的自訂 Gateway。如要隱藏外部 Provider,請設定 AUTO_BLOCK_EXTERNAL_PROVIDERS 環境變數:

AUTO_BLOCK_EXTERNAL_PROVIDERS=true

當此變數設為 true1 時,Mastra 只會傳回你自行註冊的 Gateway 所提供的 Provider。靜態 Provider 登錄及內置 Gateway(models.devnetlifymastra)會從模型選擇器隱藏。當你透過單一私有 Gateway 路由所有模型流量,並且不希望顯示其他 Provider 時,這項設定會很有用。

如果設定了此變數但未註冊任何自訂 Gateway,模型選擇器將會留空。請註冊至少一個自訂 Gateway 以顯示其模型。

內置 Gateway
內置 Gateway 的直接連結

Mastra 包含以下內置 Gateway 作為參考實作:

  • NetlifyGateway:整合具備 token 交換功能的 Netlify AI Gateway
  • ModelsDevGateway:models.dev 所提供、與 OpenAI 相容的 Provider 登錄

Gateway 使用範例請參閱 NetlifyOpenRouterVercel