The window was the wrong container.
The instinct when you automate a second client is to make the assistant smarter: one capable agent that knows about every server you touch. That works until roughly agent five, then it fails in a way that looks like the model getting worse.
It is not the model. It is arithmetic. Our fleet's working context is 3.26 MB of prose, or about 856,000 tokens. A 200K-token window holds a fifth of it. The thing we wanted to put in the window was 4.3 times larger than the window, and it grew every time we signed a client.
Even if it fit, it should not go in. Every token describing another client's database schema is a token of noise for the task in front of you, and a fact the agent can act on by mistake. Capacity was the obvious problem. Blast radius was the real one.
Stop paging context into the window. Give the window an address.
Context became infrastructure.
We stopped treating a context window as a conversation that accumulates and started treating it as a named, addressable resource, something with a path, an owner, and a lifecycle, like a database or a volume.
Once context has an address, the question becomes what to bind that address to. We bound it to a single SSH host. One agent, one context, one machine it is allowed to touch. The unit of work stopped being "a chat" and became a (context, host) pair that outlives any individual conversation.
The practical effect: the context window is no longer something we assemble per request and hope fits. It is a directory on disk. It is the same directory tomorrow. You can read it, diff it, and grep it without asking a model what it remembers.
The boundary already existed.
An SSH host is not an arbitrary partition key. We picked it because it comes with three properties we would otherwise have had to build, badly:
Already a permission model
Keys, users, and host-level access are decades-hardened. We inherit authorization instead of inventing an agent permission system that only we review.
Already uniquely named
DNS hands you a globally unique, human-meaningful name. example.com becomes the primary key across directory, channel, session, and host, no ID mapping table.
Already a blast radius
"This agent can reach one machine" is a sentence a client understands. Scope is enforced in the sandbox rules, not left to the model's good manners.
The mapping is one name across four resources, so there is nothing to look up and nothing to drift:
agents/example.com/#example.comexample-comexample.comWhat a context window looks like on disk.
The agent directory is the context window, materialised. context.md is the resident memory the model reads on every wake; the SSH host is the hands. Everything else is working state that survives the process.
agents/example.com/
context.md identity, scope, host, routines (~14 KB)
.cursor/ sandbox rules: the enforced boundary
logs/ dispatch.log: every message, JSON lines
utilities/ scripts this agent wrote for this host
routines/ scheduled work, run in its own session
→ ssh example.com (the only host in scope)
The median context.md across the fleet is 14.3 KB, roughly 3,700 tokens, or 1.8% of a 200K window. The agent is not straining against a limit. It has room to work, because it is only carrying one machine's worth of truth.
Hibernation is swap.
If context lives on disk rather than in a process, the process becomes disposable. That is the payoff. An agent idle for 24 hours has its tmux session killed; its context is untouched, because the context was never in the session.
- Idle — Nothing for 24 hours, the session is killed and the RAM is returned.
context.md, logs, and utilities stay exactly where they were. - A message arrives — Anything posted for a sleeping agent is written to a pending queue first, so it cannot be lost in the gap.
- Wake — The session is rebuilt from the directory. The agent re-reads its context and comes back knowing what it knew.
- Replay — The queued messages are delivered in order, and the agent answers as if it had been awake.
Right now 21 of 164 agents are resident. The other 143 cost nothing but disk, and are one message away from running. A fleet that would need 164 live processes needs about an eighth of that, because we page on demand.
Measured on the running fleet.
- 164 agentsEach with its own context, channel, session, and host. 142 resolve to an exact alias in
~/.ssh/config; the rest reach their host by other means. - 856K tokens of context3.26 MB total, 4.3× a single 200K window. It never has to fit, because it is never loaded at once.
- 3,700 tokens loadedThe median agent's working context. The largest is 35K tokens, and that one is an outlier we intend to split.
- 21,674 dispatch eventsLogged across 164 per-agent logs as JSON lines. The audit trail is per host, not a single shared firehose.
- 13% resident21 live sessions serving a 164-agent fleet from one laptop.
What this costs.
Isolation is the feature, so the bill arrives as isolation. Three things get harder, and it is worth knowing them before you copy the pattern:
- Agents cannot learn from each otherA fix discovered on one host does not propagate. One shared, read-only file sits above the fleet for genuinely universal rules, deliberately small, because everything in it is loaded 164 times.
- Fleet-wide changes need fan-outGranting one new read path meant editing 164 sandbox files. Scripted, but it is real work, and a change that would be one line in a monolith is a migration here.
- Duplication is the defaultThe same deploy recipe exists in dozens of context files with small drifts. We treat that as acceptable: a stale line in one agent breaks one host, not the fleet.
What it bought.
The fleet grew past a hundred agents without the architecture changing, because nothing in it scales with fleet size. Each agent's cost is fixed at one context and one host. Adding a client is scaffolding a directory, not rebalancing a prompt.
The part that mattered most was not capacity. It was being able to answer "what can this thing touch?" with one hostname. That sentence is why the pattern survives contact with clients, and why we still run it every day.
Start a conversation All case studies