@kentcdodds: Looser Specs, Better Results: Kent C. Dodds on Thinking in Primitives

X AI KOLs Following News

Summary

Kent C. Dodds argues that defining and maintaining well-designed primitives in codebases allows AI agents to operate more autonomously with looser, higher-level specifications, improving effectiveness in software development.

Looser Specs, Better Results: Kent C. Dodds on Thinking in Primitives https://t.co/7RO21WOyFN
Original Article
View Cached Full Text

Cached at: 08/28/26, 07:46 PM

Looser Specs, Better Results: Kent C. Dodds on Thinking in Primitives https://t.co/7RO21WOyFN


Looser Specs, Better Results: Kent C. Dodds on Thinking in Primitives

TL;DR: To make AI agents more autonomous and effective, focus on building and maintaining a strong set of well-defined “primitives” (reusable, semantic building blocks) within your codebase, which allows you to give them looser, higher-level specifications.

The Problem with Tight Specifications

Kent C. Dodds observes a common issue: developers who lack good primitives often resort to writing long, detailed specifications to constrain AI agents, trying to prevent them from going off track. The solution isn’t a bigger spec, but a better foundation. The core argument is: the more detailed a specification needs to be, the worse your primitives are. A good development environment should allow an agent to focus on the task, not on deciphering a massive rulebook. This is why primitives are so crucial.

What Are Primitives?

Primitives are the smallest semantic unit in your codebase or the tools available to an agent. They are the system’s exposed, named capabilities that are composable and do not require re-implementing internal logic. This doesn’t mean every function in your codebase is a primitive, nor is it just a 400-line description in an agent’s documentation. If an agent needs to reinvent a function, it’s not an available primitive. The majority of an agent’s work should be composing existing primitives, not adding new ones or creating from scratch.

Examples of Primitives

Primitives can span all layers of a tech stack. Kent provides several categories:

  • Application Layer: React itself is a primitive. Upon it, you build component primitives, which combine into more complex components. Routing mechanisms are also primitives.
  • Backend Layer: Data models, authorization patterns, and access control systems are all primitives. Some are built on top of other primitives, while others are standalone.
  • Tool Layer: Tools like Kodi (Kent’s framework for connecting external systems and giving agents autonomy) are primitives. In the initial example, Kodi granted the agent access to Discord, allowing it to act autonomously within that environment.
  • Specific Toolkits: The Google toolset (which removes guesswork about API endpoints), a function library, and the Stripe payments package are all critical primitives for the “Kodi Video” example.

Designing Good Primitives

How do you know if your primitives are well-designed? Kent offers a simple test: Can a junior agent, by composing primitives and given a one-sentence task, produce good results? If it can’t—if it needs to invent new primitives or use workarounds—then primitives are missing, hidden, or building new functionality is easier than using what exists. You should avoid this scenario.

A key metric for evaluating primitive quality is to check, after the agent completes its work, how it used the existing primitives. The more optimized your primitives are, the stronger your “software factory” becomes at producing high-quality software.

Managing the Primitive Lifecycle

Primitives are not built once and left to fossilize. They require continuous evolution: modification, removal, extension, and composition. This requires a product engineering mindset—a deep understanding of the product’s purpose, vision, and data model. Your role as a product engineer is to translate product decisions into code implementation, which includes designing the system and its available primitives.

Introducing New Primitives Cautiously

Introducing new primitives must be a deliberate decision. For instance, Kent considered a new primitive for “code snippets to subscribe to events without packaging them for storage.” He discussed the idea with an AI agent (Grok 4.6) but ultimately postponed it, stating, “I want to think about this design carefully.” Not every potential primitive is worth adopting; you must decide which ones truly benefit the system.

Pruning Redundant Primitives

Equally important is removing redundant primitives—what Kent calls “primitive pruning,” like trimming a garden. He gives the example of planning to remove a value store primitive, replacing it with a package store, memory, and repositories. He instructed the agent to analyze production data before proceeding, as removing a primitive can be difficult and must be data-driven. He recognized this early “value store” had become a junk heap, superseded by better primitives. The agent even proposed a one-month migration plan, a typical approach for deprecating a primitive.

Another example is removing a persistence service primitive because other primitives covered its functionality better, and it wasn’t even serving niche cases well. It’s crucial to consider business sustainability and ask the agent about the cost of related primitives to avoid a “cost denial” trap.

Troubleshooting Agent-Primitive Interactions

Kent identifies three common failure modes when agents interact with primitives:

  1. It can’t find the primitive. The solution is to improve routing documentation, ensuring your agents.md file points to all relevant documentation.
  2. It invents a new primitive instead of using an existing one (e.g., building a new component instead of using a current one). This indicates the primitive is too rigid or hard to discover, and you need to optimize it.
  3. You can’t track which primitives it used. Therefore, pull requests should include a system difference diagram, not just code diffs. Kent covers this in his YouTube series, “Better with Kent.”

Architecture Decision Records (ADRs) are a vital tool to guide primitive usage. They provide direction by explicitly stating: “We won’t do X; we’ll do Y instead, and here’s why.” This helps agents understand why not to take a seemingly obvious path.

The Power of Strong Primitives

With a robust primitive system, you can command agents to perform complex, autonomous tasks. Kent lists several capabilities he can now delegate:

  • Check his inbox and execute operations.
  • Manage his Discord community.
  • Deploy features autonomously.
  • Implement self-healing via Sentry, waking up to find the agent has automatically fixed many issues.

The ultimate test and assignment Kent gives is this: Give an agent a one-sentence task in your actual codebase. Observe whether it effectively composes primitives. If it succeeds, your primitive foundation is on the right track.

Source

Video: @kentcdodds: Looser Specs, Better Results: Kent C. Dodds on Thinking in Primitives

Similar Articles