# Worktrees para agentes: aislar archivos no aísla el sistema

> Bases de datos, puertos, colas y servicios externos pueden seguir compartidos aunque cada agente tenga su propio checkout.

- Author: Viktor Berthelius (BRTHLS)
- Published: 2026-11-09
- Category: automation aiops
- Tags: worktrees, concurrencia, entornos
- Language: es
- Canonical: https://www.brthls.com/magazine/worktrees-agentes-estado-compartido-es
- Source: BRTHLS Magazine — https://www.brthls.com

---

## Problema

Cada agente trabaja en un directorio distinto y el equipo da por resuelta la concurrencia. Después, una prueba modifica la base de datos que usa otra tarea, un proceso ocupa el puerto esperado o una limpieza elimina artefactos compartidos.

El aislamiento del árbol de archivos evita una clase de colisiones. No separa automáticamente todos los recursos que el proyecto utiliza durante desarrollo y pruebas.

## Tesis

Acompaña cada worktree con un contrato de recursos. La documentación de Git explica los árboles de trabajo vinculados al mismo repositorio; ese mecanismo no pretende aislar bases de datos ni servicios. La continuidad de agentes de larga duración también requiere gestionar el entorno, como señala el trabajo de Anthropic sobre arneses.

Para operar en paralelo, debes saber qué pertenece a cada tarea, qué se comparte y qué acciones necesitan coordinación.

## Framework

### Inventaría el estado fuera del checkout

Incluye puertos, directorios temporales, cachés, bases de datos, cuentas de prueba y colas. Añade cualquier proceso que pueda sobrevivir a la sesión. El inventario debe describir el recurso y su propietario, no guardar secretos.

Clasifica los recursos compartidos según su comportamiento. Una caché de lectura puede ser aceptable; una base de datos con pruebas destructivas necesita aislamiento o exclusión mutua. La decisión depende de los efectos, no del nombre del recurso.

### Comprueba la separación con una colisión deliberada

En un entorno seguro, ejecuta tareas que intenten usar el mismo recurso y observa el resultado. La prueba debe mostrar un bloqueo claro, una asignación independiente o un fallo comprensible. Un sistema que colisiona silenciosamente solo parece aislado.

Registra también el punto de partida de cada rama. Los árboles separados no evitan que varias tareas cambien el mismo contrato. La integración debe reconciliar intención y comportamiento, además de resolver conflictos de texto.

### Define el final de la tarea

La limpieza debe detener solo los procesos propios y conservar lo necesario para revisar o recuperar el trabajo. Evita comandos generales que afecten a todas las sesiones. Un identificador de tarea ayuda a asociar recursos, pero no sustituye la comprobación antes de borrarlos.

El cierre debe dejar una entrega recuperable y una relación de recursos aún activos. Así el siguiente operador puede decidir si mantenerlos o retirarlos.

### Demostración local: checkout separado y datos de prueba separados

Este ejemplo requiere Python con SQLite y Git. Crea un repositorio temporal y árboles de trabajo desechables, asigna una base SQLite distinta a cada uno y comprueba que un registro escrito por una tarea no aparece en la otra. Utiliza datos sintéticos, sin acceder a repositorios existentes.

```python
from pathlib import Path
from tempfile import TemporaryDirectory
import sqlite3
import subprocess

def git(*args):
    subprocess.run(["git", *map(str, args)], check=True,
                   stdout=subprocess.DEVNULL)

with TemporaryDirectory() as directory:
    root = Path(directory)
    repo = root / "repo"
    git("init", "-q", repo)
    git("-C", repo, "-c", "user.name=Demo",
        "-c", "user.email=demo@example.invalid",
        "commit", "-q", "--allow-empty", "-m", "base")
    for task in ("alpha", "beta"):
        git("-C", repo, "worktree", "add", "-q",
            "-b", task, root / task)
        connection = sqlite3.connect(root / task / "fixture.sqlite")
        connection.execute("CREATE TABLE marker (task TEXT)")
        connection.execute("INSERT INTO marker VALUES (?)", (task,))
        connection.commit()
        connection.close()
    for task in ("alpha", "beta"):
        connection = sqlite3.connect(root / task / "fixture.sqlite")
        assert connection.execute("SELECT task FROM marker").fetchall() == [(task,)]
        connection.close()
    print("Datos separados por tarea; comprobación correcta")
```

La separación de datos se debe a las rutas distintas de SQLite, no a una protección automática de Git. Si ambas tareas usan la misma conexión remota, el worktree no la divide. Tampoco este ejemplo impide que un proceso del mismo usuario abra la base de la otra tarea: no demuestra aislamiento de seguridad.

### Lo que el proyecto real debe añadir

| Recurso | Separación que hay que configurar | Comprobación |
| --- | --- | --- |
| Base de pruebas | Base, esquema o instancia por tarea | Una escritura no altera la lectura de otra tarea |
| Servidor local | Puerto asignado y proceso identificado | La prueba consulta su propio servidor |
| Cola o bucket | Espacio de nombres y permisos adecuados | Limpieza limitada al propietario |
| Credenciales | Cuenta de prueba con alcance limitado | No permiten modificar recursos ajenos |

No copies un archivo de entorno compartido esperando que cambien sus destinos. Revisa la conexión efectiva que carga el proceso. El contrato termina con la retirada de recursos propios y la conservación de la entrega necesaria para revisar; una limpieza general puede borrar trabajo aunque cada checkout estuviera separado.

## Por qué importa ahora

La ejecución paralela hace visibles dependencias que antes se coordinaban de manera informal. El coste de una colisión puede superar la velocidad ganada si invalida pruebas o mezcla datos. Un contrato de recursos permite ampliar concurrencia con conocimiento de sus límites.

## Anti-ejemplo

Caso hipotético: varios agentes tienen worktrees propios, pero todos cargan la misma conexión de pruebas. Una suite vacía las tablas antes de empezar y otra falla de forma intermitente. El equipo investiga al modelo cuando la causa es un estado compartido sin propietario.

## Protocolo (3 pasos)

| Paso | Trabajo | Señal de aceptación |
| --- | --- | --- |
| Inventariar | Localizar recursos fuera del checkout | Propiedad y uso compartido explícitos |
| Colisionar | Probar interferencias en entorno seguro | Fallos visibles o separación comprobada |
| Cerrar | Detener y conservar según propietario | Sin procesos huérfanos ni pérdida de evidencia |

## Relacionado

- [Sandboxed Work: el nuevo perímetro de ejecución para agentes en producción](/magazine/sandboxed-work-perimetro-ejecucion-agentes-produccion-es)
- [Swarm budget: reserva agentes para verificar, no solo para producir](/magazine/swarm-budget-reservar-agentes-verificar-es)

## Fuentes consultadas

- [Git — git-worktree](https://git-scm.com/docs/git-worktree)
- [Anthropic — Effective harnesses for long-running agents](https://www.anthropic.com/research/effective-harnesses-for-long-running-agents)

## Próximo paso

Antes de añadir otro agente paralelo, revisa qué conexión de datos y qué procesos usaría. Si no puedes distinguir sus recursos de los de la tarea actual, todavía falta aislamiento.

## Lecturas conectadas

- [Swarm budget: reserva agentes para verificar, no solo para producir](https://www.brthls.com/magazine/swarm-budget-reservar-agentes-verificar-es) — Conexión editorial.
- [Sandboxed Work: el nuevo perímetro de ejecución para agentes en producción](https://www.brthls.com/magazine/sandboxed-work-perimetro-ejecucion-agentes-produccion-es) — Conexión editorial.
- [Trazas multiagente: reconstruir quién causó el cambio](https://www.brthls.com/magazine/trazas-multiagente-causalidad-delegacion-es) — En la misma categoría.

---

_Cite as: Berthelius, V. (2026). "Worktrees para agentes: aislar archivos no aísla el sistema". BRTHLS Magazine. https://www.brthls.com/magazine/worktrees-agentes-estado-compartido-es_
