自定义模型 Gateway
自定义模型 Gateway 允许你通过 MastraModelGatewayInterface 接口或 MastraModelGateway 基类,实现私有或专用 LLM Provider 集成。
概述概述的直接链接
Gateway 负责处理访问语言模型时与 Provider 相关的逻辑:
- Provider 配置和模型发现
- 认证和 API key 管理
- 构造 API endpoint 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,再 fallback 到 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 实例时,以 record 形式传入 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,则 fallback 到内置 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 同步
- registry 从自定义 Gateway 获取 Provider
- 在
~/.cache/mastra/中重新生成 TypeScript 类型 - IDE 会在数秒内识别新类型
-
开始使用自动补全:
const agent = new Agent({model: 'my-gateway-id/my-provider/model-1', // Full autocomplete!})
工作原理工作原理的直接链接
GatewayRegistry 每小时同步一次,并执行以下操作:
- 对所有已注册 Gateway 调用
fetchProviders() - 生成 TypeScript 类型定义
- 将类型写入全局 cache 和项目的
dist/目录 - TypeScript Server 自动识别变更
第一次添加 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)的直接链接
通过注册 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 与注册 key 不同
- 需要跨不同实例通过 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 key |
resolveLanguageModel(args) | 创建语言模型实例 |
getId() | 获取 Gateway ID(返回 id 或 name) |
Provider 配置Provider 配置的直接链接
fetchProviders() 方法返回由 ProviderConfig 对象组成的 record:
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 与 key 的区别Gateway ID 与 key 的区别的直接链接
二者的区别如下:
- Key:将 Gateway 添加到 Mastra 时使用的注册 key(record key)
- 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
高级示例高级示例的直接链接
带 cache 的 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 进行版本管理时,请设置显式
idreadonly 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 registry 和内置 Gateway(models.dev、netlify 和 mastra)会从模型选择器中隐藏。当所有模型流量都通过单个私有 Gateway 路由,并且不希望显示其他 Provider 时,这一设置很有用。
设置此变量后,如果未注册任何自定义 Gateway,模型选择器将为空。请至少注册一个自定义 Gateway 以显示其模型。
内置 Gateway内置 Gateway的直接链接
Mastra 提供以下内置 Gateway 作为参考实现:
- NetlifyGateway:集成 token exchange 的 Netlify AI Gateway
- ModelsDevGateway:来自 models.dev 的 OpenAI 兼容 Provider registry
Gateway 用法示例请参阅 Netlify、OpenRouter 和 Vercel。