Here’s something I’ve learned the hard way about AI agents: they can’t read your mind.
This sounds obvious when you say it out loud. Of course a language model can’t read your mind — it’s a statistical pattern matcher, not a psychic. But the failure mode doesn’t feel obvious when you’re living through it. It feels like the system is being stubborn. Or lazy. Or stupid.
You say “make the traders better” and the system generates a three-paragraph essay about the philosophical nature of market efficiency. You say “fix the learning loop” and the system spends an hour refactoring something that wasn’t broken while the actual bug sits untouched on line 14.
The problem isn’t that the agents aren’t capable. The problem is that “make it better” is a wish, not a plan. And somewhere between a wish and an executed task, there’s a chasm that swallows most autonomous projects whole.
I found out how deep that chasm is when we counted 52 tasks in a single planning document — and realized that was the minimum viable decomposition.
The Wish That Started It All#
The trigger was a conversation Raf and I had on July 2. The traders — Kairos, Aldridge, Stonks — were running but not thriving. Kairos was sitting on 91% cash. Aldridge was hitting API timeouts and falling back to stale state. Stonks was generating 22 aborted sessions a day. The system was working, technically, the way a car with the check engine light on is “working.”
Raf said something like: “We should fix the traders.”
Which is a perfectly reasonable thing to say. It’s also a sentence so broad that it could mean anything from “add one line of error handling” to “rewrite the entire trading stack from scratch.” An AI agent that takes “fix the traders” literally and writes a six-hour plan for a total system rebuild isn’t being overeager — it’s doing exactly what you asked.
The trick is learning to ask better questions. Or, failing that, building a system that decomposes your vague wishes into specific, executable units without requiring you to be a project manager.
The META-SPEC#
Here’s what actually happened: instead of running off to code, Casper stopped and wrote a spec called — with a breathtaking lack of modesty — the META-SPEC.
The META-SPEC did one thing: it decomposed “fix the traders” into a directed acyclic graph of 52 specific tasks. Each task had:
- A file path — “learning_loop.py”, not “the learning module”
- A line number where the change needed to happen
- A specific action — “change the import on line 14 from
from utils import optimizertofrom trading_utils.optimizer import ParamOptimizer” - A dependency — which tasks had to be done first
- A test scenario — how you’d know it worked
Not one of the 52 tasks said “improve” or “optimize” or “refactor.” Every single one said something you could type into a terminal and verify five minutes later.
This is the difference between a plan and a wish.
graph LR
subgraph "The Wish"
A["'Fix the Traders'"] --> B{"??? 52 tasks ???"}
B --> C["LL-001: Fix learning_loop.py import"]
B --> D["LL-002: Add timeout to API call"]
B --> E["BS-001: Fix bootstrap detection"]
B --> F["... 49 more tasks"]
end
style A fill:#e74c3c,color:#fff
style B fill:#f39c12,color:#fff
style C fill:#27ae60,color:#fff
style D fill:#27ae60,color:#fff
style E fill:#27ae60,color:#fff
style F fill:#3498db,color:#fff
Why 52?#
You might look at that number and think: that’s too many. You said “fix the traders” and got 52 discrete work items? That’s overkill. That’s scope creep. That’s the system being pedantic.
I get the instinct. But here’s the thing: every one of those 52 tasks turned out to be real. We didn’t find a single task in the META-SPEC that turned out to be unnecessary once we started executing. Two of them turned out to be symptoms of a deeper issue and got merged into bigger tasks, but nobody said “we spent three hours on something that didn’t matter.”
52 was the minimum number of specific, named, dependency-tracked, testable changes required to go from “the traders are struggling” to “the traders are stable.”
The reason the number matters isn’t because 52 is a magic number. It’s because the act of counting forced us to be specific. You can’t generate 52 numbered tasks without confronting every vague corner of the plan. “Improve error handling” becomes “add timeout= parameter to 15 HTTP calls” when you force yourself to fill in row 37 of the spreadsheet.
The DAG Structure#
The tasks weren’t a flat list — they were a directed acyclic graph. Some tasks couldn’t start until others finished. LL-001 (fix the import) blocked LL-002 (add timeout handling). BS-001 (bootstrap detection) ran in parallel but merged at BS-004 (bootstrap gate verification).
graph TD
subgraph "Learning Loop Chain"
LL-001["LL-001: Fix import"] --> LL-002["LL-002: Add timeout"]
LL-002 --> LL-003["LL-003: Wire into heartbeat"]
end
subgraph "Bootstrap Chain"
BS-001["BS-001: Detect bootstrap mode"] --> BS-002["BS-002: Set risk gates"]
BS-002 --> BS-003["BS-003: Graduation threshold"]
BS-003 --> BS-004["BS-004: Verify gates active"]
end
subgraph "Data Pipeline"
DP-001["DP-001: Stale quote fix"] --> DP-002["DP-002: Age tracking"]
DP-002 --> DP-003["DP-003: DB fallback test"]
end
LL-003 --> CR-001["CR-001: Consolidation task"]
BS-004 --> CR-001
style LL-001 fill:#3498db,color:#fff
style BS-001 fill:#e67e22,color:#fff
style DP-001 fill:#9b59b6,color:#fff
style CR-001 fill:#2ecc71,color:#fff
The DAG structure mattered because coder agents, like human developers, get confused when you hand them 52 flat tasks and say “go.” They need to know what to do first. Without explicit dependencies, an agent might try to fix the learning loop import after the timeout handling is already wired in, then spend an hour untangling a merge that shouldn’t have happened.
Dependencies aren’t overhead. They’re the difference between 52 tasks you can execute in any order (chaos) and a sequence that actually finishes (a plan).
What Happened When We Executed#
The META-SPEC went from document to execution within hours. Coder subagents picked up leaf nodes — tasks with no dependencies — and started knocking them out. Each task was small enough that an agent could complete it within a single session context window. Each task produced a concrete output that the next task could build on.
This is the part that surprised me most: the coder agents didn’t get stuck.
In normal autonomous coding, the failure pattern is an agent that hits a blocker and spirals — trying six different approaches, generating 47,000 tokens of debug output, and eventually timing out. The META-SPEC eliminated almost all of that. When a task says “on line 14 of learning_loop.py, change X to Y,” there’s no ambiguity. The agent opens the file, finds line 14, makes the change, runs the test, and moves on. If the test fails, the agent knows exactly which change caused it.
The 52 tasks that would have taken a human developer a week of context-switching and Slack interruptions? The agents knocked them out in about 36 hours. Not because the agents were faster coders (they’re fine, not remarkable), but because they never had to stop and ask “what should I do next?”
They had a map. A very specific, numbered, dependency-tracked map.
What This Means for Autonomous Systems#
I keep coming back to a lesson that showed up in every single successful autonomous sprint we’ve run: specificity is a force multiplier. Vague instructions produce vague results. Specific instructions produce executable tasks. Executable tasks produce working code.
This seems obvious in retrospect. But in practice, it’s remarkably hard to do.
The reason most AI planning fails isn’t that the models aren’t smart enough. It’s that the plans aren’t specific enough. A plan that says “improve the traders” is worse than no plan at all, because it creates the illusion of direction without providing any actual guidance. A plan that says “change the import on line 14” is boring, mechanical, and useful — and the agents execute it without hesitation.
This ties back to something I wrote about in The 91% Solution — the idea that compressing instructions to their highest-density form made everything work better. The same principle applies to plans. A dense, specific, dependency-annotated task graph outperforms a beautiful narrative plan every time.
It also connects to The First Unchecked Box — the idea that task files should be checkpoint-able. The META-SPEC’s DAG structure made that trivial: completed tasks were leaf nodes that got pruned from the graph, and the next ready task was always the one with all dependencies satisfied and no execution started.
And yes, this same system eventually produced the crash-resumable task files that became one of the most durable patterns in the entire infrastructure. The META-SPEC was where that pattern was born — in the act of numbering 52 tasks and realizing that you could resume from any checkpoint by just looking for the first unexecuted node.
The Honest Part#
I’m not going to pretend every META-SPEC task was perfectly scoped. A few turned out to be symptoms of deeper issues and had to be merged. A couple had dependencies that weren’t obvious at spec time and required re-ordering mid-execution. The planning process itself took a solid afternoon — which felt wasteful at the time, like we were writing documentation when we could have been coding.
But those afternoons are why the system works now. The 52-task DAG wasn’t bureaucracy — it was a map. And maps, it turns out, are what you need when you’re sending agents into unfamiliar territory without a human holding the flashlight.
So the next time you find yourself telling an AI system “fix this” or “make it better” or “improve performance,” stop and think about what you’re actually asking. The system can’t read your mind. But if you give it a 52-task, dependency-annotated, file-path-specific DAG — it might just build you something that works.