> Discover all available pages from the documentation index: https://mastra.zisheng.pro/fr/llms.txt # Passerelles de modèles personnalisées Les passerelles de modèles personnalisées permettent d’implémenter des intégrations LLM privées ou spécialisées avec l’interface `MastraModelGatewayInterface` ou la classe de base `MastraModelGateway`. ## Vue d’ensemble Les passerelles gèrent la logique propre aux Providers pour accéder aux modèles de langage : - Configuration des Providers et découverte des modèles - Authentification et gestion des clés API - Construction des URL des points de terminaison d’API - Création d’instances de modèles de langage Créez des passerelles personnalisées pour prendre en charge : - Déploiements LLM privés ou d’entreprise - Mécanismes d’authentification personnalisés - Logique de routage spécialisée - Gestion des versions des passerelles avec des ID uniques ## Créer une passerelle personnalisée Implémentez `MastraModelGatewayInterface` pour une passerelle sous forme d’objet simple, ou étendez `MastraModelGateway` lorsque vous souhaitez les valeurs par défaut de la classe de base. ```typescript 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> { 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); }, }; ``` L’exemple suivant étend la classe `MastraModelGateway` : ```typescript 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> { 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 { return 'https://api.myprovider.com/v1'; } /** * Get the API key for authentication * @param modelId - Full model ID */ async getApiKey(modelId: string): Promise { 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 { const baseURL = this.buildUrl(`${providerId}/${modelId}`); return createOpenAICompatible({ name: providerId, apiKey, baseURL, supportsStructuredOutputs: true, }).chatModel(modelId); } } ``` ### Authentification gérée par la passerelle Ajoutez `resolveAuth` lorsque la passerelle gère la recherche des identifiants. Mastra utilise ce hook avant de recourir à `getApiKey()`. ```typescript const myPrivateGateway: MastraModelGatewayInterface = { // ...gateway fields and methods async resolveAuth() { const apiKey = process.env.MY_API_KEY; return apiKey ? { apiKey, source: 'gateway' } : undefined; }, }; ``` ## Enregistrer des passerelles personnalisées ### Lors de l’initialisation Transmettez les passerelles sous forme d’enregistrement lors de la création de votre instance Mastra : ```typescript import { Mastra } from '@mastra/core'; const mastra = new Mastra({ gateways: { myGateway: new MyPrivateGateway(), anotherGateway: new AnotherGateway(), }, }); ``` ### Après l’initialisation Ajoutez des passerelles dynamiquement avec `addGateway` : ```typescript 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) ``` ## Utiliser des passerelles personnalisées Référencez les modèles de votre passerelle personnalisée en utilisant l’ID de la passerelle comme préfixe : ```typescript 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'); ``` Lorsque vous créez un Agent ou utilisez un modèle, le routeur de modèles de Mastra sélectionne automatiquement la passerelle appropriée selon l’ID du modèle. L’ID de la passerelle sert de préfixe. Si aucune passerelle personnalisée ne correspond, il revient aux passerelles intégrées. ### Autocomplétion TypeScript #### Génération automatique des types en développement En mode développement (`MASTRA_DEV=true`), Mastra génère automatiquement les types TypeScript de vos passerelles personnalisées. 1. **Définissez la variable d’environnement** : ```bash export MASTRA_DEV=true ``` 2. **Enregistrez vos passerelles** : ```typescript const mastra = new Mastra({ gateways: { myGateway: new MyPrivateGateway(), }, }); ``` 3. **Les types sont générés automatiquement** : - Lorsque vous ajoutez une passerelle, Mastra se synchronise avec le GatewayRegistry - Le registre récupère les Providers depuis votre passerelle personnalisée - Les types TypeScript sont régénérés dans `~/.cache/mastra/` - Votre IDE détecte les nouveaux types en quelques secondes 4. **L’autocomplétion fonctionne désormais** : ```typescript const agent = new Agent({ model: 'my-gateway-id/my-provider/model-1', // Full autocomplete! }); ``` #### Fonctionnement Le GatewayRegistry exécute une synchronisation horaire qui : - appelle `fetchProviders()` sur toutes les passerelles enregistrées ; - génère les définitions de types TypeScript ; - les écrit dans le cache global et dans le répertoire `dist/` de votre projet ; - permet à votre serveur TypeScript de détecter automatiquement les modifications. > **Astuce:** La première fois que vous ajoutez une passerelle, la génération des types peut prendre quelques secondes. Les mises à jour suivantes sont effectuées en arrière-plan toutes les heures. #### Autres méthodes de génération manuelle des types Si vous n’exécutez pas le mode développement ou avez besoin de mises à jour immédiates des types : **Option 1 : utiliser une assertion de type (méthode la plus simple)** ```typescript 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 : créer une union de types personnalisée (avec sûreté des types)** ```typescript 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 : étendre ModelRouterModelId globalement (avancé)** ```typescript // 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']; } } ``` Cela étend le type intégré pour inclure vos modèles personnalisés et vous offre une prise en charge complète de l’autocomplétion. ## Gestion des passerelles ### getGateway(key) Récupérez une passerelle par sa clé d’enregistrement : ```typescript const gateway = mastra.getGateway('myGateway'); console.log(gateway.name); // 'My Private Gateway' ``` ### getGatewayById(id) Récupérez une passerelle par son ID unique : ```typescript const gateway = mastra.getGatewayById('my-private-gateway'); console.log(gateway.name); // 'My Private Gateway' ``` Cela est utile lorsque : - les passerelles possèdent des ID explicites différents de leurs clés d’enregistrement ; - vous devez rechercher une passerelle par son ID parmi différentes instances ; - vous prenez en charge la gestion des versions des passerelles (par exemple, `'gateway-v1'`, `'gateway-v2'`). ### listGateways() Obtenez toutes les passerelles enregistrées : ```typescript const gateways = mastra.listGateways(); console.log(Object.keys(gateways)); // ['myGateway', 'anotherGateway'] ``` ## Propriétés de la passerelle ### Obligatoire | Propriété | Type | Description | | --------- | -------- | ------------------------------------------------------------------------------------------------- | | `id` | `string` | Identifiant unique de la passerelle, utilisé comme préfixe de passerelle dans la chaîne du modèle | | `name` | `string` | Nom lisible de la passerelle | ### Méthodes | Méthode | Description | | ----------------------------- | ------------------------------------------------------ | | `fetchProviders()` | Récupère les configurations des Providers | | `buildUrl(modelId, envVars?)` | Construit l’URL d’API d’un modèle | | `getApiKey(modelId)` | Obtient la clé API d’authentification | | `resolveLanguageModel(args)` | Crée une instance de modèle de langage | | `getId()` | Obtient l’ID de la passerelle (renvoie `id` ou `name`) | ## Configuration du Provider La méthode `fetchProviders()` renvoie un enregistrement d’objets `ProviderConfig` : ```typescript 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 } ``` ## ID et clés de passerelle Comprendre la distinction : - **Clé** : clé d’enregistrement utilisée lors de l’ajout de la passerelle à Mastra (clé de l’enregistrement) - **ID** : identifiant unique de la passerelle (via la propriété `id`, ou `name` si elle n’est pas définie) ```typescript 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 ``` ## Format de l’ID de modèle Les modèles accessibles via des passerelles personnalisées suivent ce format : ```text [gatewayId]/[provider]/[model] ``` Exemples : - `private/my-provider/model-1` ## Exemple avancé Passerelle fondée sur des jetons avec cache : ```typescript class TokenGateway extends MastraModelGateway { readonly id = 'token-gateway-v1'; readonly name = 'Token Gateway'; private tokenCache: Map = new Map(); async fetchProviders(): Promise> { 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): Promise { 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 { 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 { const baseURL = await this.buildUrl(`${providerId}/${modelId}`); return createOpenAICompatible({ name: providerId, apiKey, baseURL, supportsStructuredOutputs: true, }).chatModel(modelId); } } ``` ## Gestion des erreurs Fournissez des erreurs descriptives pour les scénarios d’échec courants : ```typescript class RobustGateway extends MastraModelGateway { // ... properties async getApiKey(modelId: string): Promise { 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): Promise { 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; } } ``` ## Tester des passerelles personnalisées Exemple de structure de test : ```typescript 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(); }); }); ``` ## Bonnes pratiques 1. **Utilisez des ID explicites pour la gestion des versions** : définissez des valeurs `id` explicites lorsque vos passerelles doivent être versionnées ```typescript readonly id = 'my-gateway-v1'; ``` 2. **Implémentez une gestion appropriée des erreurs** : levez des erreurs descriptives accompagnées de messages exploitables 3. **Mettez en cache les opérations coûteuses** : mettez en cache les jetons, les URL ou les configurations de Provider lorsque cela est pertinent 4. **Validez les variables d’environnement** : vérifiez les variables d’environnement requises dans `getApiKey` et `buildUrl` 5. **Documentez votre passerelle** : ajoutez des commentaires JSDoc qui expliquent son objectif et sa configuration 6. **Respectez les conventions de nommage** : utilisez des noms clairs et cohérents pour les Providers et les modèles 7. **Gérez les opérations asynchrones** : utilisez `async/await` pour les requêtes réseau et les opérations d’E/S 8. **Testez minutieusement** : écrivez des tests unitaires pour toutes les méthodes de la passerelle ## N’afficher que les passerelles personnalisées dans Studio Par défaut, **Studio** liste chaque Provider de modèles externe (tel qu’OpenAI, Anthropic ou Gemini) en plus des passerelles personnalisées que vous enregistrez. Pour masquer les Providers externes, définissez la variable d’environnement `AUTO_BLOCK_EXTERNAL_PROVIDERS` : ```bash AUTO_BLOCK_EXTERNAL_PROVIDERS=true ``` Lorsque cette variable vaut `true` ou `1`, Mastra ne renvoie que les Providers des passerelles que vous enregistrez vous-même. Le registre statique des Providers et les passerelles intégrées (`models.dev`, `netlify` et `mastra`) sont masqués du sélecteur de modèles. C’est utile lorsque vous acheminez tout le trafic de modèles par une passerelle privée unique et ne souhaitez pas afficher les autres Providers. Avec cette variable définie et sans passerelle personnalisée enregistrée, le sélecteur de modèles est vide. Enregistrez au moins une passerelle personnalisée pour exposer ses modèles. ## Passerelles intégrées Mastra inclut des passerelles intégrées comme implémentations de référence : - **NetlifyGateway** : intégration de Netlify AI Gateway avec échange de jetons - **ModelsDevGateway** : registre des Providers compatibles avec OpenAI provenant de models.dev Consultez [Netlify](https://mastra.zisheng.pro/fr/models/gateways/netlify), [OpenRouter](https://mastra.zisheng.pro/fr/models/gateways/openrouter) et [Vercel](https://mastra.zisheng.pro/fr/models/gateways/vercel) pour des exemples d’utilisation des passerelles.