跳到主要内容

自定义模型 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 类型。

  1. 设置环境变量

    export MASTRA_DEV=true
  2. 注册 Gateway

    const mastra = new Mastra({
    gateways: {
    myGateway: new MyPrivateGateway(),
    },
    })
  3. 自动生成类型

    • 添加 Gateway 时,Mastra 会与 GatewayRegistry 同步
    • registry 从自定义 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 类型定义
  • 将类型写入全局 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 属性的直接链接

必需属性
必需属性的直接链接

属性类型描述
idstringGateway 的唯一标识符,用作模型字符串的 Gateway 前缀
namestring便于阅读的 Gateway 名称

方法
方法的直接链接

方法描述
fetchProviders()获取 Provider 配置
buildUrl(modelId, envVars?)为模型构造 API URL
getApiKey(modelId)获取用于认证的 API key
resolveLanguageModel(args)创建语言模型实例
getId()获取 Gateway ID(返回 idname

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()
})
})

最佳实践
最佳实践的直接链接

  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 registry 和内置 Gateway(models.devnetlifymastra)会从模型选择器中隐藏。当所有模型流量都通过单个私有 Gateway 路由,并且不希望显示其他 Provider 时,这一设置很有用。

设置此变量后,如果未注册任何自定义 Gateway,模型选择器将为空。请至少注册一个自定义 Gateway 以显示其模型。

内置 Gateway
内置 Gateway的直接链接

Mastra 提供以下内置 Gateway 作为参考实现:

  • NetlifyGateway:集成 token exchange 的 Netlify AI Gateway
  • ModelsDevGateway:来自 models.dev 的 OpenAI 兼容 Provider registry

Gateway 用法示例请参阅 NetlifyOpenRouterVercel