自訂模型 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 類型。
-
設定環境變數:
export MASTRA_DEV=true -
註冊 Gateway:
const mastra = new Mastra({gateways: {myGateway: new MyPrivateGateway(),},}) -
自動產生類型:
- 加入 Gateway 時,Mastra 會與 GatewayRegistry 同步
- 登錄會從自訂 Gateway 擷取 Provider
- 系統會在
~/.cache/mastra/重新產生 TypeScript 類型 - IDE 會在數秒內載入新類型
-
現在可使用自動完成:
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 屬性 的直接連結
必填必填 的直接連結
| 屬性 | 類型 | 說明 |
|---|---|---|
id | string | Gateway 的唯一識別碼,用作模型字串的 Gateway 前綴 |
name | string | 便於閱讀的 Gateway 名稱 |
方法方法 的直接連結
| 方法 | 說明 |
|---|---|
fetchProviders() | 擷取 Provider 設定 |
buildUrl(modelId, envVars?) | 為模型建構 API URL |
getApiKey(modelId) | 取得用於驗證的 API 金鑰 |
resolveLanguageModel(args) | 建立語言模型實例 |
getId() | 取得 Gateway ID(傳回 id 或 name) |
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()
})
})
最佳實務最佳實務 的直接連結
-
使用具描述性的 ID 管理版本:需要管理 Gateway 版本時,請設定明確的
id值readonly id = 'my-gateway-v1'; -
妥善處理錯誤:擲出具描述性且可採取行動的錯誤訊息
-
快取高成本操作:適時快取 token、URL 或 Provider 設定
-
驗證環境變數:在
getApiKey及buildUrl檢查必要環境變數 -
為 Gateway 撰寫文件:加入 JSDoc 註解,說明 Gateway 的用途及設定
-
遵循命名慣例:為 Provider 及模型使用清晰一致的命名
-
處理非同步操作:網絡請求及 I/O 操作使用
async/await -
全面測試:為所有 Gateway 方法編寫單元測試
在 Studio 只顯示自訂 Gateway在 Studio 只顯示自訂 Gateway 的直接連結
Studio 預設會列出所有外部模型 Provider(例如 OpenAI、Anthropic 及 Gemini),以及你註冊的自訂 Gateway。如要隱藏外部 Provider,請設定 AUTO_BLOCK_EXTERNAL_PROVIDERS 環境變數:
AUTO_BLOCK_EXTERNAL_PROVIDERS=true
當此變數設為 true 或 1 時,Mastra 只會傳回你自行註冊的 Gateway 所提供的 Provider。靜態 Provider 登錄及內置 Gateway(models.dev、netlify 及 mastra)會從模型選擇器隱藏。當你透過單一私有 Gateway 路由所有模型流量,並且不希望顯示其他 Provider 時,這項設定會很有用。
如果設定了此變數但未註冊任何自訂 Gateway,模型選擇器將會留空。請註冊至少一個自訂 Gateway 以顯示其模型。
內置 Gateway內置 Gateway 的直接連結
Mastra 包含以下內置 Gateway 作為參考實作:
- NetlifyGateway:整合具備 token 交換功能的 Netlify AI Gateway
- ModelsDevGateway:models.dev 所提供、與 OpenAI 相容的 Provider 登錄
Gateway 使用範例請參閱 Netlify、OpenRouter 及 Vercel。