
Sixty containers on one server
One bare-metal box runs dozens to hundreds of Hoody containers. KSM and BTRFS dedup make the marginal cost near zero.
A research agent receives a complex prompt. Instead of doing everything itself, it posts to the containers API and gets back three sub-agent URLs. Each sub-agent can spawn its own sub-agents. None of them know about an orchestrator. They just call each other over HTTP.
Every node in the tree is a Hoody container with a hoody-agent service. Parents and children only know each other by URL. There is no central planner watching from above.
Receives the prompt. Decides which sub-tasks to fan out. POSTs to the containers API to spawn one new container per sub-agent, then calls each one's /api/v1/agent/tasks endpoint with the slice of work it owns.
Each runs in its own container with its own filesystem, terminal, and SQLite. None can corrupt the others. Any of them can decide it needs help and spawn its own children the same way the parent did. The protocol is symmetric.
The fact-checker sees five claims, spawns five containers in parallel, fires five HTTP requests, awaits five responses. Same pattern, one level deeper. Idle containers cost nothing, so deep trees are economically free.
There is no agent runtime to install, no message bus to configure, no shared state to synchronise. The parent agent uses the same Containers API a human would: POST to create, then call the child's URL.
// 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 ]) ]),
]);Both endpoints are documented Hoody APIs: POST /api/v1/projects/$PID/containers spawns a new container with the agent service preinstalled; POST $CHILD_URL/api/v1/agent/tasks dispatches a task to it. The fact-checker can run the exact same code to spawn its own per-claim verifiers — the recursion is just HTTP.
Every agent framework is a thin layer on top of in-process function calls. They all assume agents share memory, share Python, share a single runtime. Hoody assumes the opposite: agents are separate computers, and HTTP is already the protocol they speak.
POST /api/v1/projects/$PID/containers
fetch(child.url + '/api/v1/agent/tasks')
Two HTTP calls per child. The parent doesn’t import a framework, doesn’t register a tool, doesn’t share state. Every sub-agent is a peer with a URL — same shape as the parent, same shape as you would call any other HTTP service.
Each agent is a peer with a URL. They call each other the way any HTTP service calls any other HTTP service.
There is no orchestrator. There is no message bus. There is no shared state to synchronise. The only thing that limits how many agents you run in parallel is how much you want to spend — and idle containers cost nothing.
The orchestration frameworks and ephemeral-runtime services people reach for when one agent isn’t enough. Each one solves a slice of the problem. The HTTP-native primitive replaces the slice and the framework wrapped around it.
Stop wiring agent graphs. Spawn one. Let it spawn the rest.