Addy Osmani provides a detailed description of spec-driven LLM-based software development in How to write a good spec for AI agents.
This serves as a proposal for a formal programming and specification language designed specifically for LLM-driven software development. Consequently, there is a clear requirement for rigor and structure to minimize ambiguity and ensure the quality of the LLM’s generated responses.
The specification covers all the phases of software development:
- Requirements Engineering: The specification defines the features to be implemented using established formats such as user stories and use cases. This ensures the LLM has a clear functional boundary.
- Software Architecture: The LLM must be explicitly provided with the architectural styles and constraints (e.g., Microservices, Layered, Hexagonal) to ensure the generated components fit the broader system design.
- Software Design: Each task should specify the design patterns to be applied. This includes dedicated tasks for refactoring to ensure the code remains clean and maintainable.
- Software Implementation: Every generation task must define the specific coding standards and style guides to follow, ensuring the output is consistent with the existing codebase.
- Software Testing and Validation: Provide rigorous definitions, like invariants, from which the LLM can generate test cases.
- Project Management: Projects should be decomposed into atomic, concise tasks. This minimizes “context bloat” and keeps the LLM focused on a singular, high-quality goal.
When an LLM is integrated into an existing codebase, the repository itself functions as a de facto specification. The model naturally attempts to mirror the established patterns, architectural styles, and coding practices it encounters. However, if the codebase lacks homogeneity, it serves as a ‘poor specification’—leading the LLM to produce inconsistent or low-quality code that reflects the surrounding technical debt.
Consequently, the rigorous application of LLMs in software development demands a deep mastery of the core concepts, methods, and techniques of the software engineering discipline. Yet, as new dimensions of AI interaction become central to the developer’s role, a fundamental question arises: are these skills unique to software engineering, or are they universal to all LLM-based tasks? By stripping away domain-specific expertise, we can isolate the ‘residual’ elements of the interaction. The following aspects are essential to consider, as they remain entirely software engineering agnostic:
- Context Management: The skill of providing just enough background information for the LLM to understand the goal without “distracting” it with irrelevant data (often called context window optimization).
- Intent Disambiguation: The process of refining a vague human thought into a specific instruction. Whether you are asking for a “secure login” or a “healthy dinner,” the challenge is the same: reducing the gap between what you meant and what you said.
- Iterative Refinement (The Feedback Loop): The “conversation” itself. This is the skill of recognizing when an LLM has strayed off-path and providing the precise “nudge” or correction needed to bring it back.
- Verification of Truth (The Oracle Problem): Because LLMs are probabilistic, the “user” always acts as the final judge. The ability to verify if a response is factually correct or logically sound is a universal requirement.
LLMs are a new tool for software development, and mastering the associated software engineering-agnostic techniques is essential for the modern software engineer.