cd /news/artificial-intelligence/your-ai-agent-isnt-dumb-how-real-ai-… · home topics artificial-intelligence article
[ARTICLE · art-89942] src=pub.towardsai.net ↗ pub= topic=artificial-intelligence verified=true sentiment=· neutral

Your AI Agent Isn’t Dumb. (How Real AI Engineers Work Daily)

Martin Fowler says context is the bottleneck for coding agents, and a developer's experience shows that inconsistent code stems from ambiguous domain vocabulary, not weak models. In an enterprise NL-to-SQL pipeline, the same entity was named 'account' in the schema, 'member' by stakeholders, and 'customer' by product, causing the agent to pick inconsistently. Matt Pocock's five-skill loop addresses this by building a shared language first, which the developer found to be the missing layer.

read11 min views1 publishedAug 10, 2026

“Context is the bottleneck for coding agents now.” — Martin Fowler [1]. I spent most of a year blaming the model instead.

Every time an agent shipped inconsistent code, I reached for a bigger model or a longer prompt. Neither fixed it. The bottleneck was never intelligence. It was vocabulary.

Here is the part that took me too long to accept. My agent wasn’t confused about how to write code. It was confused about what I meant — and no amount of reasoning power fixes a naming problem.

I build production RAG, Graph-RAG, and NL-to-SQL systems. In one enterprise NL-to-SQL pipeline, the same entity had three names: the database schema called it account, the business stakeholders called it member, and the product team called it customer. Same thing. Three words.

The agent picked whichever one appeared last in its context window. So my generated SQL joined accounts, my API layer returned members, and my tests asserted on customer. Every layer was internally correct. The system as a whole was incoherent.

I hit the same wall on a five-agent LangGraph fan-out pipeline. Each agent re-derived the domain terms from scratch, burning tokens explaining to itself what a “run,” a “trace,” and a “materialized node” were — every single session. I was paying, in tokens and in bugs, for a shared language I had never written down.

The retrieval side was worse. In a Graph-RAG system, the quality of the answer depends on whether the agent and the knowledge graph agree on what a node is. When my prompt said “entity,” my graph schema said “node,” and my chunking code said “record,” the agent quietly picked a lane and my retrieval precision fell off a cliff on multi-hop queries. I chased that for two days assuming the embeddings were weak. They weren’t. Three words for one concept were.

That is the moment Matt Pocock’s skills stopped looking like a productivity gimmick and started looking like the missing layer. Not because they made the agent smarter. Because they made me say what I meant, once, in a place the agent would read every time.

TL;DR: Your agent produces inconsistent code because it’s guessing your domain vocabulary, not because the model is weak. Matt Pocock’s five-skill loop works because it builds a shared languagefirst— then grills, specs, slices, ships, and reviews against it. Fix the language, and the other four skills start to compound.

The dominant way people use coding agents is to drop them into a repo and let them figure out the jargon as they go. It feels efficient. It is the single most expensive habit in AI-assisted development.

Think about onboarding a contractor on day one. A strong engineer who doesn’t know your team’s shorthand will still ship something. But they’ll say “the thing that happens when a lesson gets a real spot in the file system” instead of “the materialization cascade” — because nobody handed them the word. They use twenty words where one would do, and every one of those words is a chance to drift.

Agents do exactly this, at scale, every session. And unlike a human contractor, they never build up the shorthand on their own. They reset.

This is not a new problem. Eric Evans named it two decades ago in Domain-Driven Design: teams and the people they build for speak different languages, and software rots in the gap between them. His fix was a ubiquitous language — one agreed vocabulary, used in conversation, in specs, and in the code itself [2]. What’s new is that we now have a second party in every conversation who needs that vocabulary even more than we do.

There’s a subtlety here that trips people up. A single global glossary can flatten meaning. In one bounded context “customer” is a marketing lead; in another it’s a finance debtor [3]. A word is only shared inside its context. Get that wrong and you don’t remove the ambiguity — you standardize on the wrong meaning and make it worse.

So the goal isn’t “write more documentation.” The goal is semantic agreement before implementation begins. Daniel Schleicher, formalizing this for agents, argues that the real leverage in AI development isn’t faster typing — it’s agreeing on what words mean before code exists [3]. That reframed the whole thing for me.

Here is what convinced me this wasn’t theory. When researchers gave coding agents a repository context file, mean output token usage dropped from roughly 5,745 to 4,591 tokens per task — about a 20% reduction — and the agents finished faster [4]. Matt Pocock reports the same effect from his own glossary skill: reading the agent’s reasoning traces, he found a shared vocabulary improved alignment and cut verbosity, an unexpected token-and-cost win [5].

A 20% cut is not a rounding error. On a multi-agent pipeline running dozens of sessions a day, that compounds into real money and real latency. But the number is only the surface. The deeper point is where that language lives in the workflow — because Matt’s five skills are, structurally, five different operations on the same shared language.

His repo — over 200,000 GitHub stars, and the most-installed skills pack for Claude Code [6] — is deliberately not an all-in-one framework. It’s small, composable skills you invoke by name. The famous loop is five of them in sequence. Watch the language move through each one.

**1. ****/grill-me (and **/grill-with-docs) — write the language. Grilling is a relentless interview. The agent models your feature as a design tree and works it in rounds: it asks every question it can answer now, each with its recommended answer, then waits [6]. Before AI we called this rubber-ducking; this version argues back. The upgraded /grill-with-docs does one more thing — it maintains a CONTEXT.md glossary as you talk, challenging vague terms and pinning canonical ones. This is where "the thing that gets materialized" becomes "the materialization cascade" [7]. Matt calls this technique maybe the coolest thing in the repo. He's not wrong.

**2. **/to-spec — spec in the language. The conversation becomes a structured spec: a problem statement, a long list of user stories in the format as an actor, I want a feature, so that a benefit, and the modules you'll touch. Crucially, /to-spec first sketches the test seams and prefers exactly one new seam — the fewer the better [8]. It writes no file paths and no code snippets, because those rot. What it does carry, top to bottom, is your glossary. A spec written in member/account/customer soup produces soup.

**3. **/to-tickets — slice the language. The spec breaks into tracer-bullet tickets: vertical slices that each cut a narrow but complete path through every layer — schema, API, UI, tests — and are demoable on their own [9]. Two constraints matter. Each ticket declares its blocking edges, so the agent works the frontier in dependency order. And each is sized to fit in a single fresh context window. That second rule is quietly the whole game: if a ticket fits one window, the agent never has to page your domain back in mid-task and re-guess your terms.

**4. **/implement — build in the language. This one is short and does a lot. It picks up a ticket, drives test-driven development at the pre-agreed seam, runs type-checks and single test files as it goes, the full suite once at the end, then calls code review before committing [10]. Because the ticket and its acceptance criteria are already in your vocabulary, the code the agent writes — variable names, function names, module names — inherits that vocabulary for free.

**5. **/code-review — enforce the language. The review runs two independent axes as parallel sub-agents so they don't pollute each other: Standards (does it follow the repo's conventions, plus a Martin Fowler code-smell baseline?) and Spec (does it faithfully implement the originating spec?) [11]. Look closely at that smell baseline. The very first smell Fowler lists is Mysterious Name — a function or variable whose name doesn't reveal what it does. A Mysterious Name is a language violation. The final step of the loop is, literally, the language police.

That’s the pattern I missed for a year. The five skills aren’t five unrelated tools. One writes the language, one specs in it, one slices in it, one builds in it, and the last one checks against it. The glossary isn’t a side artifact. It’s the substrate the whole loop runs on.

Here is a trimmed CONTEXT.md from a fulfillment domain, close to the shape /grill-with-docs produces:

## Fulfillment Domain Language**Consignee**: The person or entity receiving a shipment.Identified by delivery address and contact. May differ from the purchaser.*Avoid*: Customer, Buyer, User**Consignment**: The full set of items delivered to one consignee.*Avoid*: Order, Package, Cart

Ten lines. But now every downstream skill has a spine. /to-spec writes user stories about a consignee, not a "user." /to-tickets names a slice create-consignment, not create-order. /implement generates Consignment types. And /code-review flags submitCart() as a Mysterious Name because the glossary already banned "cart" here [3].

Had I written six lines like this for my NL-to-SQL pipeline — one canonical term for the entity, two banned aliases — the schema, the API, and the tests would have agreed on member from the first commit. The bug wasn't in the model. It was in the empty space where the glossary should have been.

There’s a second-order effect I didn’t expect. Once the language is written down, /grill-me gets sharper too. When I grill an agent about a new feature and it already knows consignee is not purchaser, its questions stop being definitional and start being about the actual decision. It asks "should a consignee be able to reassign a consignment mid-transit?" instead of "what do you mean by consignee?" The grilling session gets shorter and the questions get better, because we're no longer negotiating vocabulary — we settled that in the file. Cheap terms up front buy you expensive questions later, and expensive questions are the ones worth an agent's time.

This is also why I stopped treating the glossary as documentation. Documentation is written for humans who can tolerate ambiguity and fill gaps with judgment. A glossary for an agent is closer to a type system — it constrains what the machine is allowed to assume. That reframe changed how I write it: fewer prose paragraphs, more canonical-term-and-banned-aliases, the way you’d write an enum, not a wiki page.

I’d be selling you content marketing if I stopped there. This approach has real edges.

A glossary rots. A stale CONTEXT.md is worse than none, because the agent trusts it completely and will confidently propagate a term you've since abandoned. If you adopt this, /domain-modeling and grilling have to keep the file honest — a dead glossary is a liability, not an asset.

The bounded-context trap is real. One global file that says “customer means X” will actively mislead the module where customer means something else. This works when your vocabulary is genuinely shared across the code it governs. It breaks the moment you flatten two distinct meanings into one canonical term. If you’re there, you need per-context glossaries, not one big file.

The evidence has a ceiling, too. That 20% token study also found the savings concentrated in a few high-cost runs rather than spread evenly, and on some complex tasks the context file barely helped or even hurt [4]. So the honest claim is narrow: a shared language pays off most on codebases with recurring sessions and stable domain terms. For a one-off script you’ll throw away tomorrow, the overhead isn’t worth it — just prompt it directly and move on.

And none of this rescues a bad design. The loop makes an agent consistent with your intent. If your intent is wrong, you’ll get a coherent implementation of the wrong thing, faster. Grilling helps here, but the skills are a communication fix, not a judgment substitute.

Start with the five-minute version. Open your project, think of the three domain terms your agent keeps getting wrong, and write them into a CONTEXT.md with one canonical name and the aliases to avoid. Point your agent at the file. That alone will change the next thing it writes.

If that lands, run /grill-with-docs on your next feature instead of describing it in a paragraph — let the agent interview you and build the glossary as you go.

And when you’re ready for the whole loop, take one real ticket through /grill-me → /to-spec → /to-tickets → /implement → /code-review, and watch the same vocabulary survive from the first question to the final review. The compounding doesn't show up on ticket one. It shows up around ticket five, when the agent stops asking what your words mean — because you finally told it.

Your AI Agent Isn’t Dumb. (How Real AI Engineers Work Daily) was originally published in Towards AI on Medium, where people are continuing the conversation by highlighting and responding to this story.

── more in #artificial-intelligence 4 stories · sorted by recency
── more on @martin fowler 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/your-ai-agent-isnt-d…] indexed:0 read:11min 2026-08-10 ·