Imaginemos un único con todas las herramientas y la tarea "implementa X, revisa que esté bien y verifica que los tests pasen". Aparecen cuatro problemas: el mismo agente que escribió el código decide si está bien (conflicto de intereses); cuando llega a revisar, su contexto está lleno de intentos fallidos (contexto contaminado); tiene permiso de escritura incluso mientras "revisa" (privilegio máximo todo el tiempo); y si el resultado es malo no sabemos si falló la planificación, la implementación o la verificación (fallas opacas).
Un reparte ese trabajo entre roles. Bien hecho, resuelve esos cuatro problemas. Mal hecho, multiplica el costo y agrega puntos de falla sin mejorar nada. Veamos cómo distinguir un caso del otro.
Dividir por rol
Pipeline Orquestador-worker Paralela
A ──► B ──► C Orquestador ┌─► B ─┐
┌─────┼─────┐ A ┼─► C ─┼─► E
Con rework ▼ ▼ ▼ └─► D ─┘
A ──► B ──► R ──► T B C D
▲ │
└─────┘
La elección no es estética. Un pipeline es fácil de razonar, trazar y reanudar tras un fallo. Un orquestador dinámico es flexible, pero más difícil de acotar en costo y de testear. El paralelismo reduce latencia solo si las subtareas son de verdad independientes (no escriben los mismos archivos).
Los roles clásicos para trabajo de código:
| Rol | Hace | No debería poder |
|---|---|---|
| Lead | planifica y delega | editar código |
| Implementer | escribe el cambio | aprobar su propio trabajo |
| Reviewer | lee el diff, pide cambios | escribir ni ejecutar |
| Tester | corre la suite, da PASS/FAIL | editar archivos |
El pod de docket
Lo central es cómo se hace cumplir cada rol. La plantilla del Reviewer dice "read-only", pero eso no es lo que lo hace read-only.
| Prohibición declarativa | Prohibición estructural |
|---|---|
| prompt: "no uses write" | el registry no contiene write |
| el modelo ve la herramienta | el modelo no la ve |
| un texto persuasivo puede convencerlo | no hay nada que convencer |
| falla en silencio | un intento deja "unknown tool" en la traza |
Handoffs tipados
Concatenar toda la salida de un agente en el prompt del siguiente crece sin límite y mezcla ruido con señal. docket pasa un HandoffArtifact (src/docket/core/handoff.py), un modelo Pydantic que rechaza campos extra, con summary, files_changed, diff_ref y verdict. files_changed no lo declara el modelo: sale de git. Si un dato se puede obtener del mundo real, no se le pregunta al modelo. Cada rol tiene además un de para el handoff (token_budget en archetypes.py) y los campos se descartan en un orden fijo (DROP_ORDER) cuando no caben; el detalle está en Contexto, routing y costo.
Gates que el modelo no puede convencer
Un Implementer dice "listo, los tests pasan". ¿Cómo lo sabemos? Con un gate: una condición evaluada fuera del modelo.
Tres reglas generales salen de aquí:
- Una salida ambigua es un fallo, no un éxito.
- Los ciclos de corrección necesitan techo, o un Reviewer exigente y un Implementer incapaz iteran (y gastan) sin fin.
- Prefiere evidencia mecánica a juicio del modelo. Si un comando puede decidir, que decida el comando; un Tester con modelo es para lo que un comando no puede verificar.
La verificación independiente significa que quien verifica no es quien produjo, no comparte su contexto y no tiene sus herramientas. Un Reviewer que puede escribir tiende a "arreglar" en vez de pedir cambios, y entonces nadie revisa lo que escribió. Además lee el diff, que puede contener texto hostil: lo que ese texto logre depende enteramente de las herramientas del Reviewer.
Cuándo un solo agente es mejor
Cada agente adicional agrega llamadas al modelo, latencia, un handoff donde se pierde información y un punto de falla. "Suena más avanzado" no es una razón.
| Beneficio | Costo |
|---|---|
| revisión independiente | más llamadas, más latencia |
| mínimo privilegio por rol | roles mal diseñados bloquean trabajo legítimo |
| contexto enfocado | pérdida de información en cada handoff |
| fallas localizables | más estados y más código de orquestación |
| gates estructurales | modelos pequeños fallan el formato a menudo |
La recomendación del README de docket coincide con la literatura seria: empieza con el pod mínimo y agrega Reviewer o Tester cuando un gate de calidad concreto justifique los turnos extra.
Tack: el equipo como frontera
Es otra forma legítima de dividir: el tablero decide qué trabajo existe y en qué orden; el harness decide cómo se hace. La frontera del "equipo" es el ítem.
Para CTOs
- Exige una razón concreta para cada rol adicional: un gate que hoy falla o un privilegio que hoy sobra.
- Verifica que los límites de rol estén en el código (registry, ), no en el prompt.
- Pide un
verifyCmdo equivalente mecánico antes de aceptar cualquier gate basado en la opinión de un modelo. - Decide dónde vive la frontera: orquestación dentro de tu runtime o delegación a un harness externo que trazas desde fuera.
Para llevar
- Multi-agente resuelve conflicto de intereses, contexto contaminado y privilegio excesivo, a cambio de costo y coordinación.
- Los roles se hacen cumplir quitando herramientas del registry, no con instrucciones en el prompt.
- Los handoffs deben ser estructuras tipadas, con datos obtenidos del mundo real cuando sea posible.
- Los gates mecánicos y los veredictos estrictamente parseados convierten una mala respuesta en una falla visible.
- Empieza con el sistema mínimo y agrega roles solo cuando una necesidad medida lo pida.
Comprueba lo aprendido
¿Por qué quitar `write` del registry del Reviewer es más fuerte que prohibirlo en su prompt?
Porque el modelo nunca ve la herramienta, así que ningún texto puede convencerlo de usarla, y un intento queda registrado como herramienta desconocida. Una instrucción en el prompt depende de la obediencia del modelo.
¿Qué hace docket si el Reviewer escribe `APPROVE` en una línea y `REQUEST-CHANGES` en otra?
parse_verdict lo trata como no parseable, porque hay dos valores distintos, y un veredicto no parseable bloquea el avance igual que un rechazo.
¿Cuándo es preferible un solo agente?
Cuando no hay un gate ni un límite de privilegio concreto que justifique otro rol, o cuando las subtareas comparten mucho contexto y dependen entre sí. En esos casos, más agentes agregan costo y handoffs con pérdida sin mejorar el resultado.