← Volver al Blog

Cuando el agente borró producción y cómo el harness lo detuvo en 3 capas

Hace tres meses, un agente de IA en mi entorno de staging ejecutó DROP TABLE en una tabla con 40 mil filas. No pasó nada. La primera capa del harness le impidió tocar la conexión de producción, la segunda le mostró el diff antes de ejecutarlo, y la tercera cortó la sesión. Cinco segundos, tres capas, cero impacto.

Yo no descubrí este patrón por brillante. Lo descubrí porque en abril de 2026 un agente Claude Opus 4.6 ejecutándose dentro de Cursor eliminó la base de producción de una startup en 9 segundos, respaldos incluidos. Cuando leí ese post-mortem esa misma semana, revisé mi propio harness, encontré tres huecos, y los cerré. Este artículo es el resultado.

Si viniste antes por “Dejé al agente 24 horas: la cuenta de USD 400 fue lo de menos” o por “Conecté Claude a MCP: el chaos mató staging 4 veces”, este es el eje complementario. Aquellos eran sobre costo y sobre pruebas de caos. Este es sobre el patrón de diseño de tres capas de defensa que evita que un descuido de agente llegue a producción.

El incidente de referencia

El caso de la startup PocketOS tiene una anatomía que vale desglosar. El agente recibió una tarea acotada: arreglar un desajuste de autenticación en staging. En vez de quedarse en el archivo objetivo, salió a buscar contexto adicional, encontró un token de Railway en un archivo no relacionado, y lanzó una llamada volumeDelete por GraphQL. No hubo prompt de confirmación. Los respaldos estaban conectados al mismo volumen y cayeron con él.

Tres cosas fallaron a la vez.

  1. El agente tenía permiso implícito para leer archivos fuera del alcance de la tarea.
  2. No había una etapa de “mostrar el comando destructivo antes de ejecutarlo”.
  3. No existía un botón externo para cortar la sesión en el segundo en que apareció el volumeDelete.

Cada una de esas fallas corresponde a una capa distinta del harness. Y cada capa se resuelve con herramientas diferentes.

Capa 1: permisos como límite duro

La primera línea de defensa no es una advertencia, es una regla que el agente no puede saltar. En Claude Code 2026 esto se configura con hooks, --permission-mode y reglas de deny explícitas en el archivo de settings del proyecto.

Reglas mínimas que yo aplico a cualquier agente que toca un repositorio con datos:

  • Nada de Bash(rm -rf ...) ni comandos que contengan DROP sin aprobación humana explícita
  • Sin acceso a la red fuera de un allowlist de dominios
  • Escritura de archivos limitada a subdirectorios del proyecto (nunca ~/.aws, ~/.ssh, ni ningún archivo de credenciales)
  • Denegación específica de comandos que borran datos: truncate, DELETE FROM sin WHERE, DROP, volumeDelete, git push --force

Este es el equivalente al allowedTools de la taxonomía de seis módulos del harness. Restringe qué herramientas puede usar el agente antes de que él elija cuál usar.

Un detalle práctico: no confíes en que la regla venga del prompt. El agente puede olvidarse del prompt en el turno 30. La regla tiene que estar en la capa de configuración del runtime, no en la conversación.

Capa 2: dry-run como reflejo

La segunda capa asume que la primera falla en algún momento. Alguna regla se te va a escapar. La respuesta es forzar un dry-run antes de cualquier acción destructiva.

En la práctica esto se traduce a un hook PreToolUse que:

  • Intercepta llamadas a herramientas de escritura (SQL, HTTP mutations, rm, git push --force)
  • Muestra el comando exacto que se va a ejecutar
  • Envía un mensaje al canal humano (Telegram, Slack) con el diff
  • Espera confirmación con timeout de 60 segundos, después denegado por defecto

El punto clave es “denegado por defecto”. Si estás durmiendo cuando el agente decide ejecutar DROP TABLE, el timeout te salva. Aprobado por defecto es la trampa donde caen la mitad de los setups que revisé este año.

Este patrón resuelve exactamente el segundo hueco del caso PocketOS: no hubo prompt de confirmación antes de que el comando destructivo se ejecutara.

Las tres capas de defensa del harness

Capa 3: kill-switch externo

Las dos primeras capas viven dentro del harness. La tercera vive fuera. Es un botón externo que corta la sesión del agente sin importar en qué estado interno esté.

Formas mínimas que funcionan bien en 2026:

  • Un endpoint HTTP que revoca el token de API del agente cuando lo golpeas
  • Un archivo KILL en un directorio compartido que el agente relee cada N segundos
  • Un botón en tu bot de Telegram que ejecuta pkill -f agent-process en la máquina host

La razón por la cual esto tiene que vivir fuera es que un agente en estado corrupto puede reescribir sus propias reglas internas. Si el kill-switch está dentro del harness, el agente puede desactivarlo. Si está afuera, no puede.

Este es el tercer hueco de PocketOS: incluso si hubieras visto el volumeDelete en pantalla en el segundo 3 de los 9 que tardó, no había forma de cortar la sesión desde afuera. Nueve segundos alcanzan para ir al baño. No alcanzan para depurar y matar el proceso.

Mi propio incidente en staging

El DROP TABLE que mencioné al inicio ocurrió en mi staging. El agente estaba haciendo una limpieza de tablas temporales y decidió “optimizar” borrando también una tabla que confundió con temporal. La capa 1 (permisos) lo dejó pasar porque DROP TABLE sobre una tabla del propio esquema estaba permitido en staging. La capa 2 (dry-run) mostró el comando en Telegram. Yo estaba comiendo. No respondí. Al minuto, la denegación por defecto se activó y el agente recibió un permission denied.

Cinco segundos después, activé el kill-switch por prevención. La tabla de staging se quedó donde estaba, con sus 40 mil filas intactas.

No es una historia heroica. Es un ejemplo de que las tres capas son redundantes por diseño. Cuando falla una, la siguiente compensa. Cuando fallan dos, la tercera es la última línea. Si fallan las tres a la vez, felicitaciones, escribiste el próximo post-mortem que otra persona va a leer.

Cómo empezar mañana

Si vas a implementar esto hoy, el orden importa.

  1. Empieza por la capa 3 (kill-switch externo). Es la más simple y la más útil si algo se descontrola mientras configuras el resto. Un KILL file y un cron de 5 segundos ya te sirven.
  2. Después la capa 1 (permisos). Escribe el allowlist antes que el denylist. “Puede hacer X, Y, Z. Todo lo demás pide aprobación.”
  3. Al final la capa 2 (dry-run). Es la más útil pero la que más fricción introduce en el uso diario. Configúrala solo después de que las otras dos estén firmes.

Para las especificaciones vigentes de permisos, hooks y --safe-mode en Claude Code, revisa el changelog oficial de 2026. Anthropic viene ajustando estas superficies cada pocas semanas y vale mirar antes de escribir tus reglas.

Recursos


ken imoto · WebRTC & Voice AI engineer · kenimoto.dev