Los ocho hooks que garantizan la fiabilidad de un agente de IA
Las reglas de CLAUDE.md se siguen en torno al 80% de los casos. Los hooks se siguen el 100% de las veces. Tras seis meses probándolos, estos son los ocho que nunca he eliminado.
CLAUDE.md es una sugerencia. Si escribes «ejecuta Prettier antes de hacer commit», el agente lo saltará aproximadamente una vez de cada tres. Afinar las instrucciones no resuelve el problema. Un 80% de cumplimiento no es un problema de calidad del modelo: es una limitación estructural de colocar reglas dentro de la ventana de contexto y esperar que el modelo las siga.
Los hooks operan en un plano completamente distinto. Son scripts que se ejecutan automáticamente en puntos concretos del ciclo de vida, independientemente de lo que decida el modelo. PreToolUse se dispara justo antes de que el agente modifique un archivo o ejecute un comando. PostToolUse se dispara justo después. El modelo no elige si ejecutarlos. Simplemente se ejecutan.
La diferencia práctica es inmediata. Añadir diez líneas de reglas a CLAUDE.md y añadir un hook a .claude/settings.json son intervenciones de naturaleza completamente diferente. El código de salida 2 bloquea la acción del agente en seco. El código de salida 0 la deja pasar. Cualquier otro código registra una advertencia pero no bloquea. Y como los hooks viven en settings.json, se hace commit una vez y todo el equipo los recibe por git.
Los cuatro guardias antes de ejecutar
Llevo más de seis meses usando hooks. Estos cuatro de tipo PreToolUse sobrevivieron en todos los proyectos sin que los eliminara ni una sola vez.
Bloquear comandos peligrosos detecta patrones destructivos como rm -rf, git reset --hard y DROP TABLE mediante expresiones regulares, y devuelve el código de salida 2 para matar la acción antes de que ocurra. He visto agentes intentar rm -rf en directorios que no debían tocar. Sin este hook, el daño habría sido real.
Proteger archivos sensibles bloquea cualquier intento de modificar .env, package-lock.json, archivos *.pem y similares. El agente nunca tiene la oportunidad de sobreescribir el lockfile ni de filtrar credenciales en un commit.
Exigir pruebas antes de un PR condiciona la creación de pull requests a que los tests pasen. Configura el matcher para mcp__github__create_pull_request y el agente literalmente no puede abrir un PR hasta que los tests estén en verde. Se acabó el «arreglaré los tests en el siguiente commit».
Registrar cada comando escribe en .claude/command-log.txt todos los comandos bash que ejecuta el agente, con marcas de tiempo. Tres días después, cuando algo parece haber ido mal, puedes trazar exactamente lo que ocurrió.
Los tres inspectores después de ejecutar
Los hooks de tipo PostToolUse se ejecutan inmediatamente después de que el agente modifique un archivo. Los encadeno en secuencia de tres.
Formateo automático ejecuta Prettier sobre cada archivo modificado. En proyectos Python se sustituye por Black; en Go, por gofmt. El formateador se ejecuta tanto si el agente se acordó de formatear como si no.
Linting automático ejecuta ESLint justo después del formateo. Si ESLint encuentra errores, el agente los ve de inmediato y los corrige en el mismo turno. El número de problemas de lint que llegan a la revisión de código humana cae a casi cero.
Tests automáticos ejecuta la suite de pruebas relevante tras cada cambio de archivo. Cuando falla un test, el agente lo sabe en segundos e intenta una corrección. Paso la salida por tail -5 para conservar solo el resumen, lo que evita que la salida de los tests inunde la ventana de contexto.
El orden importa. Primero Prettier, luego ESLint, luego los tests. Cuando un humano revisa el código, el formateo y el lint ya han pasado. Los comentarios de estilo en la revisión de código desaparecen.
Preservar el trabajo cuando el agente se detiene
Un único hook de tipo Stop se encarga de esto: commit automático ejecuta git add -A && git commit cada vez que el agente termina una respuesta. Cada unidad de trabajo obtiene su propio commit. Dos tareas nunca se mezclan en un mismo commit.
Combinado con git worktrees se obtienen commits automáticos por rama en las ramas de funcionalidad. Si el agente falla o se interrumpe, nunca se pierde el último bloque de trabajo.
Lo que no funcionó bien
El encadenamiento de hooks parece elegante, pero depurar una cadena que falla es más complicado que depurar un script individual. Cuando el hook de tests automáticos empezó a fallar silenciosamente porque el ejecutor de pruebas no estaba instalado en un proyecto nuevo, tardé una hora en entender por qué el agente seguía produciendo código sin probar. El hook devolvía el código de salida 0 porque el propio script de tests no se encontraba, y la shell trató «command not found» como una condición no bloqueante. Tuve que añadir una comprobación explícita de la existencia del ejecutor de pruebas antes de invocarlo.
El rendimiento es la otra limitación. La preocupación habitual es que muchos hooks ralentizan las cosas, pero no es exactamente así. La pregunta real es si cada hook individual termina en menos de 200 milisegundos. Una ejecución de Prettier sobre un solo archivo tarda unos 50 ms. Una comprobación de ESLint tarda unos 80 ms. Los tests varían, pero limitar el alcance a los archivos afectados mantiene la mayoría de ejecuciones dentro de márgenes rápidos. Si algún hook individual supera el segundo, el bucle de retroalimentación del agente empieza a notarse lento.
Por qué esto encaja con un patrón más amplio
El blog de Harness Engineering de OpenAI señalaba que los agentes funcionan mejor dentro de límites rígidos y una estructura predecible. La filosofía de diseño de React dice lo mismo sobre los componentes: unidades componibles con fases de ciclo de vida definidas y estado.
Los hooks en Claude Code siguen la misma abstracción. El estado corresponde a las sesiones y la memoria. Los hooks son las funciones que intervienen en los límites del ciclo de vida. PreToolUse establece las fronteras. PostToolUse hace la estructura predecible. Stop conserva el resultado.
La línea «ejecuta Prettier» que antes tenía en CLAUDE.md ya no está. El hook lo ejecuta cada vez, sin que se lo pida nadie.
Únete al boletín
Recibe insights sobre la IA más reciente.