DSLs and agents: constraining the domain to increase reliability
Martin Fowler published a lengthy piece proposing a contrarian thesis: AI agents perform better when operating within a Domain-Specific Language (DSL) than when you ask them anything in natural language. A narrow domain isn’t a constraint—it’s a guide: the agent makes fewer mistakes because the possible vocabulary is smaller and more precise.
The article starts from the impossibility of complete upfront specification and arrives at a practical observation: those using Claude Code or Codex on well-structured codebases get more reliable results than those asking it to build from scratch without constraints. The piece documents two concrete examples: a system for generating feature-rich PowerPoint presentations with diagrams and Tickloom, a DSL for illustrating distributed system behavior. In both cases, the model learns the domain language and uses it as a natural interface, producing more verifiable output.
Why it matters to you: if you’re designing an agent for a repeated task in your field, constraining the language rather than leaving it open can be the difference between a reliable tool and a surprise generator. The idea also runs through the lesson on your first useful agent: stated objectives and limits aren’t bureaucracy—they’re your agent’s implicit DSL.
In detail
The missing context.
AI agents emerged with the idea of working on open natural language: ask for what you want, and the model decides the steps. Fowler flips the perspective: natural language is too broad for a specific domain. When you design an agent for a repeated task—generating architectural diagrams, testing distributed scenarios, producing structured reports—you have a limited vocabulary of operations and entities. Making that vocabulary explicit in a DSL (even a very simple one) gives the agent a more precise and verifiable interface.
The article develops the argument through two cases:
-
Feature-rich PowerPoint presentations. A semantic model of slides (title, bullets, diagram, notes) becomes the DSL. The user describes what they want to communicate in natural language, the LLM generates the DSL, a second step transforms it into PowerPoint. The point: separate semantic generation (controllable) from final rendering (mechanical).
-
Tickloom: a DSL for distributed systems. Fowler and his team built a minimal language for describing interactions between nodes in a distributed system (messages, failures, retries). The LLM reads textual descriptions of scenarios and generates Tickloom, which then produces the diagram. The DSL serves as a contract: if the output doesn’t compile, the error is immediately recognizable.
The central thesis is that the DSL becomes the source of truth: the verifiable output isn’t the text generated by the LLM, but the DSL code the LLM produced. A well-made DSL is easier to parse, test, and correct than prose output.
Convergence with Claude Code and Codex.
The idea resonates with those using coding agents in production. Claude Code and Codex work better on codebases with clear abstractions and consistent conventions—effectively, an implicit DSL. When structure is weak, the agent generates code that compiles but doesn’t integrate, or makes wrong assumptions about boundaries.
Fowler cites Domain-Driven Design and Ubiquitous Language: building a shared conceptual model has always been the way to grow complex software. The LLM accelerates the process, but doesn’t replace it: the LLM helps discover the right vocabulary, then uses it.
The gaps and what remains open.
The article doesn’t address two practical problems:
- Who writes the DSL? Fowler describes the iterative process (the LLM as brainstorming partner), but doesn’t say how long it takes to reach a stable DSL. If the domain changes often, the DSL becomes a second codebase to maintain.
- When the DSL isn’t enough. There are tasks where the vocabulary is genuinely open (creative writing, idea exploration). Fowler doesn’t discuss when natural language is the right choice.
The Hacker News discussion (121 points, 80 comments) confirms the idea resonates with those building agents: many report that constraining the domain reduces errors and simplifies debugging. Others raise the opposite concern: building a DSL only makes sense if the task is truly repeated, otherwise the design cost exceeds the benefit.
Implications for those designing agents.
If you’re building an agent that solves the same type of problem many times, consider explicitly defining the vocabulary of operations and entities instead of letting it emerge from the prompt. You don’t need a formal language: even a JSON schema or a list of recognized commands is a DSL.
The method connects to two tools on the site:
- The lesson on your first useful agent insists on stated objectives and limits: that implicit contract is already a minimal DSL.
- The playbook for writing executable specifications proposes defining acceptance criteria before generating: there too, you’re constraining the domain to get verifiable output.
Fowler closes with an observation worth applying to all agent work: the DSL is where design and generation meet. The LLM accelerates, but design—deciding what matters and what doesn’t—remains your responsibility.