Una agent box: el sitio donde viven tus loops de agentes
El loop engineering necesita un sitio donde vivir: una agent box en tu server —demonio saliente, motor de worktrees propio y acceso sin abrir puertos.
El loop engineering —diseñar loops de agentes que trabajan solos en vez de promptear a mano cada paso— tiene un requisito del que se habla poco: un loop que trabaja solo necesita un sitio donde vivir. No tu portátil, que se apaga cuando lo cierras; una máquina siempre encendida, aislada de lo que te importa, que puedas arrancar y dirigir desde donde estés.
Monté esa caja —una agent box— en un Hetzner propio: un proceso de Claude Code ejecutándose 24/7 que aparece como un “entorno” en la app de mi móvil sin abrir un solo puerto en la máquina. El truco está en la dirección del tráfico: el proceso se registra hacia fuera, contra Anthropic, y cada sesión que creas se ejecuta en tu server, dentro de un worktree —una copia de trabajo aislada de tu repositorio— que montan tus propios scripts. Esta primera parte cubre la arquitectura que lo hace portable y seguro; lo que se rompe cuando un loop trabaja solo de verdad va en la segunda.
¿Cómo aparece tu server como entorno sin abrir puertos?
El demonio —claude remote-control --spawn worktree, un proceso que se queda vivo en segundo plano— abre conexiones salientes HTTPS/WebSocket contra api.anthropic.com y no escucha en ningún puerto de entrada. Se registra con un POST a .../v1/environments/bridge y recibe un environment_id; ese registro es exactamente lo que hace aparecer el server en la UI, en el selector de entornos.
A partir de ahí entra en un poll loop: pregunta cada poco a Anthropic “¿hay trabajo para mí?”. Cuando creas una sesión desde el chat, Anthropic hace de relay —de intermediario— entre tu móvil y el proceso que vive en tu máquina, y todo (mensajes, diffs, permisos, notificaciones push) viaja por esa conexión saliente. Nada entra al server: no hay puertos abiertos ni SSH para el agente; tu SSH queda solo para administrar la caja.
La acción concreta: modela el acceso como saliente. Un demonio que se registra hacia fuera y pregunta “¿hay trabajo?” en vez de un puerto que abres y expones. El agente no necesita entrada; solo salida.
El worktree es la unidad de aislamiento, y quién lo crea lo decides tú
Un mismo bridge —ese proceso saliente— sostiene hasta 32 sesiones concurrentes, cada una en su propio git worktree: una rama con su directorio de trabajo separado, para que dos sesiones no se pisen los ficheros. Por defecto, el demonio los crea dentro de ./proyecto/.claude/worktrees/, acoplados a la carpeta del proveedor y con un layout que no controlas.
Ahí está el punto de extensión que lo cambia todo. Si defines los hooks WorktreeCreate y WorktreeRemove —comandos tuyos que el demonio ejecuta en momentos concretos—, sustituyen por completo el mecanismo por defecto. El contrato es minúsculo: el hook recibe un JSON por stdin y debe devolver por stdout una única línea, la ruta del worktree. Con eso, apuntas la creación a tu propio script: un worktree hermano del master, con su rama nacida de master, sus puertos libres y su .env generado.
La acción concreta: sustituye el mecanismo de worktrees por defecto con tus hooks. Que devuelvan la ruta de un worktree que crea tu script, con tu layout y tus puertos. No dejes que el proveedor decida dónde vive tu código ni cómo se aísla.
Motor neutral y adaptador fino: el 80% no sabe de tu proveedor
En una agent box montada así —un demonio de agente sobre tu propia máquina—, el ~80% del trabajo —infra, usuario dedicado, toolchain, motor de worktrees, puertos, red privada— es neutral: nada de eso sabe que existe Claude. Todo el acoplamiento al proveedor cabe en 2 hooks de ~50 líneas más unas 15 de configuración. Esa proporción no es casualidad: es la decisión de diseño que hace que el prototipo no se muera cuando cambie el viento.
El reparto es por capas. scripts/ es el motor neutral: nombra ramas, asigna puertos, arranca y para entornos, limpia al terminar, genera el .env. .claude/hooks/ es el adaptador: parsea el JSON que manda el proveedor y llama a esos scripts. Un futuro adaptador para Codex o Cursor apuntaría a los mismos scripts, y todos los worktrees vivirían en el mismo sitio con el mismo layout. No es un patrón exclusivo de Claude: los self-hosted cloud agents de Cursor —disponibles desde marzo de 2026— son workers en tu infraestructura que abren conexiones salientes hacia su nube, sin puertos de entrada, la misma forma que el bridge de Claude.
La acción concreta: pon toda la lógica de workflow en scripts neutrales y deja el adaptador del proveedor tan fino que lo reescribas en una tarde. El test de salud es una pregunta —¿cuántas líneas necesito para enchufar otro proveedor?—: si la respuesta es más que “un adaptador”, la lógica se te coló donde no debía.
Una caja dedicada, aislada de lo que te importa
La caja donde ejecutas agentes no debería ser la misma donde vive nada que te importe. La razón es un fallo que no grita: un worktree de desarrollo que asume localhost:5432 se conecta a la base de datos que encuentre en ese puerto —sin error, sin aviso—, y si esa base es real, ya has escrito donde no debías. En una caja compartida ese riesgo lo llevas encima siempre; en una dedicada, desaparece por construcción.
El principio es aislar por construcción, no por configuración: una máquina —o directamente un proveedor— aparte, sin credenciales ni datos de producción, con master protegido por revisión humana. Encima de eso, dos cosas que una caja de agentes pide: swap —memoria de disco que respalda la RAM— porque un build de Vite más un Chrome headless —sin interfaz gráfica— dispara el OOM-killer —el proceso del kernel que mata procesos cuando se agota la RAM— y se llevaría por delante las demás sesiones; y ejecutar cada agente como un usuario de Linux sin sudo, que acota su terreno de juego con permisos de fichero normales.
Ese último punto es lo que además hace la caja multiusuario sin rediseñarla: el modelo que escala a un equipo es un usuario de Linux + un login del proveedor + una unit de systemd por persona, cada uno con sus propios worktrees en la misma máquina.
La acción concreta: dedica una caja a esto —sin credenciales ni datos de producción—, añade swap, y ejecuta cada agente como un usuario sin sudo. Cuando seáis varios, un usuario y una unit por persona. Aíslala por construcción, no confiando en una config.
Ver la app desde el móvil: una red privada, no un puerto abierto
Chatear con el agente desde el móvil ya funciona —de eso se encarga el relay—. Lo que falta es ver la app que construye: los dev servers escuchan en el localhost del server, invisibles desde fuera. La respuesta no es abrir un puerto, es una red privada: Tailscale monta una VPN WireGuard —un túnel cifrado entre tus dispositivos—.
Instalas Tailscale en el server y en el móvil con la misma cuenta, tailscale up, y un ufw allow in on tailscale0 —el firewall bloquearía el tráfico del tailnet, la red privada, si no—. Desde ahí el móvil ve la IP privada del server (100.x.y.z) desde cualquier red, 4G incluido. Pero la parte no obvia son tres retoques por worktree, porque los dev servers escuchan solo en localhost y el frontend lleva URLs absolutas a localhost que, desde el móvil, apuntan al propio móvil:
- Vite con
--host 0.0.0.0, para que escuche en todas las interfaces (seguro aquí: UFW bloquea lo público y solotailscale0está permitido). VITE_API_URL=http://100.x.y.z:<puerto>: el navegador del móvil ejecuta el JS, así que “localhost” sería el móvil; tiene que apuntar a la IP del tailnet.- El CORS del backend aceptando ese mismo origen.
El resultado: http://100.x.y.z:<puerto> abre en el móvil el frontend del worktree en el que el agente trabaja, con hot-reload, desde cualquier red. Y sigue sin entrar nada al server: UFW solo abre 22/80/443 al exterior; los puertos dev son invisibles desde internet y solo alcanzables dentro del tailnet, cifrados extremo a extremo por WireGuard.
La acción concreta: para ver la app desde fuera, no abras un puerto —une el dispositivo a una red privada y expón el dev server solo dentro de ella—. Y no olvides los tres retoques (bind del host, URL del API, CORS), o la app carga pero todas las llamadas fallan.
Esa es la arquitectura estable: un demonio saliente, un motor de worktrees propio, acceso por red privada y una caja dedicada. Es la continuación natural de las cuatro fronteras de un agente con acceso a tu contabilidad: aquí la primera frontera es que nada entra a la caja. Con esto, tus loops dejan de depender de que tu portátil esté abierto —viven en la caja y los diriges desde donde estés—.
Falta la otra mitad: lo que se rompe cuando un loop trabaja solo durante horas y nadie mira. Esa es la segunda parte de esta serie.
¿Dónde ejecutas tus agentes de larga duración: en una caja dedicada que puedes dirigir desde el móvil, o en un portátil que tienes que dejar abierto?