본문으로 건너뛰기

Custom model gateways

사용자 지정 Model 게이트웨이를 사용하면 다음을 통해 비공개 또는 특수 LLM Provider 통합을 구현할 수 있습니다: MastraModelGatewayInterface interface or the MastraModelGateway base class.

Overview
Overview에 대한 직접 링크

게이트웨이는 언어 Model에 접근하기 위한 Provider별 로직을 처리합니다:

  • Provider configuration and model discovery
  • Authentication and API key management
  • URL construction for API endpoints
  • Language model instance creation

Create custom gateways to support:

  • Private or enterprise LLM deployments
  • Custom authentication schemes
  • Specialized routing logic
  • Gateway versioning with unique IDs

Creating a Custom Gateway
Creating a Custom Gateway에 대한 직접 링크

Implement MastraModelGatewayInterface for a plain object gateway, or extend MastraModelGateway when you want base class defaults.

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);
},
};

The following example extends the MastraModelGateway class:

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-owned authentication
Gateway-owned authentication에 대한 직접 링크

Add resolveAuth 게이트웨이가 자격 증명 조회를 담당하는 경우에 사용합니다. Mastra는 다음으로 대체하기 전에 이 후크를 사용합니다: getApiKey().

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

Registering Custom Gateways
Registering Custom Gateways에 대한 직접 링크

During Initialization
During Initialization에 대한 직접 링크

Mastra 인스턴스를 생성할 때 게이트웨이를 레코드로 전달하세요:

import { Mastra } from '@mastra/core';

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

After Initialization
After Initialization에 대한 직접 링크

Add gateways dynamically using addGateway:

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)

Using Custom Gateways
Using Custom Gateways에 대한 직접 링크

게이트웨이 ID를 접두사로 사용하여 사용자 지정 게이트웨이의 Model을 참조하세요:

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를 생성하거나 Model을 사용할 때 Mastra의 Model 라우터는 Model ID를 기준으로 적절한 게이트웨이를 자동 선택합니다. 게이트웨이 ID가 접두사 역할을 합니다. 일치하는 사용자 지정 게이트웨이가 없으면 기본 제공 게이트웨이로 대체됩니다.

TypeScript Autocomplete
TypeScript Autocomplete에 대한 직접 링크

Automatic type generation in development
Automatic type generation in development에 대한 직접 링크

When running in development mode (MASTRA_DEV=true), Mastra는 사용자 지정 게이트웨이에 대한 TypeScript 타입을 자동으로 생성합니다.

  1. Set the environment variable:

    export MASTRA_DEV=true
  2. Register your gateways:

    const mastra = new Mastra({
    gateways: {
    myGateway: new MyPrivateGateway(),
    },
    });
  3. Types are generated automatically:

    • 게이트웨이를 추가하면 Mastra가 GatewayRegistry와 동기화됩니다.
    • 레지스트리는 사용자 지정 게이트웨이에서 Provider를 가져옵니다.
    • TypeScript types are regenerated in ~/.cache/mastra/
    • IDE가 몇 초 안에 새 타입을 인식합니다.
  4. Autocomplete now works:

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

How it works
How it works에 대한 직접 링크

The GatewayRegistry runs an hourly sync that:

  • Calls fetchProviders() on all registered gateways
  • Generates TypeScript type definitions
  • 전역 캐시와 프로젝트의 다음 위치 모두에 해당 타입을 기록합니다: dist/ directory
  • TypeScript 서버가 변경 사항을 자동으로 인식합니다.

게이트웨이를 처음 추가하면 타입을 생성하는 데 몇 초 정도 걸릴 수 있습니다. 이후 업데이트는 백그라운드에서 매시간 이루어집니다.

Manual Type Generation Alternatives
Manual Type Generation Alternatives에 대한 직접 링크

개발 모드에서 실행 중이 아니거나 타입을 즉시 업데이트해야 하는 경우:

Option 1: Use type assertion (simplest)

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

Option 2: Create a custom type union (type-safe)

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,
});

Option 3: Extend ModelRouterModelId globally (advanced)

// 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'];
}
}

이렇게 하면 기본 제공 타입이 확장되어 사용자 지정 Model이 포함되므로 완전한 자동 완성 기능을 사용할 수 있습니다.

Gateway Management
Gateway Management에 대한 직접 링크

getGateway(key)
getGateway(key)에 대한 직접 링크

Retrieve a gateway by its registration key:

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

getGatewayById(id)
getGatewayById(id)에 대한 직접 링크

Retrieve a gateway by its unique ID:

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

This is useful when:

  • Gateway에 등록 키와 다른 명시적 ID가 있는 경우
  • 서로 다른 인스턴스에서 ID로 Gateway를 찾아야 하는 경우
  • Supporting gateway versioning (e.g., 'gateway-v1', 'gateway-v2')

listGateways()
listGateways()에 대한 직접 링크

Get all registered gateways:

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

Gateway Properties
Gateway Properties에 대한 직접 링크

Required
Required에 대한 직접 링크

PropertyTypeDescription
idstringGateway의 고유 식별자이며, Model 문자열에서 Gateway 접두사로 사용됩니다
namestringHuman-readable gateway name

Methods
Methods에 대한 직접 링크

MethodDescription
fetchProviders()Fetch provider configurations
buildUrl(modelId, envVars?)Build API URL for a model
getApiKey(modelId)Get API key for authentication
resolveLanguageModel(args)Create language model instance
getId()Get gateway ID (returns id or name)

Provider Configuration
Provider Configuration에 대한 직접 링크

The fetchProviders() method returns a record of ProviderConfig objects:

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 IDs vs Keys
Gateway IDs vs Keys에 대한 직접 링크

Understanding the distinction:

  • Key: Mastra에 Gateway를 추가할 때 사용하는 등록 키(레코드 키)
  • ID: The gateway's unique identifier (via id property or name if not set)
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

Model ID Format
Model ID Format에 대한 직접 링크

사용자 지정 Gateway를 통해 액세스하는 Model은 다음 형식을 따릅니다:

[gatewayId]/[provider]/[model]

Examples:

  • private/my-provider/model-1

Advanced example
Advanced example에 대한 직접 링크

Token-based gateway with caching:

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

Error handling
Error handling에 대한 직접 링크

Provide descriptive errors for common failure scenarios:

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;
}
}

Testing Custom Gateways
Testing Custom Gateways에 대한 직접 링크

Example test structure:

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

Best practices
Best practices에 대한 직접 링크

  1. Use descriptive IDs for versioning: Set explicit id Gateway의 버전을 관리해야 할 때 사용하는 값

    readonly id = 'my-gateway-v1';
  2. Implement proper error handling: Throw descriptive errors with actionable messages

  3. Cache expensive operations: 적절한 경우 토큰, URL 또는 Provider 구성을 캐시하세요

  4. Validate environment variables: Check for required environment variables in getApiKey and buildUrl

  5. Document your gateway: Gateway의 용도와 구성을 설명하는 JSDoc 주석을 추가하세요

  6. Follow naming conventions: Provider와 Model에 명확하고 일관된 이름을 사용하세요

  7. Handle async operations: Use async/await for network requests and I/O operations

  8. Test thoroughly: Write unit tests for all gateway methods

Showing only custom gateways in Studio
Showing only custom gateways in Studio에 대한 직접 링크

By default, Studio 에는 등록한 모든 사용자 지정 Gateway와 함께 모든 외부 Model Provider(예: OpenAI, Anthropic, Gemini)가 나열됩니다. 외부 Provider를 숨기려면 AUTO_BLOCK_EXTERNAL_PROVIDERS environment variable:

AUTO_BLOCK_EXTERNAL_PROVIDERS=true

When this variable is set to true or 1로 설정하면 Mastra는 직접 등록한 Gateway의 Provider만 반환합니다. 정적 Provider 레지스트리와 기본 제공 Gateway(models.dev, netlify, and mastra)는 Model 선택기에서 숨겨집니다. 모든 Model 트래픽을 하나의 비공개 Gateway를 통해 라우팅하고 다른 Provider가 표시되지 않도록 하려는 경우 유용합니다.

이 변수가 설정되어 있고 등록된 사용자 지정 Gateway가 없으면 Model 선택기가 비어 있습니다. Model을 표시하려면 사용자 지정 Gateway를 하나 이상 등록하세요.

Built-in Gateways
Built-in Gateways에 대한 직접 링크

Mastra includes built-in gateways as reference implementations:

  • NetlifyGateway: Netlify AI Gateway integration with token exchange
  • ModelsDevGateway: Registry of OpenAI-compatible providers from models.dev

See Netlify, OpenRouter, and Vercel for examples of gateway usage.