Yo desarrollando harnesses y usando varios me di cuenta un patrón interesante que no fuí la única quién lo notó.
Los agentes son mas útiles cuando su instrumentación está hecha en bash shell en vez de tool calls.
Un agente no necesita aprender otro protocolo de ejecución como las tool calls en JSON para delegar acciones. Si le das acceso a una shell puede hacer todo y mas con sintaxis unix/posix like.
Menos tool calls, acciones encadenadas con pipes y operadores de control de flujo:
head -n 5 file.txt > split_1.txt
tail -n 5 file.txt > split_2.txt
Usa menos tokens y tiene el mismo resultado que
{ action: "read_file", target: "file.txt" }
{ response: "1234567890" }
{ action: "write_file", target: "split_1.txt", content: "12345" }
{ action: "write_file", target: "split_2.txt", content: "67890" }
Los primeros agentes se manejaban de la 2nda manera. Teniendo que escribir JSON perfecto cuando no hay o no había tokenización precisa para las tool calls en crudo. Sin embargo si la hay y de sobra para shell/unix like scripts.
---
Siguiente paso: normalización.
En vez de darle acceso a una shell podemos darle acceso a una terminal falsa con comandos builtins y flags que imitan un entorno unix.
Formatear el resultado o la salida de las herramientas en formato legible y tokenizable, como CSV, Markdown o información comprimida antes que el agente vuelva a pedirlo.
---
Se reducen las tools calls si el harness revisa la intención de ejecución del modelo LLM antes de pedirlo.
$ echo "content" > file.txt
Error: Lee el archivo al menos una vez antes de escribirlo.
Se reducen las iteraciones y turnos cuando se delega a subagentes tareas especificas.
"Arreglá este bug de autenticación".
Agente 1: Revisa donde está el módulo de auth, endpoints, servicios, etc... Ensucia el contexto de contenido de archivos y rutas que no vamos a usar a la hora de hacer la implementación pero que NO queremos perder a la hora de buscar donde implementar el cambio.
Agente 2: Recibe un brief del descubrimiento del Agente 1, solo la conclusión, no como llegó a ella. Escribe la implementación sin pensar por que hacerlo ahí. En caso de necesitarlo, puede preguntarle al sub agente anterior que aún conserva el contexto.
Fin del turno: Los sub agentes efimeros se descartan. Se salvan sus conclusiones finales y van a parar al orquestador para tener un registro de pensamiento lógico que llevó a la conclusión de ese turno del loop.
---
El arte de ahorrar tokens no es por cuestiones económicas. Si no para cuidar la context window. El agente es mas preciso cuando tiene menos obligaciones y responsabilidades, pero no podemos eliminar esas responsabilidades del loop entero. Podemos activarlas y desactivarlas a voluntad. Operar con estados efimeros dinamicos formados desde el historial entero representativo guardado de forma persistente.
El agente es stateless. El futuro del coding con agente es stateless y efimero. El último tramo del contexto es dinamico. Se construye en runtime, se recorta al finalizar, se cachea en el provider una vez quitada toda la información que sobre, que puede volver a estar en los sub agentes, por algo son efimeros, pero no en el orquestador, el orquestador y todo lo demas es stateless.
---
Esa fue mi investigación sobre harnesses y agentes en el último año. Vi que Claude y Codex adoptaron estas medidas, excepto Antigravity. La diferencia es increíblemente notoria.
Usar el mismo modelo en harnesses diferentes que implican o no medidas stateless y de delegaciones mejoran potencialmente las capacidades del LLM, o en su defecto, lo vuelve inútil en el peor de los casos.
🫡