---
title: "Laravel Tackle: el agente de IA que vive dentro de tu app"
excerpt: "Tackle no es otra CLI de agente: se instala con Composer y corre como comandos Artisan, así que ve tus rutas, tu Telescope y tus tests. Y los límites no se le piden por prompt, están en PHP. Cómo funciona, el autocurador de colas y por qué su base es la parte frágil."
date: "2026-08-20T10:30:00.000Z"
category: "Laravel"
author:
  name: "angel cruz"
  picture: "/images/me/angel-cruz.png"
ogImage:
  url: "/images/open-graph/tackle-opengraph-image.png"
seo_title: "Laravel Tackle: agente de IA dentro de tu app Laravel"
seo_description: "Qué es Laravel Tackle: un harness de agentes de IA que se instala por Composer y corre como comandos Artisan, con límites de shell, presupuesto y rutas protegidos en PHP. Instalación, autocurador de colas y riesgos."
tech_article:
  article_section: "Laravel"
  keywords: "laravel tackle, agente ia laravel, laravel ai, ai:code artisan, autocurar colas laravel, agente codigo php, harness agentes laravel, jordan dalton tackle"
---

**Laravel Tackle es un harness de agentes de IA que se instala con Composer y corre como comandos Artisan dentro de tu propia aplicación.** No es una CLI que abre tu carpeta desde fuera: vive dentro del framework, así que puede listar tus rutas, consultar tu base de datos, leer una excepción de Telescope y formatear con Pint porque esas herramientas ya están ahí.

Y la parte que de verdad me interesó: **los límites están escritos en PHP, no pedidos por prompt**. Las rutas protegidas, la lista blanca de comandos y el techo de gasto no son instrucciones que el modelo pueda decidir ignorar, son código que se ejecuta antes que él.

Lo publicó [Jordan Dalton](https://github.com/jordandalton/laravel-tackle) y [Laravel News le dedicó una nota](https://laravel-news.com/laravel-tackle), que es por donde le llegó visibilidad. Aviso de siempre: esto sale del repositorio, del README y de Packagist, no de haberlo puesto en producción yo.

## La diferencia real con Claude Code

Cuando usas [Claude Code en un proyecto Laravel](/post/claude-code-proyecto-laravel), el agente ve archivos. Sabe leer PHP, entiende el framework porque lo tiene en el entrenamiento, y si le pones Boost aprende un poco más. Pero está fuera: para saber qué rutas existen tiene que abrir los archivos de rutas y deducirlas.

Tackle invierte eso. Al correr como comando Artisan está **dentro del ciclo de vida de la aplicación**, con el contenedor de servicios levantado. Cuando quiere saber las rutas, llama a la herramienta `ListRoutes`, que es tu `route:list` de verdad, con los middlewares resueltos. Cuando quiere entender un fallo, `ReadTelescopeEntry` le da la entrada real. Puede correr `RunLarastan` o consultar la base con `QueryDatabase`.

La arquitectura son tres capas, y así las describe el propio README:

| Capa | Qué es |
|---|---|
| **Tools** | Primitivas de acción: `ReadFile`, `EditFile`, `RunTests`, `RunShell`. Cada una pasa por `PathGuard` y por la política de shell antes de ejecutarse. |
| **Agents** | Clases que implementan `CodingAgent`, reciben un prompt, llaman herramientas y devuelven un resultado. Vienen tres, puedes añadir las tuyas. |
| **Safety** | `PathGuard` bloquea lecturas y escrituras fuera del workspace. `BudgetTracker` aborta la sesión al pasar el límite de gasto. Los modos de shell controlan la ejecución de comandos. |

La frase que cierra esa tabla en el README es la tesis del proyecto entero: "All enforced in PHP, not advisory".

## Los comandos

```bash
composer require jordandalton/laravel-tackle
php artisan vendor:publish --provider="Laravel\Ai\AiServiceProvider"
php artisan vendor:publish --tag="tackle-config"
```

Requiere **PHP 8.3 o superior** y **Laravel 12 o 13**. La API key va en `.env`, por defecto `ANTHROPIC_API_KEY`, aunque el proveedor se cambia con dos variables porque debajo está `laravel/ai`:

```env
AI_CODE_PROVIDER=ollama
AI_CODE_MODEL=deepseek-coder-v2
```

Los cinco comandos que importan:

- **`ai:code`** es la sesión interactiva. Tiene plan mode, slash commands, entrada de imágenes, memoria de sesión y compactación automática de contexto.
- **`ai:run`** es el mismo agente sin terminal: devuelve código de salida y JSON opcional, para pipelines.
- **`ai:fix`** ataca un problema concreto a partir de una excepción pegada, un ID de Sentry o un enlace a un issue de GitHub.
- **`ai:review`** revisa un diff o un pull request en modo solo lectura y publica comentarios en línea con niveles de severidad, con veredicto que va de "LGTM" a "Needs changes".
- **`ai:upgrade`** planifica subidas de versión mayor de paquetes de Composer leyendo las guías del propio paquete y validando con tus tests.

Hay además `tackle:init`, que crea un `TACKLE.md` en la raíz con convenciones, límites y trampas del proyecto. Si no existe, el agente cae a `AGENTS.md` o `CLAUDE.md`, con un tope de 20.000 caracteres para no fundirse el contexto. Reutilizar los archivos que ya tienes en vez de exigir el suyo es la decisión correcta.

## La configuración es el producto

Aquí es donde Tackle se separa del resto, y merece leerse el `config/tackle.php` entero porque **los valores por defecto están pensados por entorno**:

```php
'shell' => [
    'local'      => env('AI_CODE_SHELL', 'approve'),
    'staging'    => env('AI_CODE_SHELL', 'approve'),
    'production' => env('AI_CODE_SHELL', 'off'),
],

'artisan_allowlist' => [
    'local'      => ['make:*', 'migrate:*', 'db:seed', 'route:list', 'test'],
    'staging'    => ['migrate', 'route:list'],
    'production' => ['route:list'],
],

'worktree' => [
    'local'      => env('AI_CODE_WORKTREE', false),
    'production' => env('AI_CODE_WORKTREE', true),
],

'protected_paths' => ['.env', '.env.*', 'storage/*', 'vendor/*', '.git/*'],
'budget_usd' => env('AI_CODE_BUDGET', 1.00),
```

Léelo despacio, porque cada línea es una decisión que casi nadie más toma:

En **producción el shell está apagado** y lo único que puede correr es `route:list`. En producción **el worktree está activo por defecto**, así que las ediciones van a un árbol temporal de Git y no a los archivos vivos. Los comandos que no están ni en la lista blanca ni en la de destructivos **se rechazan directamente**, no se preguntan. Y hay un **presupuesto de un dólar por sesión** que aborta cuando se pasa.

Los cuatro modos de shell van de `off` (rechaza todo), a `allowlist` (solo `composer`, `npm`, `php artisan`), a `approve` (el default: confirmación por comando, y "permitir siempre este comando exacto" se guarda en `.tackle/permissions.json`), a `yolo`, que el propio README marca como peligroso y solo para CI o entornos de confianza total.

Compara eso con el patrón habitual de la industria, que es un `AGENTS.md` diciéndole al modelo "por favor no toques `.env`". Una de las dos cosas es una garantía y la otra es una esperanza.

## Subagentes, y por qué están bien planteados

Vienen dos activados: `explorer`, de solo lectura, para localizar archivos y trazar cómo funciona una feature; y `test-writer`, que escribe un test de [Pest](/post/aprende-laravel-testing-pest) y lo corre.

La razón de existir la explica bien el README: leer veinte archivos para responder "¿cómo funciona la facturación aquí?" ya no cuesta veinte archivos de contexto en la conversación principal. La exploración pasa en el hijo, vuelven solo las conclusiones.

Las garantías son las que uno querría y rara vez encuentra: **presupuesto compartido** (el subagente cuenta contra el mismo `BudgetTracker`, así que delegar no puede saltarse tu límite), la misma capa de seguridad, **un solo nivel de profundidad**, sin preguntas al usuario, y fallo blando (si un subagente revienta devuelve el error al padre, que sigue).

## El autocurador de colas

Esta es la parte que no tiene equivalente claro en otras herramientas, y la que justifica el nombre de "harness" en vez de "asistente".

Cuando un job de cola o una tarea programada falla, un runtime dirigido por eventos levanta un agente **por su cuenta, sin nadie mirando**, en un worktree de Git aislado, diagnostica, parchea, corre los tests y abre un pull request.

Se activa aparte:

```bash
php artisan vendor:publish --tag="tackle-migrations"
php artisan migrate
php artisan queue:work --queue=healer
```

Los detalles que muestran que esto se pensó con la cabeza puesta en producción: un job puede excluirse con el atributo `#[Healable(false)]`; `AI_CODE_HEALING_THRESHOLD` retrasa la curación hasta que el job falle varias veces, para que los fallos transitorios se resuelvan solos sin quemar tokens; todo intento se registra en la tabla `tackle_healing_log` con resultado, tests y el PR asociado; y si los tests fallan, el parche no se mergea.

Es decir: no arregla producción a tus espaldas, prepara un candidato y te lo pone en una cola de revisión. Esa distinción es todo.

## El servidor MCP

Tackle también expone sus herramientas por [MCP](/post/mejores-servidores-mcp), lo que te deja usarlo desde fuera:

```bash
claude mcp add tackle -- php artisan tackle:mcp
```

A partir de ahí Claude Code, Cursor o Zed acceden a `ListRoutes`, `QueryDatabase`, `ReadTelescopeEntry` y `RunLarastan`. Y lo importante: las restricciones de rutas, listas blancas y límites de base de datos **siguen aplicándose sin importar quién llama**. Los guardarraíles no viven en el cliente, viven en el paquete.

Ese detalle convierte a Tackle en algo más interesante que un competidor de Claude Code: puede ser la capa de permisos *debajo* de Claude Code. Es una respuesta concreta a algo que ya discutí en [si PHP y Laravel son buenos lenguajes para programar con agentes](/post/php-laravel-lenguaje-para-agentes).

## Dónde está lo frágil

Y ahora la parte que el entusiasmo se salta. Nada de esto invalida el proyecto, pero cambia bastante cuándo lo adoptas.

**La base es un 0.x que se mueve.** Tackle está construido sobre `laravel/ai`, el SDK de IA oficial de Laravel, que sigue en versiones cero. El propio README lo documenta como riesgo conocido, y la redacción es más seria de lo que parece: `laravel/ai` "reshapes its `Agent` contract on most 0.x minors", y una firma de método incompatible es un fatal **en tiempo de compilación**, o sea que la clase del agente no se puede ni declarar y se cae con ella cualquier comando.

Tackle declara compatibilidad con `>=0.1 <0.11`. Comprobado ayer contra Packagist: **`laravel/ai` publicó la 0.11.0 el 19 de agosto de 2026**, justo fuera de ese rango. No rompe nada, Composer resolverá una anterior, pero significa que la versión más reciente de la base todavía no está cubierta por su matriz de CI. Es el riesgo que el autor documentó, materializándose a la semana.

**Es muy joven y muy pequeño.** El repositorio se creó el **13 de junio de 2026**. Tiene **57 estrellas** y **205 descargas totales** en Packagist. El 16 de agosto salieron cuatro releases (1.27.0 a 1.27.3) en veintiocho minutos. Eso es un mantenedor atento, y también un proyecto que todavía se está encontrando. La licencia es MIT, declarada en `composer.json` y en el README, aunque el repositorio no tiene archivo `LICENSE`.

**El agente no tiene internet.** Es una limitación declarada en la v1: no puede leer documentación, ni buscar en la web, ni llamar APIs externas. Solo trabaja con los archivos del workspace. Para `ai:upgrade` esto es notable, porque significa que las guías de actualización tienen que estar ya en `vendor/`.

**El presupuesto es estimado, no exacto.** Se calcula con conteo de tokens contra un catálogo interno de precios. Lo que te cobre el proveedor puede diferir. Con un dólar de límite por defecto, la diferencia es irrelevante; si lo subes a cincuenta, ya no.

**No hay commits automáticos** en modo normal: las ediciones quedan sin stagear. En modo worktree puede commitear y empujar a una rama de PR existente, pero siempre llamando antes a `ConfirmAction`.

## Entonces, ¿lo instalo?

Tres respuestas según dónde estés.

**Si te interesa el problema de los permisos**, sí, y ya. Es la implementación más seria que he visto de la idea de que los límites de un agente deben ser código y no cortesía, y el modelo por entorno con producción en solo lectura debería copiarse en todas partes. Aunque no lo adoptes, léete su `config/tackle.php`.

**Si buscas tu agente de programación diario**, todavía no. [Claude Code](/post/claude-code-proyecto-laravel) y compañía están años por delante en la experiencia interactiva, tienen internet, y no dependen de un 0.x que rompe contratos. Tackle no está compitiendo ahí de verdad, y su servidor MCP sugiere que su autor tampoco cree que deba.

**Si tienes colas que fallan de noche**, es lo más interesante del artículo. Un autocurador que diagnostica en un worktree aislado, corre los tests y abre un PR es una categoría casi vacía. Yo lo probaría en staging, con el threshold alto, y mirando el `tackle_healing_log` durante un par de semanas antes de creerle nada.

## Preguntas frecuentes

### ¿Tackle reemplaza a Claude Code o a Cursor?

No, y su propio servidor MCP lo deja claro: está pensado para poder correr *debajo* de ellos, aportando herramientas conscientes de Laravel y los guardarraíles. Como agente interactivo diario está muy por detrás de las herramientas dedicadas, entre otras cosas porque no tiene acceso a internet.

### ¿Necesito una API key de Anthropic?

Es el proveedor por defecto, pero no es obligatorio. Al construirse sobre `laravel/ai` acepta OpenAI, Gemini, Groq u Ollama en local, y se cambia con `AI_CODE_PROVIDER` y `AI_CODE_MODEL`. Con Ollama puedes poner los precios a cero y el presupuesto deja de aplicar.

### ¿Es seguro dejarlo tocar producción?

Sus valores por defecto están del lado prudente: en producción el shell viene apagado, el único comando Artisan permitido es `route:list` y el aislamiento por worktree está activo. Dicho eso, es un paquete de dos meses sobre una dependencia 0.x, así que yo empezaría en local con el modo `approve`, que pide confirmación comando por comando.

### ¿Qué versiones de PHP y Laravel necesita?

PHP 8.3 o superior y Laravel 12 o 13. Un detalle del README que conviene leer: `laravel/ai` 0.1.x requiere PHP 8.4, así que en PHP 8.3 Composer resolverá la 0.2 o posterior.

## Recursos

- Documentación: [tackle.jordandalton.com](https://tackle.jordandalton.com/)
- Código, README completo y riesgos conocidos: [github.com/jordandalton/laravel-tackle](https://github.com/jordandalton/laravel-tackle)
- Paquete: [packagist.org/packages/jordandalton/laravel-tackle](https://packagist.org/packages/jordandalton/laravel-tackle)
- La base sobre la que corre: [github.com/laravel/ai](https://github.com/laravel/ai)
- Cobertura: [Laravel News](https://laravel-news.com/laravel-tackle)

---

## Sitemap

Índice completo del sitio: [/sitemap.md](https://www.angelcruz.dev/sitemap.md)

Canónico HTML: [https://www.angelcruz.dev/post/laravel-tackle-agente-ia](https://www.angelcruz.dev/post/laravel-tackle-agente-ia)
