
Soixante conteneurs sur un seul serveur
Une machine bare-metal exécute des dizaines à des centaines de conteneurs Hoody. La dédupplication KSM et BTRFS rend le coût marginal quasi nul.
Un agent de recherche reçoit un prompt complexe. Plutôt que de tout faire lui-même, il poste vers l'API containers et récupère trois URLs de sous-agents. Chaque sous-agent peut lancer ses propres sous-agents. Aucun d'eux ne connaît d'orchestrateur. Ils s'appellent simplement les uns les autres en HTTP.
Chaque nœud de l'arbre est un conteneur Hoody avec un service hoody-agent. Parents et enfants ne se connaissent que par URL. Pas de planificateur central qui regarde d'en haut.
Reçoit le prompt. Décide quelles sous-tâches faire fan-out. POST vers l'API containers pour lancer un nouveau conteneur par sous-agent, puis appelle l'endpoint /api/v1/agent/tasks de chacun avec la part de travail qu'il possède.
Chacun tourne dans son propre conteneur avec son propre système de fichiers, son propre terminal, et SQLite. Aucun ne peut corrompre les autres. N'importe lequel peut décider qu'il a besoin d'aide et lancer ses propres enfants de la même manière que le parent l'a fait. Le protocole est symétrique.
Le fact-checker voit cinq revendications, lance cinq conteneurs en parallèle, tire cinq requêtes HTTP, attend cinq réponses. Même pattern, un niveau plus profond. Les conteneurs inactifs ne coûtent rien, donc les arbres profonds sont économiquement gratuits.
Pas de runtime d'agent à installer, pas de bus de messages à configurer, pas d'état partagé à synchroniser. L'agent parent utilise la même API Containers qu'un humain utiliserait : POST pour créer, puis appel à l'URL de l'enfant.
// Parent agent (running in its own Hoody container).
// Spawn three sub-agents, hand each one a slice of work,
// await their results in parallel.
const HOODY = 'https://api.hoody.com';
async function spawnChild(name) [
// 1. Create a fresh container with the agent service running.
const res = await fetch(HOODY + '/api/v1/projects/' + PROJECT + '/containers', [
method: 'POST',
headers: [ authorization: 'Bearer ' + TOKEN ],
body: JSON.stringify([
name,
server_id: SERVER,
container_image: 'debian-12',
hoody_kit: true,
ai: true,
]),
]);
const child = (await res.json()).data;
// 2. Hit the child's agent URL like any other HTTP service.
const agentUrl = 'https://' + PROJECT + '-' + child.id + '-agent-1.' + SERVER + '.containers.hoody.com';
return [ id: child.id, agentUrl ];
]
const [scrape, summarize, factCheck] = await Promise.all([
spawnChild('scrape'),
spawnChild('summarize'),
spawnChild('fact-check'),
]);
// 3. Dispatch tasks. Each child runs autonomously,
// can spawn its own children the same way.
const results = await Promise.all([
fetch(scrape.agentUrl + '/api/v1/agent/tasks', [ method: 'POST', body: JSON.stringify([ description: scrapeBrief ]) ]),
fetch(summarize.agentUrl + '/api/v1/agent/tasks', [ method: 'POST', body: JSON.stringify([ description: summarizeBrief ]) ]),
fetch(factCheck.agentUrl + '/api/v1/agent/tasks', [ method: 'POST', body: JSON.stringify([ description: factCheckBrief ]) ]),
]);Les deux endpoints sont des APIs Hoody documentées : POST /api/v1/projects/$PID/containers lance un nouveau conteneur avec le service agent préinstallé ; POST $CHILD_URL/api/v1/agent/tasks dispatche une tâche vers lui. Le fact-checker peut exécuter exactement le même code pour lancer ses propres vérificateurs par revendication — la récursion, c'est juste du HTTP.
Chaque framework d'agent est une fine couche au-dessus d'appels de fonction in-process. Tous supposent que les agents partagent la mémoire, partagent Python, partagent un seul runtime. Hoody suppose l'inverse : les agents sont des ordinateurs séparés, et HTTP est déjà le protocole qu'ils parlent.
POST /api/v1/projects/$PID/containers
fetch(child.url + '/api/v1/agent/tasks')
Deux appels HTTP par enfant. Le parent n'importe pas de framework, n'enregistre pas d'outil, ne partage pas d'état. Chaque sous-agent est un pair avec une URL — même forme que le parent, même forme que celle avec laquelle vous appelleriez n'importe quel autre service HTTP.
Chaque agent est un pair avec une URL. Ils s'appellent les uns les autres comme n'importe quel service HTTP appelle n'importe quel autre service HTTP.
Pas d'orchestrateur. Pas de bus de messages. Pas d'état partagé à synchroniser. La seule chose qui limite combien d'agents vous lancez en parallèle, c'est combien vous voulez dépenser — et les conteneurs inactifs ne coûtent rien.
Les frameworks d'orchestration et les services de runtime éphémère auxquels les gens font appel quand un agent ne suffit pas. Chacun résout une part du problème. La primitive HTTP-native remplace la part et le framework qui l'enveloppe.
Arrêtez de câbler des graphes d'agents. Lancez-en un. Laissez-le lancer le reste.