Skip to content

CH 11 · Herramientas y Sandbox

Word count~3,430 wordsTime~15 minPrereqCH 03–05 already runningLevelReproducible

Objetivo del capítulo

En los capítulos anteriores has visto al Agent en acción: lee archivos por su cuenta, ejecuta comandos, busca en la web y abre un diálogo para preguntarte sobre operaciones sensibles. Este capítulo desmonta "herramienta" y "sandbox" — cómo se invoca una herramienta, qué comprobaciones atraviesa; cómo el sandbox acorrala al Agent y qué pasa cuando choca con el límite. Cuando entiendas estos dos mecanismos, sabrás por qué se "atreve" a actuar en tu ordenador y qué es lo que realmente no puede tocar.

Herramientas: las "manos" del Agent

En dsh, el Agent en sí no puede mover nada; todas sus "acciones" se realizan a través de herramientas — leer archivos, ejecutar comandos, buscar en la web: cada una es una herramienta. En CH 08 dijimos que las herramientas son "el armario + el portero"; vamos a desglosarlo un poco más.

Una herramienta en el sistema tiene este aspecto:

ParteQué hace
schemaLas "instrucciones" que ve el modelo: nombre, descripción, parámetros (JSON Schema)
Función de ejecuciónEl código que realmente hace el trabajo
Declaración de salidaLa estructura que debe devolverse al terminar
Metadatos de planificaciónSi puede ejecutarse en paralelo, timeout, cómo se muestra en la UI

La clave está en la primera: a los ojos del modelo solo existen el nombre, la descripción y los parámetros de una herramienta — la función de ejecución, la declaración de salida, el timeout y la marca de paralelismo no son visibles para el modelo. Esta es la primera capa de seguridad: el modelo sabe "esta herramienta existe, los parámetros se rellenan así", pero no conoce su implementación interna y no puede saltarse la lógica de ejecución.

Una llamada a herramienta: una pipeline extensible

Después de que el modelo dice de llamar a una herramienta, no se ejecuta directamente; en su lugar, atraviesa una pipeline extensible. El equipo oficial diseñó esta pipeline de modo que cada etapa pueda ser interceptada o mejorada por plugins — otro "todo es un plugin" (en el diagrama se omite una etapa opcional finalizeContent; es el callback de fin de tubería propio de la herramienta y no afecta a la línea principal):

Una llamada a herramienta: de la petición del modelo al resultado autoritativo (ilustración)

Recorrido paso a paso:

  1. Petición del modelo: el modelo emite un tool/call (nombre de herramienta + parámetros). Los parámetros se validan primero; si son inválidos, se lanza directamente un error (INVALID_ARGS) y nunca se ejecuta.
  2. pre-execute: el primer punto de control. Aquí se decide si una llamada es allow / deny / ask — el diálogo de aprobación que ves en la UI ocurre en esta capa.
  3. guard: una guardia monótona: solo puede volverse más estricta, no más laxa, evitando que alguna etapa relaje silenciosamente el límite.
  4. execute: la ejecución real. El sandbox se monta en este paso — antes de que el comando se ejecute de verdad, se envuelve en una capa de archivos (ver más abajo).
  5. post-execute: inspecciona el resultado, puede reemplazarlo si hace falta.
  6. result: produce el resultado autoritativo, se devuelve al modelo y entra en la siguiente ronda.

Cada paso puede tener hooks enganchados por plugins — por eso más adelante, al escribir plugins, podrás hacer uno que "intercepte ciertas llamadas de herramientas" (CH 21 cubre los hooks). Lee esta pipeline y sabrás dónde se montan la aprobación, el sandbox y los "componentes de seguridad" del log.

Sandbox: una "capa de archivos" alrededor de los comandos

CH 04 cubrió los tres niveles de permiso (read-only / workspace-write / danger-full-access), desde la perspectiva de tu manejo de la UI. Aquí vemos el mecanismo: el sandbox solo gobierna los efectos sobre el sistema de archivos; la visibilidad de red y procesos no es de su competencia.

El equipo oficial diseñó el sandbox como dos capas separadas — "política" y "backend":

Sandbox: la política marca el límite, el backend lo aplica (ilustración)

  • Política (SandboxPolicy): se re-parsea en cada llamada — modo + raíz del workspace. La raíz del workspace se deriva del cwd de la sesión actual.
  • Backend (SandboxProvider): envuelve el comando en un proceso restringido para la plataforma actual. Cada plataforma tiene su propia implementación — Linux usa bwrap / Landlock (control de acceso sin privilegios a nivel de kernel), macOS usa Seatbelt, Windows usa un runner con token restringido por ACL.

Algunos diseños que vale la pena recordar:

fail-closed: esta es la clave de su seguridad. Si no hay ningún backend de sandbox disponible en el entorno actual, el sistema reporta directamente un error SANDBOX_UNAVAILABLE, nunca baja silenciosamente a "ejecutar desnudo sin sandbox". Mejor negarse a ejecutar que arriesgarse a soltar las riendas.

danger-full-access no envuelve una capa: solo los modos restringidos (read-only / workspace-write) pasan por la envoltura del sandbox. El modo de permiso total lanza directamente el comando original sin aislamiento de archivos — por eso la UI confirma dos veces cuando cambias al tercer nivel.

Integridad obligatoria dividida en full / partial: la mayor parte del tiempo el backend puede gobernar todos los efectos prometidos sobre archivos (full); pero en ABIs antiguas del kernel de Linux o en algunos límites de Windows, solo puede gobernar parte de ellos (partial), y cualquier escenario que requiera garantías absolutas debe saber esto. Para el uso diario ordinario, el workspace-write por defecto es suficientemente estable.

Manos a la obra: compruébalo tú mismo

Paso 1: ver una llamada a herramienta en la Trayectoria

En la Web UI, ejecuta una tarea que haga alguna acción (p. ej., el resumen de repo de CH 05). Cuando termine, cambia a la pestaña Trayectoria y haz clic en cualquier fila TOOL. El panel derecho tiene cuatro pestañas clave, que se corresponden exactamente con la estructura de herramienta anterior:

  • Schema: las "instrucciones" de la herramienta (nombre, descripción, parámetros)
  • Payload: los parámetros reales enviados esta vez
  • Result: el resultado devuelto
  • Summary / Timing: resumen y tiempo transcurrido

La imagen de abajo es una llamada real: a la izquierda, una fila TOOL (web_search) seleccionada en la línea de tiempo; a la derecha, todas las pestañas expandidas en el panel; abajo puedes ver las estadísticas globales de la ronda — fíjate en que en mitad también hay dos comandos pwsh que fallaron por problemas de red y el Agent cambió inmediatamente a web_search. Este es exactamente un ejemplo real de "las herramientas pueden cambiar de camino cuando fallan":

Detalle de una llamada a herramienta en la Trayectoria: fila TOOL seleccionada a la izquierda, pestañas Schema / Payload / Result expandidas a la derecha

Paso 2: ver una aprobación

Con el permiso por defecto workspace-write, haz que el Agent escriba un archivo fuera del workspace. Aquí le pido que cree un archivo de saludo bajo E:\software-workspace\doubaowork\doubao — ese directorio no está en el workspace actual:

Hacer que el Agent escriba un archivo fuera del workspace: introducción del comando

Fíjate en que lo que pasa en realidad son dos pasos:

  1. El primer Write choca contra el muro directamente — la Trayectoria muestra Write · Error: [sandbox: file access denied under workspace-write mode].
  2. El Agent se da cuenta de que el destino está fuera del workspace y solicita proactivamente una escalada; el diálogo ask de la capa pre-execute aparece solo en este punto: elevar el sandbox a danger-full-access, con un motivo. Los dos botones de abajo — Denegar y Permitir una vez:

Diálogo de aprobación de escalada: Denegar / Permitir una vez

Pulsa "Permitir una vez", solo permite esta única escritura; pulsa "Denegar" y tiene que buscar otra forma.

Paso 3: cambia a read-only y mira

En el cuadro de entrada escribe /permission, cambia a read-only (tras la entrada, la UI mostrará permission · preset read-only) y haz que el Agent escriba un archivo. El resultado es similar al de arriba, pero con una diferencia clave:

Escritura denegada en modo read-only: error + solicitud de escalada

  1. El primer Write también choca contra el muro — pero el error es distinto: Write · Error: [sandbox: file access denied under read-only mode].
  2. El Agent también solicita una escalada — pero esta vez el destino es escalate sandbox to workspace-write, no danger-full-access (solo necesita un permiso de escritura normal, no hace falta subirlo del todo).

Comparando los tres casos de "bloqueo" queda claro: independientemente del nivel de permiso, cuando falla una escritura el Agent choca primero contra el muro y luego muestra el diálogo pidiéndote permiso. Las diferencias son el mensaje de error (workspace-write mode / read-only mode) y el siguiente nivel que solicita (danger-full-access / workspace-write). El botón "Denegar" siempre está ahí — este es el núcleo del diseño del sandbox: el Agent puede "pedir", pero "dar o no dar" siempre depende de ti.

Qué aprendiste en este capítulo

Apruebas si puedes completar los siguientes puntos:

  • [ ] Enumerar de qué partes se compone una herramienta y cuáles son visibles para el modelo y cuáles no
  • [ ] Dibujar la pipeline de ejecución de herramientas (model request → pre-execute → guard → execute → post-execute → result) y decir dónde se montan la aprobación y el sandbox
  • [ ] Explicar qué significa que el sandbox "solo gobierna los efectos sobre el sistema de archivos" y por qué
  • [ ] Explicar fail-closed: qué hace el sistema cuando no hay backend de sandbox disponible (reporta SANDBOX_UNAVAILABLE, no ejecuta desnudo)
  • [ ] Abrir una llamada a herramienta en la Trayectoria y entender Schema / Payload / Result
  • [ ] Indicar los errores cuando se deniegan escrituras en distintos niveles de permiso (workspace-write mode / read-only mode) y los destinos de escalada que pide el Agent (danger-full-access / workspace-write)
  • [ ] Poder explicar: cuando una escritura falla, el Agent choca primero contra el muro y luego abre el diálogo, pero "Denegar" siempre está en tus manos

Open Source · MIT · Community Driven