← All writing

Building Ca$ino

I Deleted All 26 Agents. The Memory Stayed.

Building a data science agent that was actually good meant building two layers of memory first. The orchestration I thought was the product turned out to be scaffolding — and better models ate it. What was underneath generalized to any agent at all.

engineeringagentsarchitectureaiinfrastructure

I set out to build a data science agent that was actually good. What I ended up building was two layers of memory and a pile of infrastructure. Then I deleted most of the part I thought was the agent.

The deleting is what people react to. In February I published a post here about a 26-agent swarm — specialists, an orchestrator, a strategic planner routing work between them. Six weeks later one commit took out all 26, plus the planner and the routing graph.

That's the anecdote. It isn't the point. The point is which half survived, and why the half that survived turned out to be worth more than the thing I was trying to build.


What "good" actually required

A data science agent that works once is a demo. Anyone can get one of those. You hand a model a CSV, it writes some pandas, you get a chart. Impressive for about a day.

A data science agent that's good has to work the second time. Someone runs a quarterly analysis in October and needs the same pipeline in January — not a new adventure, the same one. And within a single session it can't behave like it just met you, because a real analysis is twenty minutes of back and forth and half of that is context it should already have.

Neither of those is a model problem. Both are memory problems, and they're different memory problems, so they became two layers.

The workspace outlives the conversation. Datasets, cleaned exports, charts, reports — they get written to durable storage under the client's own scope, not held in the model's head. The session ends and the work is still there. Run the analysis again next quarter and it starts from artifacts, not from scratch. This is also what made a swarm possible at all: agents never passed messages to each other, they read and wrote the same workspace. The workspace was the coordination.

The agent stops re-asking what it knows. The second layer is semantic memory — recall that persists across sessions and gets searched by meaning rather than by exact match. It replaced a hand-written session-context manager that was mostly a bag of special cases. Without it the agent asks which collections are available, every time, forever. With it, an error it hit in March informs the code it writes in August.

This is the unglamorous half of the work and it was most of the work. Nobody demos it. It doesn't look like anything. It's the difference between a toy and a thing you can run a business on.


The part I thought was the agent

On top of that I built a swarm. Twenty-six specialists — data operations, visualization, statistics, one per connected platform — with an orchestrator on top and a strategic planner deciding who did what and in which order.

26 Names, One Everything
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
specialists — different prompts, different tools
One container, one account, one owner
Owner
me
Bill
mine
Process
one
Off switch
one
Separation existed in the prompts, not in anything that could be owned, paid, or switched off on its own.

I want to be precise about why it existed, because at the time it wasn't a mistake. Every piece of that machinery was compensating for something the models of the moment couldn't do.

A long analysis meant twenty-odd tool calls, and by the end the model's context was mostly its own output — reasoning degraded exactly when the conclusions mattered. An agent asked to be data engineer, statistician, designer and writer at once drifted between roles and did all four adequately. When a step failed, nothing recovered; it just failed harder.

So: narrow the roles, add a planner to hold the plan the model couldn't, inject error history so the second attempt differs from the first. That's not architecture for its own sake. That's a set of workarounds with a diagram drawn around it.


Then the models got better and ate it

The limits I'd built around stopped being limits.

Context windows got big enough that a twenty-call analysis no longer crowded out the reasoning. Models got better at holding a role across a long task without a system prompt narrowing them to one job. They got better at reading their own failure and trying something else, which is what the planner's error-injection was for.

Every one of those improvements deleted a reason for a piece of my scaffolding to exist. By April the swarm wasn't doing work — it was routing between things that no longer needed to be separate. Taking it out cost nothing. Nothing got worse. That's the tell: scaffolding is the part a better model makes redundant.

I'd have kept it much longer if I'd been attached to it. Writing a post about it six weeks earlier probably helped — publishing an architecture makes you notice when you stop believing it.


What didn't get eaten

The memory layers and the infrastructure underneath them. Not one model release has made those less necessary, and I don't expect one to.

A better model with no state is a smarter thing that forgets. It'll write more elegant code against a dataset it can't find, produce a better chart it can't save, and ask you again next week which collections exist. Model improvements multiply against structure. They don't substitute for it.

What a Better Model Ate, and What It Didn't
scaffolding — compensating for model limits
Strategic planner
held the plan the model couldn’t
26 specialists
narrow roles to stop drift
Routing graph
decided who did what
Error injection
made retry #2 differ from #1
deleted in one commit — nothing got worse
models improved
structure — what a model needs regardless
Workspace
artifacts outlive the session
Semantic memory
recall across sessions
Isolation
whose data this is
Metering
who pays for the run
none of it is a reasoning problem, so none of it gets absorbed

A better model with no state is a smarter thing that forgets. Model gains multiply against structure; they don't substitute for it.

That's the whole distinction, and I didn't have language for it while I was building. Scaffolding compensates for what a model can't do yet, so it has a shelf life measured in releases. Structure is what a model needs no matter how good it gets — somewhere to put things, a way to remember, a boundary around whose data this is, a record of what was spent. Nothing on that list is going to be absorbed by a smarter model, because none of it is a reasoning problem.


None of it was actually about data science

Here's what took me longer than it should have.

Once the swarm was gone, what remained was a workspace, two memory layers, sandboxed execution, per-client isolation, and a way to meter what things cost. I'd built every piece of that for a data science agent. Not one piece of it is specific to data science.

That's a substrate. And on top of a substrate, an agent stops being a system you architect. It's a prompt, a set of tools it's allowed to touch, and a name. Registering one is a single call. It shows up, it can be talked to, it can be given work.

So the question changed. Not how do I build the best data science agent — instead, how does someone describe a job and get an agent for it.


An arbitrary agent is worth more than a good one

This sounds like a downgrade and it isn't.

One excellent data science agent is useful to people who have a data science problem. That's a real audience and a narrow one, and I'd have been maintaining it forever — every new connected platform another specialist, every new analysis type another prompt I write.

A substrate that produces agents is useful to anyone with any problem, and I don't write the agents. Someone describes what they need in a sentence and gets something registered, private to them, that they can talk to and come back to. A lease tracker. A reading queue. Something that watches a spreadsheet and complains when a number moves.

None of those are data science. All of them need exactly what the data science agent needed: somewhere to keep things, memory of what happened, a boundary so their stuff is theirs, and a bill that lands on the right person.

The value moved from the agent to what's underneath it. Which is uncomfortable, because the agent is the part you can demo.


And an agent can hand you back a place to look

The last piece is the one I'm most convinced by.

An agent that answers questions is a chat window. What people actually want is the thing they come back to — the view of their data, the dashboard, the list. In the old model that meant the agent built you a web app: a real build, sixty to a hundred and twenty seconds of waiting, a URL, a deploy that could fail.

Now an agent writes a spec — what to show, from which collection, in what shape — and that renders on demand. No build step, nothing to deploy, nothing to wait for. You ask for a way to see your leases and one exists.

Which means an arbitrary agent, created from a sentence, can produce a durable place to look at your own data. That's the part that feels like the actual product to me, and it only works because of the two layers underneath. A view over data requires the data to have been somewhere, in a shape, owned by someone. That's the workspace and the isolation, doing the job they were built for by an agent that has nothing to do with data science.


Why data science was the right place to start

I don't think I'd have built any of this if I'd started somewhere easier, and that's the part I'd want someone else to take from this.

Data science is the maximal case. It needs long multi-step work, which forces session state. It needs artifacts that outlive the conversation, which forces a real workspace instead of a chat log. It needs reproducibility, which forces you to treat the workspace as the source of truth rather than the model's memory. It runs generated code, which forces sandboxing. It touches client data, which forces isolation you can actually defend. It's expensive per run, which forces you to meter and attribute cost early instead of discovering it on an invoice.

Every one of those is a requirement I'd have skipped if I'd started with something conversational. A support bot doesn't force a workspace. A writing assistant doesn't force isolation. You can build either one on nothing and it works fine, right up until it needs to work twice.

Building for the hardest case meant overbuilding for almost every other one. The two memory layers exist because a quarterly analysis demanded them, and now a lease tracker gets them for free.

I'd still call it a data science agent. It just turned out that the data science was the forcing function, not the product.