You reach a point running AI agents at scale where the filesystem becomes your primary bottleneck. Not disk space. Not performance. Navigation itself.
The naive structure is a flat folder: products/nano/, products/loopcdn/, products/context-vault/, products/glance/, and seventeen others. It works at five projects. At twenty, something breaks. Not catastrophically — the code still runs. But every agent that needs to understand what you're building now has to inspect each folder to figure out what it actually is. Is this a one-file hobby? A five-repo ecosystem? An abandoned experiment? The filesystem gives no signal.
I've been running a fleet of agents across fifty-plus projects simultaneously. The cost of undifferentiated folders was measurable: agents burning tokens on orient work that should have been instant. Humans landing in the repo and spending ten minutes just figuring out which projects were active and which were shells.
The solution isn't to shrink the number of projects — you want more projects because each one is a small, focused service. The solution is to make the structure of the filesystem a readable map instead of a dump.
Orient-cost: the metric that matters
In AI-first organizations, there's a hidden cost that doesn't show up in API bills. Call it orient-cost: the token budget spent by agents (and humans) just figuring out what they're dealing with before they can do any real work.
An agent lands in your project folder and runs ls products/. Fifty entries. Without metadata, the agent has to inspect each one. Check the README. Scan for git branches. Look for recent commits. Read the AGENTS.md file if it exists. Some folders have state; some are just template code. Some are active projects; some are archived experiments never deleted. The filesystem is a search problem.
Scale this: fifty agents a day landing in your repo, each spending 2–3 minutes of inference orienting. That's a hundred-plus agent-hours burned on context-gathering that could have been work.
The number of projects isn't the real problem. The undifferentiation is.
Two products, one filesystem
Here's the concrete failure: look at two folders side by side in your products/ directory.
products/nano/— a single 200-line file. An experiment from two months ago. Never leaving draft.products/context-vault/— a full product suite. Owns three repos. Has a dedicated connector layer. Runs a live manager seat. Has a paying customer depending on it.
From ls -la, they're identical. Both are directories. Both have an AGENTS.md. Both have a README. The filesystem structure gives zero signal about scope.
Now imagine you have forty products like this, and you need to quickly understand which ones matter, which ones are active, and which ones are small experiments. The only way to know is inspection. And if you want your agents to know the difference, you have to load global state — a manifest file, a database query, some external system to say "this one's big, this one's small."
The better move is to let the filesystem itself be the map.
The three types
I've settled on a three-type taxonomy that emerged from watching which patterns held up:
Seat. An agent role definition. Stateless. Spawnable. Describes what an agent is, not what it owns. It's the template for a worker, an advisor, a manager. Lives in workspaces/_seats/. Examples: worker, advisor, manager, scribe. Contains only the AGENTS.md that defines the role. No state. No inbox. No backlog. When you omni agent start worker, you're instantiating a Seat.
Domain. An ecosystem coordinator. A single resolve point for a product that has grown beyond a leaf. Lives at workspaces/<product-name>/. When you run scaffold resolve vault, it returns the vault Domain — which lists all the pieces that make up the vault ecosystem. The product repo itself lives in products/vault/. The connectors live in omni-connectors/vault. But the Domain is the single authoritative home that says "here's everything about the vault ecosystem."
System. OS-layer infrastructure. Stateful. Running services that coordinate or monitor the fleet. Examples: fleet-medic (monitors agent health), system-curator (maintains system state). Lives in omni-os/, not workspaces/. These have state, may run continuously, and are part of the operating system itself, not products or roles.
That's it. Three categories. Every folder in your workspace hierarchy falls into exactly one.
The promotion rule
A product stays a leaf in products/ until it crosses a threshold. The thresholds are deterministic — no judgment calls, no committee meetings about whether something is "big enough."
A product earns a Domain when it hits any one of these:
- Has a dedicated connector — it owns a module in
omni-connectors/. Once you're building connectors for a product, it's no longer a standalone thing; it's an ecosystem. - Has an active manager seat — a coordinator or manager agent is running continuously for this product's ecosystem. It has enough scope to need its own command structure.
- Spans more than one repo — the product is split across multiple git repositories. Single-repo projects live in
products/. Multi-repo systems get a Domain.
When a product crosses any threshold, you create a Domain workspace at workspaces/vault/ (or whatever the product name is). The product repo itself stays in products/ as one component. The Domain becomes the ecosystem's home — the place where AGENTS.md lists all the pieces, where the arc lives, where agents resolve to when they ask "what is this thing?"
The determinism matters. You don't debate whether a project is "ready" to be promoted. You hit a threshold, and the taxonomy updates. The filesystem stays honest.
Why this works
The insight is subtle. The taxonomy doesn't reorganize your projects. It doesn't add work — actually, it removes it by making the structure legible.
Before: your folder tree is a sequential dump. Agents read it like a book, checking every entry. The information they need (what's an ecosystem, what's a leaf, what's active, what's archived) exists outside the filesystem — in a database, a manifest, the human's head.
After: the filesystem is the information. Walk into workspaces/, and the top-level entries tell you everything. _seats/ is where roles live. Everything else is a Domain — a multi-component ecosystem with a single resolve point. Dead projects moved to _archive/. The structure itself is documentation.
An agent can answer "what is context-vault?" by running one command: scaffold resolve context-vault. It gets back the Domain's AGENTS.md, which says: here are the repos, here's the connector, here's the manager seat, here are the sub-projects. Everything legible. No token budget spent on guessing.
The cost reduction is direct: from O(n) inspections to O(1) resolve. Fifty projects goes from expensive to instant.
Practical implications
Three moves that follow from taking this taxonomy seriously:
Move all role seats to workspaces/_seats/ — your templates for worker, advisor, manager, dispatcher. These are stateless, reusable across projects. They don't have their own backlog or state. Consolidating them signals their purpose to every agent that lands in the repo.
Promote ecosystems to Domains when they cross the threshold — don't postpone the reorganization until it's painful. The moment a product gets a connector or a manager seat, create the Domain. The rename is cheap; leaving it undifferentiated is expensive in token cost.
Archive abandoned projects into _archive/products/ — the naive move is to delete them. Better is to archive them. They're still there if you need them, but they're out of the active navigation path. Agents can skip the _archive/ tree when doing discovery. Dead projects don't tax your active fleet.
The compounding insight: your filesystem is an interface. Structure it for the agents that read it, not for how you happened to organize projects today. The taxonomy is a contract between your filing system and your fleet's orient budget. When the contract gets clearer, the work gets faster.