
Sesenta contenedores en un servidor
Un servidor bare-metal ejecuta decenas a cientos de contenedores Hoody. KSM y dedup BTRFS hacen que el costo marginal sea casi cero.
Quieres que un panel de modelos revise la misma entrada. Cinco contenedores, cinco proveedores distintos, cinco opiniones. El framework de orquestación normalmente se inventa cien líneas para coordinar esto. Tú no las escribes — cada agente tiene su propia ruta de pipe, y el juez hace curl a los cinco en paralelo.
Cada agente corre en su propio contenedor con su propio handle de modelo. Cada uno transmite su veredicto a su propia ruta de pipe. El proceso juez hace curl a las cinco rutas en paralelo — el pipe retiene cada veredicto hasta que el juez se conecta, y entonces transmite los bytes. Sin bus de mensajes, sin framework de orquestación, sin grafo de callbacks.
Cinco contenedores arrancan en paralelo, cada uno con un handle de modelo distinto. El juez hace POST del prompt al endpoint de cada contenedor a la vez.
Mientras el modelo piensa, el agente vuelca su veredicto en pipe/agent-N con PUT. El pipe retiene los bytes — sin disco, sin broker — hasta que alguien los saca con curl.
GET pipe/agent-1 hasta pipe/agent-5 con un curl cada uno. El pipe enruta los bytes de cada agente al juez en cuanto ambos extremos se conectan.
El juez lee JSON de cada ruta, cuenta los votos, devuelve la mayoría. Cinco contenedores, una ruta HTTP cada uno, sin SDK entre ellos.
#!/usr/bin/env bash
set -euo pipefail
PROMPT='review this PR for security issues'
AGENTS=(claude-sonnet gpt-4o gemini llama mixtral)
BASE=https://pipe.hoody.com/api/v1/pipe
# Each container streams its verdict into its own path.
# Five paths fan-in to one judge — no broker, no SDK.
for i in "$[!AGENTS[@]]"; do
N=$((i + 1))
curl -s -X POST "https://agent-$N.hoody.com/v1/run" \
-d "[\"prompt\": \"$PROMPT\", \"sink\": \"$BASE/agent-$N\"]" &
done
# Read all five verdicts in parallel.
VERDICTS=()
for i in 1 2 3 4 5; do
VERDICTS+=("$(curl -s "$BASE/agent-$i")")
done
wait
# Tally — majority wins.
printf '%s\n' "$[VERDICTS[@]]" \
| jq -r .verdict \
| sort | uniq -c | sort -rn | head -1PUT empuja cada veredicto hacia arriba. GET tira de cada uno hacia abajo. El pipe es el cable — los bytes se mueven del agente al juez en cuanto ambos se conectan, con backpressure manejado por ruta. Para añadir un sexto agente, arrancas un sexto contenedor y añades una sexta línea al bucle.
El mecanismo es una sola forma — cinco contenedores, cinco rutas, un juez — pero el valor se lee distinto según contra qué intentes ganar.
No necesitas un framework de orquestación para enviar un prompt a cinco APIs y promediar las respuestas. Un bucle bash con cinco curls ya lo hace. El ensemble de agentes siempre fueron cinco llamadas HTTP disfrazadas.
Añadir un agente: otro contenedor, otra ruta de pipe, una línea más en el fetch paralelo del juez. Quitar uno: matas el contenedor, eliminas la línea. No hay nada que reconfigurar — sin bus de mensajes, sin grafo de callbacks, sin migración de esquema.
Los modelos baratos transmiten primero; los caros solo terminan cuando el consenso no está claro. Como cada agente es un contenedor separado con su propio pipe, puedes cortocircuitar el panel en cuanto tres coincidan — sin estado compartido, sin RPC de aborto, simplemente cierra los pipes.
Cada agente recibe una ruta. La ruta es el cable.
Cinco proveedores de modelo, cinco contenedores, cinco rutas HTTP — y un juez que cabe en veinte líneas de bash. El framework de orquestación siempre fingió que HTTP no existía.
El juez lee cada ruta, cuenta los votos, devuelve la mayoría. Para añadir un agente, arrancas un contenedor y añades una ruta. No hay bus de mensajes que reconfigurar.
Cada framework de aquí trae su propio concepto de "agente" más una forma específica del proveedor de que un agente hable con otro. El pipe colapsa esa superficie a HTTP — una ruta por agente, curl en ambas direcciones.
No necesitas un orquestador. Necesitas cinco contenedores y cinco rutas de pipe. El juez son veinte líneas de bash.