Cargando…

Esto está tardando más de lo esperado.

Conecta un proveedor de IA

Los proveedores que conoce config/ai.php, las dos funciones que los usan y cómo llamar a uno tú mismo.

El kit incluye el SDK de Laravel AI (laravel/ai, versión 0.6.8) y un config/ai.php que ya nombra quince proveedores. Dos funciones lo usan: la traducción automática detrás de php artisan lang:sync, y el asistente del equipo de soporte, que siempre habla con anthropic (la guía «Asistente de soporte», para el equipo de soporte). Léelo para darle un proveedor a ese comando, para saber cuáles de las muchas llaves de config/ai.php hacen algo hoy en realidad, y para llamar a un modelo desde tu propio código sin cablear nada nuevo.

Qué está configurado

config/ai.php tiene tres partes.

Valores por omisión. Qué proveedor responde cuando una llamada no nombra uno, por tipo de trabajo. Son valores committeados, no variables de entorno; edita el archivo para cambiarlos.

Llave Valor por omisión Se usa para
default anthropic Texto: agentes y prompts.
default_for_images gemini Generación de imágenes.
default_for_audio openai Síntesis de voz.
default_for_transcription openai Voz a texto.
default_for_embeddings openai Embeddings vectoriales.
default_for_reranking cohere Reordenar resultados de búsqueda.

Caché. caching.embeddings.cache es false; ponlo en true y el SDK guarda los embeddings generados en el almacén de caché que nombra caching.embeddings.store (CACHE_STORE, valor por omisión database).

Proveedores. Cada entrada empareja un driver con las variables de entorno que lo autentican. Poner una variable no hace nada por sí solo: un proveedor sólo se llama cuando es el valor por omisión para un tipo de trabajo o una llamada lo nombra.

Proveedor Variables Valor por omisión
anthropic ANTHROPIC_API_KEY, ANTHROPIC_URL URL https://api.anthropic.com/v1
azure AZURE_OPENAI_API_KEY, AZURE_OPENAI_URL, AZURE_OPENAI_API_VERSION, AZURE_OPENAI_DEPLOYMENT, AZURE_OPENAI_EMBEDDING_DEPLOYMENT, AZURE_OPENAI_IMAGE_DEPLOYMENT Versión 2025-04-01-preview; deployments gpt-4o, text-embedding-3-small, gpt-image-1
bedrock AWS_BEARER_TOKEN_BEDROCK, AWS_BEDROCK_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, AWS_USE_DEFAULT_CREDENTIALS Región us-east-1; proveedor de credenciales por omisión activo
cohere COHERE_API_KEY
deepseek DEEPSEEK_API_KEY
eleven ELEVENLABS_API_KEY
gemini GEMINI_API_KEY, GEMINI_URL URL https://generativelanguage.googleapis.com/v1beta/
groq GROQ_API_KEY
jina JINA_API_KEY
mistral MISTRAL_API_KEY
ollama OLLAMA_API_KEY, OLLAMA_URL Llave vacía; URL http://localhost:11434
openai OPENAI_API_KEY, OPENAI_URL URL https://api.openai.com/v1
openrouter OPENROUTER_API_KEY
voyageai VOYAGEAI_API_KEY
xai XAI_API_KEY

Sólo OPENAI_API_KEY aparece en .env.example, vacía. Aparte de ANTHROPIC_API_KEY, que necesita el asistente de soporte, todas las demás variables las lee config/ai.php y nada más en el kit: disponibles, pero no conectadas a ninguna función. La entrada bedrock comparte AWS_ACCESS_KEY_ID y AWS_SECRET_ACCESS_KEY con el sistema de archivos S3, así que llenarlas para el almacenamiento de archivos también llena las credenciales de Bedrock, sin que nada llame a Bedrock.

config/services.php no guarda credenciales de IA: sus entradas son Mailgun, Postmark, Resend, SES, Telnyx, el servicio world de Weblabor, Stripe y Facebook.

Qué usa el kit hoy

Un solo camino, del comando a la red:

php artisan lang:sync
  → App\Services\LangSyncService
    → App\Services\LangTranslatorService::translate()
      → App\Ai\Agents\TranslationAgent::make(locale: $locale)->prompt($text, provider: config('ai.default'))

lang:sync recorre cada idioma en lang/ y, por cada llave que el inglés tiene y al idioma le falta, le pide una traducción al agente. Las instrucciones del agente le dicen al modelo que traduzca al idioma destino, conserve el significado y el tono, preserve los marcadores de posición y devuelva sólo el texto traducido. Antes de la llamada el servicio reemplaza cada marcador de Laravel como :name con una marca (__PH0__) y la restaura después, así que un marcador nunca puede volver traducido.

El proveedor es el que nombre default en config/ai.php, anthropic tal como se entrega. El modelo es el modelo de texto más barato del proveedor, no el de por omisión: el agente lleva el atributo #[UseCheapestModel] del SDK, porque una sincronización traduce muchos textos cortos y el modelo más grande cuesta más sin traducirlos mejor. Para Anthropic en esta versión del SDK es Haiku, claude-haiku-4-5-20251001. Si cambias default, las traducciones siguen al modelo más barato de ese proveedor. Para elegir otro modelo sin tocar el agente, fija el modelo de texto más barato en un bloque models de la entrada del proveedor:

'anthropic' => [
    'driver' => 'anthropic',
    'key' => env('ANTHROPIC_API_KEY'),
    'url' => env('ANTHROPIC_URL', 'https://api.anthropic.com/v1'),
    'models' => [
        'text' => ['cheapest' => 'claude-haiku-4-5-20251001'],
    ],
],

El comando decide si un proveedor está configurado antes de la primera llamada. El proveedor por omisión cuenta como configurado cuando su key está llena, o cuando su driver es ollama, que no necesita llave. De lo contrario cada llave faltante se escribe en inglés con la advertencia "AI translation provider is not configured", y el comando termina de todos modos: nada más en lang:sync depende de la red. Una llamada que falla o no devuelve nada se maneja igual, con la advertencia "Translation failed for", así que una llave mala o una cuota agotada te deja con texto en inglés para traducir a mano, nunca con un archivo roto.

Entonces, para encender la traducción con Anthropic:

ANTHROPIC_API_KEY=sk-ant-your-key

Para traducir con otro proveedor, pon su llave y cambia default en config/ai.php a su nombre, por ejemplo 'default' => 'openai'. Para traducir en local sin llave alguna, instala Ollama, descarga un modelo y pon 'default' => 'ollama'; el modelo más barato ahí es llama3.1:8b, y OLLAMA_URL apunta el SDK a otro host.

El flujo completo de traducción, incluidos los idiomas que un usuario puede elegir y los demás comandos lang:*, está en /help/languages-and-translations.

El segundo camino es el asistente del equipo de soporte. No lee default: siempre llama a anthropic con ANTHROPIC_API_KEY y el modelo de FEATURE_ASSISTANT_MODEL, así que cambiar el proveedor de las traducciones nunca lo mueve. La guía «Asistente de soporte» lo explica, y sus ajustes están en Configura tu proyecto.

Dos cosas más existen porque el SDK se instaló:

  • La migración 2026_05_15_155312_create_agent_conversations_table crea las tablas agent_conversations y agent_conversation_messages. Son el almacén de conversaciones del SDK, para agentes que recuerdan un chat. El asistente de soporte guarda ahí sus conversaciones; nada más escribe en ellas.
  • stubs/agent.stub, structured-agent.stub, agent-middleware.stub y tool.stub son las plantillas que usan make:agent, make:agent --structured, make:agent-middleware y make:tool. El kit no las usa.

Nada en el kit envía datos de usuarios, contenido ni prompts a ningún proveedor aparte de las cadenas de traducción de arriba, sólo cuando corres lang:sync, y, mientras el asistente de soporte está encendido, lo que lee para responder las preguntas del equipo: el código del proyecto y los resultados de sus consultas de sólo lectura a la base de datos, sin contraseñas, tokens ni otras credenciales.

Llama a un proveedor desde tu propio código

No necesitas una librería cliente ni una clase de servicio. Genera un agente, dale instrucciones y hazle un prompt; el text de la respuesta es la respuesta del modelo.

php artisan make:agent SummaryAgent
<?php

namespace App\Ai\Agents;

use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Promptable;
use Stringable;

class SummaryAgent implements Agent
{
    use Promptable;

    public function instructions(): Stringable|string
    {
        return 'Summarize the text you receive in one sentence. Return only the sentence.';
    }
}
$summary = SummaryAgent::make()->prompt('The long text to summarize...')->text;

Esa llamada usa el proveedor default y su modelo de texto por omisión. Para fijar un proveedor o un modelo, pásalos a prompt() o decláralos en la clase:

use Laravel\Ai\Attributes\{Model, Provider};
use Laravel\Ai\Enums\Lab;

#[Provider(Lab::Anthropic)]
#[Model('claude-sonnet-4-6')]
class SummaryAgent implements Agent
{
    // ...
}

// o por llamada
SummaryAgent::make()->prompt($text, provider: 'gemini', model: 'gemini-3-flash-preview');

Lab es el enum de los quince nombres de proveedor; una cadena simple con el mismo nombre también funciona. stream() devuelve la respuesta conforme se produce, queue() corre el prompt como un job. Para un prompt suelto sin clase, la función agent() construye un agente anónimo:

use function Laravel\Ai\agent;

$answer = agent('You answer in one word.')->prompt('What colour is the sky?')->text;

Las imágenes y los embeddings tienen sus propios puntos de entrada, enrutados a default_for_images y default_for_embeddings:

use Laravel\Ai\{Embeddings, Image};

$image = Image::of('A lighthouse at dusk')->square()->generate();
$vectors = Embeddings::for(['first text', 'second text'])->generate();

En una prueba, SummaryAgent::fake(['a canned answer']) reemplaza la red con las respuestas que listes, e Image::fake() y Embeddings::fake() hacen lo mismo con las suyas. php artisan agent:chat abre una conversación con uno de tus agentes en la terminal, que es la forma más rápida de comprobar que una llave funciona.

Sigue la forma del propio kit cuando agregues uno: mantén el agente en app/Ai/Agents, llámalo desde un método de modelo o un servicio y no desde un componente Livewire, y verifica la llave antes de la llamada como hace LangTranslatorService, para que un proveedor faltante se degrade a un mensaje y no a una excepción.

Volver