Ir al contenido

Sandbox

El sandbox es un contenedor por tarea donde el agente instala dependencias, corre builds y tests, y levanta la app para que la vea QA. Vive aparte del contenedor del agente: el agente edita el código y maneja git en el suyo, y manda los comandos pesados al sandbox. Los dos ven el mismo código en /workspace/projects/<repo>/, así que lo que el agente edita ya está en el sandbox sin copiar nada.

Thulu crea el sandbox con el primer comando que el agente le manda y lo apaga después de 30 minutos sin uso. Entre corridas, la etapa siguiente encuentra el sandbox como lo dejó la anterior, con la app levantada, mientras no pasen esos 30 minutos. Las subtareas usan el sandbox de su tarea padre.

Para el uso diario no hay nada que hacer en la página “Sandboxes”: alcanza con que el agente tenga el sandbox habilitado en su etapa. La página sirve para ver qué está corriendo, quién espera lugar y matar un sandbox trabado. Si ningún agente tiene argus-sandbox tildado en ninguna etapa, la página lo avisa con un link a Agentes.

Un agente sólo puede usar el sandbox en las etapas donde tiene tildado el servidor MCP argus-sandbox. Sin eso, la corrida no recibe las herramientas y el agente instala y construye dentro de su propio contenedor, sin caché y sin que nadie más pueda ver la app.

  1. Abrí “Agentes” en la barra lateral y elegí el agente.

  2. Andá a la pestaña “MCP”. Hay un bloque por cada etapa en la que trabaja el agente.

  3. En la etapa que corresponda, tildá argus-sandbox. El contador “Tools” pasa a 7/7: el sandbox se concede entero, sin elegir herramientas sueltas.

    Pestaña MCP del agente desarrollador con argus-sandbox y argus-github tildados en la etapa En curso
    argus-sandbox tildado en la etapa En curso. Hay que repetirlo en cada etapa donde el agente tenga que construir o levantar la app.
  4. Tocá “Guardar configuración”.

Con argus-sandbox, la corrida recibe también la skill del sistema octopus-sandbox, que le enseña al agente a levantar el proyecto, qué hacer cuando un build se queda sin memoria y cómo dejar la app lista para la etapa siguiente. Ver Agentes y MCPs.

Qué puede hacer el agente con el sandbox:

Herramienta Para qué
exec Correr un comando de shell. Devuelve la salida, los errores y el código de salida. Cada comando tiene un tope de 30 minutos.
preview_url Pedir la dirección de un puerto donde escucha la app: una para el navegador de QA y otra para una persona (ver Puertos y previews).
attach_file Adjuntar a la tarea un archivo que generó en el sandbox (un PDF, un reporte de cobertura), hasta 50 MB.
init_status, init_run, init_script_get, init_script_update Consultar, correr y corregir el script de arranque del proyecto (ver Script de arranque).

La página está en el modo Configuración: tocá “Configuración” abajo en la barra lateral y después “Sandboxes”, en el grupo “Operación”.

Página Sandboxes con el aviso de que ningún agente tiene argus-sandbox, dos sandboxes activos con el título de su tarea y estado Listo, una tarea de Refinamiento en la cola y el panel de configuración
Dos sandboxes activos de un máximo de 2 y una tarea esperando lugar. Arriba a la derecha, el resumen: activos sobre el máximo y cuántas tareas hay en cola.

“Sandboxes activos” lista un sandbox por tarea:

Columna Qué muestra
“Tarea” El título de la tarea, con link a su detalle. También aparecen “Precalentado de <proyecto>” (el precalentamiento de la caché de un proyecto) y “Tanda de Evidencia” (la app de una tanda de Evidencia): ocupan un lugar igual que una tarea.
“Contenedor” Los primeros 12 caracteres del contenedor (en Kubernetes, el pod).
“Estado” “Listo” (acepta comandos) o “Arrancando”. Los desalojados y los que fallaron salen de la lista.
“Inactivo” Hace cuánto no recibe un comando. Al llegar al desalojo por inactividad, Thulu lo apaga.
“Puertos” Pares puerto-del-host:puerto-del-sandbox. En Docker, 32800:3000 quiere decir que la app que escucha en el 3000 del sandbox se abre en localhost:32800 del servidor.

La página se actualiza sola cada 4 segundos. Cada persona ve sólo los sandboxes de su workspace.

“Cola” lista las tareas que pidieron un sandbox cuando ya estaban todos ocupados, con su etapa y la prioridad de esa etapa. Cuando se libera un lugar se lo lleva la de prioridad más alta, y entre iguales la que llegó primero. Thulu relanza la etapa en la que está la tarea para que el agente retome. “Sacar de la cola”, al final de la fila, saca una tarea que ya no tiene que esperar.

Sirve cuando un sandbox quedó en mal estado (un proceso colgado, un disco lleno) o para liberar un lugar ya.

  1. En “Sandboxes activos”, tocá el botón de apagado al final de la fila. También podés hacerlo desde la tarea: la fila “Sandbox” de sus propiedades muestra el estado, cuánto lleva inactivo y “Matar”.

  2. Confirmá con “Matar”. Aparece el aviso “Sandbox eliminado”.

    Diálogo ¿Matar el sandbox? que nombra la tarea Pagar con gift card en el checkout, con los botones Cancelar y Matar
    El diálogo nombra la tarea dueña del sandbox.

Matar el sandbox no toca la tarea ni su etapa. Si el agente vuelve a mandar un comando, Thulu le crea uno nuevo: se pierden los procesos que corrían, /tmp y lo instalado fuera del repo, y se conservan el código del repo y la caché de dependencias del workspace. Hace falta rol admin.

El panel “Configuración” tiene tres números y una prioridad por etapa. Valen para toda la instalación, no por workspace: sólo los admins del workspace operador pueden guardarlos. El resto ve el panel en sólo lectura con el aviso “Los límites de sandboxes y las prioridades por etapa se aplican a todos los espacios de trabajo de esta instalación.”

Campo Default Qué hace
“Máximo de sandboxes simultáneos” 3 Cuántos sandboxes pueden estar vivos a la vez. El siguiente que se pida espera en la cola.
“Desalojo por inactividad (minutos)” 30 Cuánto tiempo sin comandos antes de apagar un sandbox. Uno que está corriendo un comando no se apaga. Si todos los lugares están ocupados y alguien pide uno, Thulu también desaloja en el momento el que lleva más de ese tiempo sin uso. Con 0 no se desaloja nunca.
“Espera por un lugar libre (segundos)” 120 Cuánto espera el pedido del agente a que se libere un lugar. Pasado ese tiempo, el agente recibe que quedó en cola y Thulu relanza la etapa cuando le toca el turno. Con 0 la tarea pasa a la cola enseguida.
“Prioridad por etapa” Las etapas que no son de inicio ni de fin reciben 10, 20, 30… según su orden en el tablero, también las que creás después; las de inicio y fin, 0. En el tablero de fábrica: Backlog 0, En curso 10, Hecho 0 Gana el número más alto cuando se libera un lugar. La prioridad va por id de etapa: dos tableros con una etapa del mismo id comparten el número.
  1. Cambiá los valores. Para que QA pase adelante de Desarrollo cuando falta lugar, dale a su etapa un número más alto.

  2. Tocá “Guardar configuración”. Al lado aparece “Guardado”. Si un campo está vacío o no es un número válido, queda marcado con el motivo y no se guarda nada: los valores se guardan todos juntos o ninguno. Las tareas que ya estaban en la cola se reordenan con las prioridades nuevas.

    Panel Configuración con máximo 2, desalojo 30 minutos, espera 120 segundos y prioridades QA 30, Revisión 25, En curso 10, Backlog 0, Hecho 0 y Refinamiento 0
    QA y Revisión con prioridad sobre En curso.

A este panel también se llega desde el tablero: en el menú de una columna, “Comportamiento” tiene el link “Prioridad del sandbox”. El panel “Capacidad” de Infraestructura muestra cuántos sandboxes corren contra el máximo, con el link “Cambiar el límite de sandboxes”.

El sandbox expone cuatro puertos para la app: 3000, 5173, 8000 y 8080. El operador puede cambiar la lista con OCTOPUS_SANDBOX_PORTS (por ejemplo 3000,4200,8080); un sandbox conserva la lista con la que se creó. Si el agente pide la dirección de otro puerto, preview_url le contesta cuáles hay y el agente tiene que mover la app a uno de esos desde el script de arranque.

preview_url devuelve dos direcciones. La primera es para el navegador del agente de QA (argus-browser), que corre en otro contenedor. La segunda es para una persona, y depende del runtime:

La dirección para personas es http://<host>:<puerto-del-host>, con el puerto que muestra la columna “Puertos” y el host de OCTOPUS_PUBLIC_HOST (localhost si no está definido). Por default Thulu publica esos puertos sólo en 127.0.0.1 del servidor donde corre el daemon: si Thulu está en tu máquina, la abrís directo; si está en un servidor, la dirección con el dominio público no responde y necesitás un túnel SSH (ssh -L 32800:localhost:32800 servidor) para abrir http://localhost:32800. El operador puede publicarlos en otra interfaz con OCTOPUS_SANDBOX_PUBLISH_IP (0.0.0.0 los abre en todas).

En Docker, la fila “Sandbox” de la tarea muestra un link “Puerto N” por cada puerto publicado. En Kubernetes no hay link: te enterás si el agente describe la app en un comentario o adjunta capturas.

Cada proyecto puede guardar un script que levanta la app en el sandbox: el script en bash, los puertos, un “Comando de listo” (por ejemplo curl -fsS http://localhost:3000/) con su timeout, parámetros, y una fase de “Setup” que instala dependencias. Se edita en la página del proyecto, en el panel “Script de arranque”, con historial de revisiones.

El agente lo corre con init_run en lugar de adivinar cómo se levanta el proyecto. Si no hay script, el agente averigua cómo levantarlo, y cuando le funciona lo guarda como revisión nueva, que queda registrada en el historial y en la auditoría con el agente como autor. Lo mismo si el script se rompe por una incompatibilidad. Cada workspace tiene además una caché persistente en /cache (npm, Go, pip y las versiones que instala mise) que sobrevive a los desalojos.

El detalle está en Proyectos.

Quien instala Thulu elige dónde corren agentes y sandboxes. Desde la UI no se ve ni se cambia: es configuración del daemon (variables de entorno en Docker, values del chart de Helm en Kubernetes). Ver Operación self-hosted.

  • Un contenedor por sandbox en el mismo host, con las capabilities de Linux quitadas salvo ocho básicas (CHOWN, SETUID, KILL y similares), no-new-privileges, 6 GB de memoria (swap incluido), 2 CPU y un tope de 4096 procesos (OCTOPUS_SANDBOX_CPUS, OCTOPUS_SANDBOX_PIDS_LIMIT).
  • Corre como root dentro del contenedor, así que el agente puede instalar paquetes con apt-get. Con OCTOPUS_ROOTLESS_AGENTS=true corre como uid 1000, sin capabilities.
  • Corre en la red propia de la instalación, octopus-agents, y publica sus puertos en 127.0.0.1.
  • Sin Docker adentro: un docker-compose up no funciona; los servicios que la app necesita corren como procesos.
  • Sin filtro de salida a internet: el sandbox y los agentes pueden conectarse a cualquier host que alcance la máquina, incluida tu red interna. El endurecimiento adicional de Docker está postergado.

En los dos runtimes Thulu pasa HTTP_PROXY, HTTPS_PROXY y NO_PROXY al sandbox, y OCTOPUS_EXTRA_CA_BUNDLE agrega la autoridad certificante de tu empresa. Para código que no es de confianza, el límite fuerte es Kubernetes con Kata.

En el día a día los sandboxes se crean y se apagan solos. Estos son los casos en que conviene mirar la página:

  • Una tarea no arranca y figura en “Cola”: están todos los lugares ocupados. Esperá a que un sandbox se desaloje, matá uno que ya no haga falta o subí el máximo.

  • Hay un lugar libre y la tarea sigue en “Cola”: Thulu intentó relanzar la etapa en la que está ahora la tarea y no pudo, por ejemplo porque la tarea se movió a una columna donde no tiene agente asignado. Llevá la tarea a una columna con agente para que corra de nuevo, o tocá “Sacar de la cola” si ya no tiene que esperar. Si el plan del workspace limita cuántos agentes corren a la vez, la otra causa es que el workspace llegó a ese tope aunque la instalación tenga lugar.

    Página Sandboxes con 1 de 2 activos, la tarea de Refinamiento todavía en la cola con la cruz de Sacar de la cola y el aviso Sandbox eliminado
    Después de matar un sandbox queda un lugar libre, pero la tarea en cola sigue ahí porque estaba en una columna sin agente. Sacar de la cola la libera.
  • El agente reporta que un comando terminó con código 137: el proceso pasó los 6 GB de memoria del sandbox. La skill octopus-sandbox le indica bajar el paralelismo del build antes de reportarlo. Si el sandbox entero dejó de responder, matalo.

  • El agente dice que el sandbox está caído o que el comando “timed out” al segundo: el contenedor murió. Matalo para que el próximo pedido cree uno nuevo.

  • La app no abre en tu navegador: en Docker, revisá que estés en el servidor o con un túnel al puerto del host; en Kubernetes no hay acceso directo.

  • El agente no tiene las herramientas del sandbox: falta tildar argus-sandbox en la etapa del agente.