Novedades de Laravel 13: atributos PHP, AI SDK y passkeys
Qué trae Laravel 13 (17 de marzo de 2026) y por qué es el upgrade más suave de la historia del framework: atributos PHP 8 para declarar modelos, jobs y comandos; el AI SDK ya de primera clase y agnóstico de proveedor; login sin contraseña con passkeys; Reverb con driver de base de datos para tiempo real sin Redis; Cache::touch(); y una guía de migración con cero cambios que rompen.
Laravel 13 salió el 17 de marzo de 2026 con una promesa que suena a contradicción: es a la vez el lanzamiento más aburrido y el más ambicioso en años. Aburrido porque no rompe nada —puedes subir de la 12 a la 13 casi sin tocar código—; ambicioso porque, por debajo de esa calma, mete IA de primera clase en el framework, login sin contraseñas y una forma nueva y más limpia de declarar tus clases. En este recorrido vamos por todo lo que importa, con el código a la vista, y al final te digo cuándo conviene migrar y cuándo esperar.
El requisito de entrada
Laravel 13 sube el mínimo a PHP 8.3 (la 12 pedía 8.2). Es el único requisito duro del salto: si ya corres 8.3 o más, el resto del upgrade es prácticamente cambiar un número en tu composer.json. Volvemos a ello en la sección de migración.
La arquitectura de Laravel en 30 segundos
Antes de entrar en lo nuevo, conviene recordar por dónde viaja una petición: casi todas las novedades de la 13 se enganchan en algún punto de ese recorrido. Toda petición entra por un único archivo (public/index.php), pasa por el kernel, atraviesa la pila de middleware, la resuelve el router hacia un controlador, y este apoya en los modelos de Eloquent antes de devolver una respuesta —que a veces también sale en tiempo real por WebSockets.
Con ese mapa en la cabeza, las novedades dejan de ser una lista suelta: los atributos ordenan tus modelos y jobs, el AI SDK vive en tus controladores y servicios, los passkeys blindan la puerta de entrada, y Reverb cambia cómo sale la respuesta en tiempo real. Vamos una por una.
Atributos PHP: menos ruido en tus clases
Es el cambio de developer experience más visible de la 13. Durante años, configurar un modelo, un job o un comando significó declarar propiedades protegidas al inicio de la clase: $table, $fillable, $hidden, y así. Laravel 13 añade una alternativa con atributos de PHP 8 en alrededor de quince lugares del framework: modelos, jobs, comandos, listeners, notificaciones, mailables, form requests, resources y factories, entre otros.
Lo importante: es opcional y retrocompatible. Las propiedades de toda la vida siguen funcionando exactamente igual; los atributos son azúcar sintáctico para quien quiera declarar la intención arriba, sobre la clase, en lugar de dentro.
La configuración del modelo sube a la cabecera de la clase, y el cuerpo queda para la lógica de negocio.
use Illuminate\Database\Eloquent\Attributes\{Table, Fillable, Hidden};
use Illuminate\Database\Eloquent\Model;
#[Table('invoices')]
#[Fillable('amount', 'status', 'user_id')]
#[Hidden('internal_notes')]
class Invoice extends Model
{
// La lógica de negocio se ve de inmediato, sin propiedades de configuración arriba.
}
El equivalente clásico —que sigue siendo válido— era declarar protected $table, protected $fillable y protected $hidden. Hay atributos para casi todo lo habitual: #[Guarded], #[Appends], #[Connection], #[Touches] y #[Visible], entre otros.
No es una migración obligatoria
No tienes que reescribir tus modelos. Los atributos brillan en clases nuevas o cuando quieres que la configuración salte a la vista; en un proyecto grande puedes adoptarlos poco a poco, o no adoptarlos. Conviven sin fricción con el estilo de propiedades.
El AI SDK ya es de primera clase
La novedad estrella. El Laravel AI SDK, que venía como paquete en beta, ahora es un componente estable y de primera clase del framework, y —clave— es agnóstico de proveedor: hablas con Anthropic, OpenAI, Gemini y otros con la misma API, y cambiar de uno a otro es cambiar un valor de configuración, no reescribir código.
Primero configuras tus proveedores. Las claves viven en el .env y el SDK trae config/ai.php:
// config/ai.php
'providers' => [
'anthropic' => [
'driver' => 'anthropic',
'key' => env('ANTHROPIC_API_KEY'),
],
'openai' => [
'driver' => 'openai',
'key' => env('OPENAI_API_KEY'),
],
],
El SDK organiza el trabajo en agentes. Generas uno con Artisan y describes su comportamiento en instructions():
php artisan make:agent SalesCoach
use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Promptable;
class SalesCoach implements Agent
{
use Promptable;
public function instructions(): string
{
return 'Eres un coach de ventas experto. Respondes breve y accionable.';
}
}
Y lo usas donde lo necesites —un controlador, un job, un comando— con prompt():
$respuesta = (new SalesCoach)->prompt('Dame tres ideas para reactivar clientes dormidos.');
return (string) $respuesta;
Para algo rápido, ni siquiera necesitas una clase
Si solo quieres una respuesta puntual, el helper agent() evita crear un agente completo:
use function Laravel\Ai\agent;
$respuesta = agent(
instructions: 'Eres experto en desarrollo de software.',
)->prompt('Explica en dos frases qué es una cola de trabajos.');
Failover entre proveedores
Aquí es donde el diseño agnóstico paga. Con un atributo declaras un orden de respaldo: si el proveedor principal falla —cae, te limita por rate limit o da error—, el SDK reintenta con el siguiente, sin que tu código se entere.
use Laravel\Ai\Attributes\{Provider, Model};
use Laravel\Ai\Enums\Lab;
#[Provider([Lab::Anthropic, Lab::OpenAI])] // primero Anthropic; si falla, OpenAI
#[Model('claude-sonnet-4-6')]
class SalesCoach implements Agent
{
use Promptable;
public function instructions(): string
{
return 'Eres un coach de ventas experto.';
}
}
Salida estructurada y RAG
Cuando no quieres texto libre sino un objeto con forma fija, tu agente implementa HasStructuredOutput y declara un esquema. El SDK te devuelve datos validados, con acceso tipo arreglo:
use Illuminate\Contracts\JsonSchema\JsonSchema;
use Laravel\Ai\Contracts\{Agent, HasStructuredOutput};
use Laravel\Ai\Promptable;
class LeadScorer implements Agent, HasStructuredOutput
{
use Promptable;
public function instructions(): string
{
return 'Evalúas la calidad de un lead comercial.';
}
public function schema(JsonSchema $schema): array
{
return [
'score' => $schema->integer()->min(1)->max(10)->required(),
'feedback' => $schema->string()->required(),
];
}
}
$resultado = (new LeadScorer)->prompt('Empresa mediana, presupuesto claro, decisor identificado.');
return $resultado['score']; // acceso como arreglo
Y para retrieval-augmented generation tienes embeddings de primera clase, con un ayudante muy a la mano sobre Str:
use Illuminate\Support\Str;
use Laravel\Ai\Embeddings;
// Un texto suelto
$vector = Str::of('Napa Valley produce excelente vino.')->toEmbeddings();
// Varios de una vez
$respuesta = Embeddings::for([
'Napa Valley produce excelente vino.',
'Laravel es un framework de PHP.',
])->generate();
Un SDK, no solo un cliente
El AI SDK no es un simple envoltorio de la API de un proveedor: trae agentes con herramientas (tools), sub-agentes, búsqueda por similitud para RAG (SimilaritySearch), streaming de respuestas, memoria de conversación y aprobación humana de acciones sensibles. Aquí vimos lo esencial; la documentación oficial cubre el resto.
Passkeys: adiós a las contraseñas
Una de las funciones más pedidas por la comunidad. Laravel 13 integra autenticación con passkeys (WebAuthn) directamente en Fortify y en los starter kits: tus usuarios pueden entrar sin contraseña usando Touch ID, Face ID, Windows Hello o una llave física de seguridad.
La idea de fondo es criptografía de clave pública. Al registrarse, el dispositivo del usuario genera un par de claves: la privada nunca sale del dispositivo (protegida por su biometría o PIN), y la pública se guarda en tu base de datos. Para iniciar sesión, tu servidor lanza un reto aleatorio, el dispositivo lo firma con la clave privada, y tu servidor verifica esa firma con la clave pública que ya tenía. Nunca viaja un secreto reutilizable, así que el phishing y las filtraciones de contraseñas dejan de aplicar.
Qué cubre lo integrado
El soporte que viene en los starter kits resuelve el caso estándar: registrar un passkey y usarlo para entrar, sin instalar nada extra. Para escenarios avanzados —gestión de varios dispositivos por usuario, políticas finas— sigue habiendo paquetes especializados de WebAuthn en el ecosistema, pero para la mayoría de las apps lo de serie basta.
Reverb con driver de base de datos
Reverb es el servidor WebSocket propio de Laravel para tiempo real (notificaciones en vivo, presencia, chats). Hasta ahora, escalarlo a varios procesos exigía Redis como capa de coordinación. Laravel 13 añade un driver de base de datos: puedes usar tu MySQL o PostgreSQL de siempre para ese escalado horizontal, sin sumar Redis a tu infraestructura.
// config/reverb.php
'scaling' => [
'driver' => 'database', // usa tu MySQL/PostgreSQL en lugar de Redis
],
Hasta dónde llega
El driver de base de datos está pensado para apps que quieren tiempo real sin la complejidad de Redis, típicamente por debajo de unos mil conexiones concurrentes. Si tu carga es alta y sostenida, Redis sigue siendo la opción de mayor rendimiento para la coordinación entre nodos. Es una puerta de entrada más barata, no un reemplazo universal.
Un extra pequeño y muy útil: Cache::touch()
A veces solo quieres renovar el tiempo de vida de una entrada en caché sin volver a leer ni reescribir su valor —piensa en una sesión que quieres mantener viva mientras el usuario está activo. Antes, eso implicaba un ciclo de leer y volver a guardar:
// Antes: dos operaciones y transferir todo el valor de ida y vuelta
$valor = Cache::get('user_session:123');
Cache::put('user_session:123', $valor, now()->addHour());
Laravel 13 lo resuelve con Cache::touch(), que extiende el TTL en una sola operación —EXPIRE en Redis, TOUCH en Memcached, un UPDATE en base de datos—, sin mover el valor:
// Ahora: una sola operación, sin transferir el valor
Cache::touch('user_session:123', 3600); // 3600 s de nuevo TTL
Devuelve true si la clave existía y false si no. Un detalle pequeño, pero que en rutas calientes ahorra ancho de banda y viajes de ida y vuelta.
Migrar a Laravel 13
La gran noticia operativa: cero cambios que rompen. El salto de la 12 a la 13 es, para la mayoría de proyectos, cuestión de minutos.
Sube a PHP 8.3 o superior
Es el único requisito duro. Verifica tu versión con php -v y actualiza el entorno (local, CI y producción) si aún corres 8.2.
Apunta a la versión 13 en composer.json
Ajusta la restricción del framework y actualiza dependencias.
"require": {
"php": "^8.3",
"laravel/framework": "^13.0"
}
composer update
Corre tu suite de pruebas
Al no haber cambios que rompan, tus tests deberían pasar sin tocarse. Si algo falla, casi siempre será por un paquete de terceros que todavía no declara compatibilidad con la 13, no por el framework.
Ya corres PHP 8.3, tus dependencias principales están al día y quieres empezar limpio: proyectos nuevos, o apps con buena cobertura de tests donde el upgrade es de bajo riesgo. Si además vas a tocar IA, tiempo real o autenticación, la 13 te da esas piezas de serie.
Dependes de paquetes de terceros que aún no publican compatibilidad con la 13, o sigues atado a PHP 8.2 por tu infraestructura. No hay prisa: la 12 tiene soporte por buen tiempo, y el upgrade seguirá siendo suave cuando tus dependencias se pongan al día.
La ventana de soporte
Laravel 13 recibirá corrección de errores hasta el tercer trimestre de 2027 y parches de seguridad hasta el primer trimestre de 2028. Tiempo de sobra para planear el salto con calma.
Cierre
Laravel 13 acierta en el equilibrio difícil: avanza sin castigarte. Te da IA de primera clase, autenticación sin contraseñas y tiempo real más barato, y a la vez te deja subir de versión casi sin abrir el código. Esa es la marca de un framework maduro —el que entiende que la mejor característica nueva es la que no te obliga a reescribir lo que ya funciona. Si estabas posponiendo el salto por miedo a la factura de un major, esta vez la excusa se quedó sin fundamento.
Fuentes
- Laravel AI SDK — documentación oficial (Laravel 13.x)
- Introducing the Laravel AI SDK (blog oficial de Laravel)
- What We Know About Laravel 13 (Laravel News)
- Laravel 13 drops March 17 — every new feature with code examples (DEV Community)
- Laravel 13: PHP Attributes, Passkeys, Zero Breaking Changes (byteiota)
Artículos relacionados
Relaciones polimórficas en Laravel 13: una tabla para muchos dueños
Qué es una tabla polimórfica, por qué resuelve el problema de compartir comentarios, imágenes o etiquetas entre varios modelos, y cómo se implementa en Laravel 13 con morphOne, morphMany y morphToMany —migraciones, morph map, carga sin N+1 y cuándo conviene evitarlas.
De un reto técnico a un SPA full-stack: Angular 19, Express y Firebase
Caso de estudio: cómo resolví un reto técnico full-stack —una app de tareas con login, CRUD y estado— con Angular 19, un API Express + TypeScript en Cloud Functions y Firestore, aplicando arquitectura hexagonal, SOLID y buenas prácticas.
