---
title: "Varios agentes de programación, un repositorio: declaraciones en lugar de bloqueos"
description: "Cómo evita Foxl Code que agentes en paralelo editen los mismos archivos: declaraciones sin bloqueo, solapamiento de globs, liberación al acabar y coste en D1."
author: "Foxl Team"
date_published: "2026-10-23"
date_modified: "2026-10-27"
canonical_url: "https://foxl.ai/es/blog/parallel-coding-agents-file-claims"
markdown_url: "https://foxl.ai/es/blog/parallel-coding-agents-file-claims/index.md"
image: "https://foxl.ai/blog/parallel-coding-agents-file-claims-cover.png"
social_image: "https://foxl.ai/blog/social/parallel-coding-agents-file-claims.png"
content_type: "Deep dive"
topics: ["Coding agents","Multi-agent","Claude Code","Codex","Cloudflare D1"]
products: ["Foxl Code"]
---

<!-- Generated by scripts/blog-publishing.mjs; do not edit. -->

# Varios agentes de programación, un repositorio: declaraciones en lugar de bloqueos

> Los agentes de programación en paralelo chocan al hacer merge porque ninguno sabe qué están editando los demás. Los agentes en la nube de Foxl Code ahora declaran los archivos que van a cambiar y reciben como respuesta cuáles de tus otros agentes activos ya han declarado una ruta que se solapa. La declaración se registra en cualquier caso y no bloquea nada; ante un conflicto, al agente se le indica que envíe el cambio al titular, que espere o que te pregunte. Salida real del comando publicado, las reglas de los globs, el coste en la base de datos y si los agentes siguen de verdad la regla, algo que aún no sabemos.

- Author: Foxl Team
- Published: 2026-10-23
- Last reviewed: 2026-10-27
- Reading time: 12 minutes
- Canonical HTML: [https://foxl.ai/es/blog/parallel-coding-agents-file-claims](<https://foxl.ai/es/blog/parallel-coding-agents-file-claims>)

![Un archivo con las etiquetas de dos agentes atadas a una esquina, una azul y otra naranja, y un candado abierto a su lado: las dos declaraciones sobre el archivo quedan registradas y no hay nada bloqueado.](<https://foxl.ai/blog/parallel-coding-agents-file-claims-cover.png>)

Si ejecutas varios agentes de programación en un mismo repositorio, chocan al hacer merge, porque ninguno sabe qué están editando los demás. Foxl Code ejecuta en la nube agentes de programación como Claude Code y Codex, y desde v0.9.3-beta.5 a cada agente se le indica que declare las rutas que va a cambiar ejecutando `foxl-agents claim <paths>` antes de editar. Si otro agente del mismo usuario que sigue en marcha (un agente activo) ya ha declarado una ruta que se solapa, la respuesta nombra a ese agente y la nota que dejó. No se bloquea nada. Ante un conflicto, al agente se le indica que envíe al titular el cambio que necesita, que espere a que el titular libere la declaración o que pregunte al usuario, y sus propias declaraciones desaparecen cuando termina su ejecución.

## Por qué chocan los agentes de programación en paralelo

Cada agente trabaja en su propio checkout y en su propia rama, así que nada impide que dos de ellos cambien el mismo archivo. Git informa de un conflicto textual cuando se hace merge del segundo pull request, después de que los dos agentes hayan terminado y se hayan pagado. Un conflicto semántico, en el que dos pull requests pasan cada uno sus comprobaciones pero rompen la build cuando se fusionan los dos, no lo notifica nada hasta que una persona fusiona ambos. Las declaraciones detectan ese tipo de conflicto solo cuando los dos agentes tocan las mismas rutas.

Nuestra propia forma de trabajar nos enseñó qué ayuda. Desarrollamos Foxl con entre 15 y 20 sesiones de Claude Code ejecutándose en paralelo sobre su repositorio, y en 14 días se enviaron entre ellas 4.773 mensajes. Lo que evitó que se sobrescribieran unas a otras fue una lista compartida de responsables. Una sesión coordinadora registra qué sesión es responsable de qué archivos (y, en un archivo que tocan muchas sesiones, de qué partes), y una sesión que necesita un cambio en un archivo del que no es responsable envía el cambio al responsable en lugar de hacerlo ella. Antes de la lista, varias sesiones editaban los mismos archivos a la vez y se enteraban al hacer merge. La lista tenía su propio coste: de las 123 veces que una sesión se quedó bloqueada en esos 14 días, 33 fueron esperas a que respondiera la coordinadora.

Foxl Code ya tenía la parte de mensajería: un comando `foxl-agents` que cada agente en la nube puede usar para listar los demás agentes activos del usuario y enviarles un mensaje. Las declaraciones añaden la lista de responsables sin coordinador: cada agente dice qué va a tocar y la base de datos responde en una sola petición.

## ¿Por qué declaraciones y no bloqueos?

Un bloqueo solo funciona si todos los agentes lo respetan y todos lo liberan. Un agente de programación que se cuelga, se queda sin presupuesto o se cancela no libera nada, así que un bloqueo necesita un tiempo de espera, y uno lo bastante largo para una ejecución real (las nuestras pueden durar más de siete horas) bloquea a todos durante ese tiempo. Dos agentes que necesitan cada uno una línea del archivo del otro se esperarían mutuamente para siempre. Y a un agente al que se le deniega un bloqueo no le queda otra cosa que hacer que detenerse.

Las declaraciones esquivan cada uno de estos problemas. Un titular que se ha colgado deja de contar en cuanto su ejecución ya no está activa, así que no hay ningún tiempo de espera que aguantar. Una declaración que se solapa con otra no se deniega: se registra, y el solapamiento vuelve al agente que preguntó, con el id de tarea, el título, las rutas declaradas y la nota del titular. Y a un agente que se topa con un conflicto se le indica primero que envíe al titular el cambio que necesita, de modo que dos agentes que necesitan archivos del otro tienen algo que hacer además de esperar, aunque nada impide que los dos esperen de todos modos. Estas son, palabra por palabra, las instrucciones que recibe cada agente:

```
- Before you start editing, claim the files and directories you expect to
  change, in one command: `foxl-agents claim <path>... --note "<why>"`. A
  directory claims everything under it; `*`, `?` and `**` globs work. Claim
  what you will change, not the whole repository, and claim again if your
  plan grows.
- The answer names any other live agent that already claimed an overlapping
  path. On a CONFLICT, do not edit those files: send the holder the exact
  change you need with `foxl-agents send <task-id> "<the change>"`, wait until
  it releases them (check `foxl-agents claims` at a natural checkpoint, never
  in a loop or behind a `sleep`), or tell the user. A claim is information,
  not a lock.
- `foxl-agents release <path>...` drops a claim you no longer need. Every
  claim you hold is dropped when your run ends.
```

Estas líneas se añaden al archivo de instrucciones de usuario que lee cada CLI: CLAUDE.md para Claude Code y AGENTS.md para Codex, Kiro, Cursor, Hermes y OpenCode. El mismo mecanismo tiene que llegar a seis CLI distintas, y por eso `foxl-agents` es un comando de shell y no un servidor MCP. Todas las CLI de programación pueden ejecutar un comando de shell, así que un solo script funciona en las seis sin configurar cada una para que cargue un servidor.

## Qué ejecuta un agente y qué ve

A continuación, la salida real del comando publicado, ejecutado por un script y no por un agente, para dos tareas de demostración en un repositorio de demostración. La tarea A es una tarea de Codex que añade limitación de peticiones, y la tarea B es una tarea de Claude Code que añade paginación al endpoint de usuarios. El servidor, su base de datos y el comando son los mismos que reciben los agentes en la nube.

![Salida de terminal. La tarea A declara src/api/middleware.ts y src/api/routes.ts con la nota 'adding a token bucket per API key' y se le dice que ningún otro agente activo ha declarado una ruta que se solape. Después, la tarea B declara el directorio src/api/ y recibe un CONFLICT que nombra a la tarea A, su título, los dos archivos y su nota, seguido de la instrucción de enviar el cambio al titular, esperar a que lo libere o avisar al usuario. Un listado de las declaraciones activas muestra las de las dos tareas.](<https://foxl.ai/blog/parallel-coding-agents-file-claims-terminal.png>)

_Figura 1. Salida capturada del comando publicado contra el servidor publicado, ejecutándose en local en workerd (el runtime de Workers de Cloudflare), el 23 de octubre de 2026. La declaración de la tarea B también queda registrada._

La tarea B declaró `src/api/` con una barra final, que indica un directorio, y el servidor lo guardó como `src/api/**`. Sin la barra, el propio comando habría añadido `/**`: se ejecuta dentro del checkout, el único sitio que puede distinguir un archivo de un directorio. El comando también reescribe cada ruta como relativa a la raíz del repositorio, sea cual sea el directorio de trabajo, y rechaza una ruta fuera del checkout antes de enviar nada.

El conflicto nombra los dos archivos de la tarea A y su nota, y la tarea B decide a partir de la nota. Aquí podría dejar en paz el middleware y enviar a la tarea A el único cambio que necesita ahí, o empezar por el propio handler del endpoint y volver a mirar cuando la tarea A haya liberado.

## ¿Cómo se sabe si dos globs se solapan?

Dos declaraciones se solapan cuando al menos una ruta coincide con las dos. La gramática es pequeña a propósito:

- una ruta normal es un glob sin comodines;
- `*` coincide dentro de un segmento de ruta;
- `?` coincide con exactamente un carácter;
- un segmento que es exactamente `**` coincide con cualquier número de segmentos completos;
- cualquier otro carácter es literal, así que `[id].tsx` es un nombre de archivo, no una clase de caracteres.

Esto es lo que devuelve el comparador publicado para algunos pares:

| declaración A | declaración B | solapamiento |
| --- | --- | --- |
| `src/api/**` | `src/api/users.ts` | sí |
| `src/*.ts` | `src/api/users.ts` | no, `*` se queda en un segmento |
| `src/**/*.test.ts` | `src/api/*.ts` | sí, las dos coinciden con `src/api/x.test.ts` |
| `docs/**` | `src/**` | no |
| `src/app/[id]/page.tsx` | `src/app/a/page.tsx` | no, `[id]` es literal |
| `**/*.md` | `docs/guide.md` | sí |

Un solapamiento nunca hace que se rechace una declaración, pero algunas formas sí:

- un glob hecho solo de comodines que incluye `**`, como `**` o `**/*`, porque declararía el repositorio entero;
- un segmento de ruta `..`, una barra invertida o un carácter de control;
- un `!` inicial, porque aquí no es una negación y no debe parecerlo.

Una tarea tiene como máximo 50 declaraciones, de hasta 200 caracteres cada una, con notas de hasta 280 caracteres.

La comparación tiene un límite para que un conjunto inusual de declaraciones no le cueste mucha CPU al servidor. Dos declaraciones cuyos segmentos literales iniciales difieren (`docs/**` y `src/**`) se descartan de inmediato. Si no, el servidor hace un recorrido memoizado por pares de segmentos y, dentro de un segmento, por pares de caracteres. Todas las comparaciones de una petición comparten un presupuesto de 50.000 pasos, y un par al que no llega el presupuesto se notifica como posible solapamiento en lugar de descartarse, así que una petición que agota el presupuesto sigue avisando al agente.

## Cuándo termina una declaración

Una declaración pertenece a una ejecución. Cuando la ejecución termina, la tarea retira todas las declaraciones que hizo, en el mismo paso que registra la ejecución como finalizada. Dos comprobaciones al leer cubren una ejecución que nunca llegó a ese paso: se ignora una declaración cuyo titular ya no está activo, y también una declaración más antigua que lo máximo que puede durar una ejecución, 7 horas y 20 minutos. Las declaraciones tienen la misma visibilidad que los mensajes: solo los agentes activos de un mismo usuario, que trabajan a través de la misma instalación de la GitHub App en el mismo repositorio, pueden ver las declaraciones de los demás.

![Dos agentes y una tabla de declaraciones. El agente A declara dos archivos y se le dice que no hay solapamiento. El agente B declara el directorio que los contiene, su declaración se escribe y recibe un conflicto que nombra al agente A. El agente B tiene entonces tres opciones: enviar el cambio al agente A, esperar a que el agente A libere o preguntar a la persona. Cuando una ejecución termina, sus declaraciones se eliminan.](<https://foxl.ai/blog/parallel-coding-agents-file-claims-flow.png>)

_Figura 2. El conflicto vuelve al agente que preguntó. No se rechaza nada por solaparse y nada espera a un bloqueo._

## Cuánto cuesta en un plan de base de datos gratuito

Las declaraciones viven en una tabla con un único índice sobre (usuario, repositorio, hora de creación), y nada la consulta periódicamente. Cada lectura pide solo las declaraciones creadas en las últimas 7 horas y 20 minutos, y la hora de creación es la última columna del índice, así que las filas más antiguas quedan fuera del rango que recorre la base de datos. Las declaraciones caducadas que nadie liberó añaden una fila a una lectura tanto si hay 1.000 como si hay 2.000; medimos los dos casos.

Lo medimos porque Foxl funciona en el plan gratuito de Cloudflare, donde todas las bases de datos D1 de una cuenta comparten 5 millones de filas leídas y 100.000 filas escritas al día, y la cuenta dispone de 100.000 peticiones de Worker al día. Las cifras de abajo salen de D1 ejecutándose en local en workerd, el runtime de Cloudflare, y aún no se han confirmado con las propias métricas de D1 en producción:

| llamada | filas leídas | filas escritas |
| --- | --- | --- |
| declarar N rutas | unas 2 por cada declaración activa en el repositorio, más 1 por ruta aproximadamente y unas pocas lecturas fijas | 2 por ruta |
| listar declaraciones | 1 + 2 por cada declaración activa | 0 |
| liberar | alrededor de 1 por ruta | 1 por fila liberada |
| termina una ejecución que nunca declaró nada | 0 | 0 |

Con unas 50 tareas en la nube al día entre todos los usuarios y dos llamadas de declaración cada una, son 100 llamadas al día. Cada llamada son dos peticiones de Worker, una en code.foxl.ai y otra por un salto interno hasta el servidor, así que unas 200 peticiones, el 0,2 % de las 100.000 del plan gratuito. Aunque cada una de esas llamadas costara lo que la de un usuario muy activo en el peor caso (diez agentes con cinco declaraciones cada uno en un mismo repositorio), el día leería unas 11.000 filas (el 0,2 % de los 5 millones) y escribiría unas 830 (el 0,8 % de las 100.000).

## ¿De verdad siguen los agentes la regla?

Aún no lo sabemos, y esta fase está hecha para averiguarlo. Nuestras propias sesiones locales necesitaban una coordinadora para hacer cumplir la misma regla, así que no damos por hecho que seis CLI distintas vayan a declarar antes de editar y a retirarse ante un conflicto solo porque sus instrucciones lo digan. Cada conflicto escribe un registro de auditoría (cada instancia del servidor omite una repetición para la misma tarea y los mismos titulares en diez minutos), y lo mismo ocurre con cada mensaje que un agente envía a otro. Si un agente escribió al titular se ve en el registro de auditoría, si liberó su declaración se ve en la tabla de declaraciones, y si editó el archivo de todos modos se ve en el diff del pull request.

La siguiente fase depende de lo que eso muestre. Si los agentes respetan las declaraciones, el plan es que la parte de Foxl Code que reparte una petición entre varios agentes dé a cada subtarea una lista de archivos y ejecute una tras otra, y no a la vez, las subtareas que se solapan. A 23 de octubre de 2026 la tabla de producción está vacía, porque no ha empezado ninguna tarea en la nube desde que se desplegó la función.

Si estás construyendo algo parecido, las tres propiedades que conservaríamos son que una declaración siempre se registra, que un solapamiento vuelve con un titular y una nota, y que una declaración dura solo lo que dura su ejecución. Nuestro artículo del lanzamiento de Foxl Code explica el propio bucle del agente, que [se va ajustando hacia un objetivo en lugar de fiarse de cada paso](<https://foxl.ai/blog/foxl-code-autonomous-agents>).

## Referencias y lecturas recomendadas

1. [Precios de Cloudflare D1 y límites del plan gratuito](<https://developers.cloudflare.com/d1/platform/pricing/>) - Documentation
2. [Versión v0.9.3-beta.5 de Foxl](<https://github.com/foxl-ai/foxl/releases/tag/v0.9.3-beta.5>) - Release