Your Agent Has More Than 12 Blind Spots

AIagenticsoftware engineeringClaude Code

Nate Jones published a video and companion Substack post this week analyzing the Claude Code source leak. While everyone else was cataloguing the Tamagotchi easter egg and counting feature flags, Nate did the more useful thing: he mapped the infrastructure underneath the features and extracted 12 design primitives that determine whether an agentic system actually works in production.

His core thesis is exactly right. The LLM call is maybe 20% of a production agent. The other 80% is plumbing: session persistence, permission pipelines, context budget management, tool registries, security stacks, error recovery. The boring stuff that separates a demo from a system millions of people depend on. If you haven’t watched the video, go watch it. The 12 primitives he identifies are solid, and the tiered prioritization (day-one non-negotiables vs. operational maturity) reflects real implementation sequencing.

I distilled Nate’s analysis into an implementation-ready reference that integrates his 12 primitives with six additional areas where the analysis stops short. These aren’t nitpicks. They’re the places where production agents actually break.

Memory is harder than compaction

Nate’s tenth primitive, transcript compaction, addresses a real problem: conversation history is token-expensive, so you need to truncate it intelligently. Keep recent entries, preserve the original instruction, discard the rest. It’s necessary, yes, but not sufficient.

Compaction answers the question “how do I fit a long conversation into a finite context window.” It doesn’t answer the harder question: “how does the agent recall relevant information from three days ago when it’s working on a related task today?”

Claude Code’s approach works for session-scoped tasks because coding sessions have a natural boundary. You open a session, do the work, close it. But agents that persist across sessions, or across days and weeks of work, need an explicit memory layer. What to remember, how to index it, when to surface it. This is retrieval of relevant prior context, not truncation of old context. It’s a fundamentally different problem.

Jannes Klaas, in his independent analysis of Claude Code’s architecture via API proxy inspection, noted the same gap: Claude Code doesn’t have a sophisticated memory system and doesn’t use any databases to represent knowledge. That’s fine for a coding agent with session boundaries. It’s a structural limitation for any agent that needs to learn from its own history.

The practical implication: if you’re building an agent that operates across sessions, memory architecture is a day-one primitive, not an afterthought you bolt on after compaction.

Error recovery needs actual semantics

Nate flags that you need to know whether an operation is safe to retry. He calls this idempotency awareness and includes it in his workflow state primitive. That’s the right instinct. But he doesn’t go deep on how to classify idempotency or what to do when an operation isn’t idempotent.

In production agents, the difference between these three recovery strategies is where most operational failures live:

Retry the whole step. The operation had no side effects, or its side effects are idempotent (writing the same file twice produces the same result). Safe to re-run.

Roll back the side effect and retry. The operation partially completed. It wrote to a database, sent an API call, modified a file, and the partial result is inconsistent. You need compensating actions before you can retry.

Skip and continue. The operation failed in a way that doesn’t block downstream work. Log it, flag it for human review, move on.

Claude Code’s security architecture is sophisticated. Nate correctly highlights the 18-module stack for the bash tool alone. But security and error recovery are different problems. Security asks “should this action be allowed.” Error recovery asks “this allowed action failed halfway through, now what.” The second question requires understanding the side-effect profile of every tool, and that understanding needs to be encoded in the tool registry metadata, not discovered at runtime.

Human handoff is a distinct primitive

Nate’s permission system covers approval gates: the agent asks the human before doing something risky. That’s important. But there’s a broader design question that permissions don’t cover: when should the agent stop and explicitly hand control back to the human?

Not because it needs permission. Because it needs judgment.

Consider an agent that’s implementing a feature and encounters an ambiguous requirement in the spec. It could guess and continue. It could pick the most common interpretation. Or it could say “I’ve reached a decision point that requires your input. Here’s what I see, here are the options, what do you want?” That third behavior isn’t a permission check. It’s an escalation protocol, and it requires the agent to have calibrated confidence about its own uncertainty.

This connects directly to the alignment questions I explored in my analysis of Zach Lloyd’s Spec & Verify framework. The places where human judgment matters most are precisely the places where it’s most tempting to let the agent decide on its own. A formal handoff protocol, distinct from permissions, makes the boundary explicit rather than hoping the model figures it out.

Jannes’ proxy analysis shows how Claude Code handles this in practice: the agent simply outputs text without calling a tool, which stops the agentic loop and waits for user input. That’s elegant for an interactive coding session. But for agents running in background processes, scheduled tasks, or multi-step workflows, “stop and wait” needs a richer vocabulary: escalate to a human, escalate with a deadline, continue with a provisional decision and flag for review, or halt entirely.

Observability is more than logging

Nate’s seventh primitive is system event logging, a structured log of what the agent did, not just what it said. That’s necessary. But logging is the foundation of an observability stack, not the stack itself.

In practice, you also need trace visualization across multi-step runs (not just individual events), cost attribution showing which steps consumed what tokens and wall-clock time, performance profiling identifying which tool calls are slow, and anomaly detection flagging runs that deviate from expected patterns.

This is the ops layer that sits on top of logging, and it matters because agentic systems fail in ways that are hard to debug from logs alone. An agent that takes 47 steps to do something that usually takes 12 isn’t producing errors. It’s not violating permissions. The logs look fine. But something is wrong, and you need pattern-level visibility to see it.

Nate’s streaming events primitive (number 6) helps with real-time visibility, but observability for agentic systems is fundamentally a post-hoc analysis problem. You need to understand what happened after the run, across runs, over time.

Testing non-deterministic systems is an unsolved primitive

Nate’s two-level verification (verify agent work, then verify harness changes) is a good start. But it frames testing as a quality gate applied to individual runs and to infrastructure changes. The harder challenge is regression testing for systems whose behavior varies with each run.

How do you write a test for an agent that should “fix the failing tests in this repo”? The agent might take different paths each time. It might fix different tests in different orders. It might use different tools. The outcome should be consistent (all tests pass), but the process won’t be. Traditional test frameworks assume deterministic behavior. Agentic systems need evaluation frameworks with fuzzy matching, statistical pass/fail criteria, and golden-path tests that check behavioral properties rather than exact execution traces.

This is an emerging area with no settled best practices, which is exactly why it deserves to be called out as a primitive. If your agent system doesn’t have a testing story beyond “run it and see if the output looks right,” you’re operating on hope.

Inter-agent communication needs a contract

Nate’s twelfth primitive, typed agent roles, constrains what each agent can do. An explore agent can’t edit files. A plan agent can’t execute code. That’s the right idea. But in multi-agent systems, the communication contract between agents matters as much as their individual constraints.

What format do agents use to hand off work? How do they share context? How does the orchestrator know whether an agent is stuck or still working? What happens when one agent’s output doesn’t match the format the next agent expects?

Jannes’ analysis shows Claude Code’s sub-agent dispatch in action: the main agent uses a Task tool with a description and prompt, and the sub-agent receives that prompt as a user message. The sub-agent doesn’t even know it’s a sub-agent. It gets the same system prompt as the main agent. That simplicity is a feature for Claude Code’s use case, where sub-agents handle bounded, well-defined tasks. But for systems with specialized agents that need to collaborate on open-ended problems, you need explicit protocols for context sharing, progress reporting, and failure signaling.

These are distinct from permissions. Permissions govern what an agent can do. Communication protocols govern how agents coordinate what they do.

The meta-point stands

None of this diminishes Nate’s core contribution. His 12 primitives are the right foundation, and his framing, that building agents is 80% non-glamorous plumbing and 20% AI, is the most important thing anyone has said about agentic systems this year. The meta-principle that this is fundamentally back-end engineering applied to a new domain is exactly right.

The six gaps I’ve identified are the next layer down. They’re the places where “I built an agent that works” becomes “I built an agent that works in production, recovers from failures, coordinates with other agents, and doesn’t silently drift.” If Nate’s 12 primitives are the plumbing, these six are the joints, valves, and pressure gauges.

The full implementation reference is available as a companion document. It integrates Nate’s 12 primitives with the six additions discussed here into a single prioritized checklist, formatted for use as project knowledge or a system prompt when building new agents.


If you want to discuss: [email protected], BlueSky @tsondo.com, or via the about page.