Over the last couple of months, like probably many developers, I have been using AI coding agents more and more as part of my daily engineering workflow.
I would say they are great thinking partners… I can explore an architecture, challenge an idea, ask them to inspect an existing codebase and iterate on a design with me. But as the work gets larger, I started noticing a problem that I think many developers are also experiencing. Conversations are useful, but they are not durable engineering artifacts.
A long AI session can contain a lot of valuable context. Architectural decisions, rejected approaches, constraints, assumptions and implementation details can all be somewhere inside that conversation. As the conversation grows, the context also starts getting bloated and can sometimes drift away from the original intent.
This became particularly important in one of the domains I am currently working on.
In my current assignment, I am rearchitecting an authorization layer around Open Policy Agent (OPA) with the goal of moving authorization decisions away from individual delivery teams into a centralized Policy as Code model.
This is not a small isolated feature. It is a high blast radius capability that will eventually sit in front of authorization decisions coming from multiple applications and delivery teams. So I was not very comfortable with important architectural intent living mostly inside AI conversations.
That was one of the main reasons I decided to onboard Spec-Driven Development (SDD) into the workflow, using OpenSpec.
After using it for a while, I realized that the biggest benefit for me was not that AI started writing better code. It was that the engineering process became much more structured and durable.
I’m not going to cover how to set up SDD or what SDD is. I happened to choose OpenSpec, but there are other approaches such as GitHub Spec Kit, and plenty of resources already explain how to get started. Instead, I want to share how I embedded SDD into my actual engineering workflow, what changed for me, and where I started feeling some friction.
The workflow I gradually got used to is quite simple. I normally start with OpenSpec’s explore mode. At this stage I don’t necessarily know the final solution yet. I use the agent as a thinking partner. We inspect the existing architecture, discuss boundaries, challenge assumptions, look at alternatives and gradually shape the solution.
In other words, I still want the conversation. The difference is what happens afterwards.
Once the direction becomes clear, I use OpenSpec’s commands to move the work into a proposal and OpenSpec starts producing structured artifacts around it: the proposal, the design, specifications and the tasks required to implement it.
So instead of this: Conversation -> Code the workflow starts looking more like: Explore -> Proposal -> Design -> Specification -> Tasks -> Implementation -> Verification -> Archive
This keeps the workflow structured, but more importantly, it prevents important context and decisions from getting lost inside conversation history.
Side note: Another side effect I started noticing is context efficiency. Instead of carrying large conversations forward or repeatedly explaining the same decisions, the agent can work against much more focused specifications and tasks. I haven’t properly measured the token savings yet, so I wouldn’t claim SDD necessarily makes AI cheaper, but it does seem to reduce the amount of unnecessary context we keep carrying around.
One thing I particularly like about this approach is that the specification is not only useful for the AI agent. It also gives us something concrete to align on as engineers.
Before implementation starts, we can look at the proposal and design files together, challenge the decisions and make sure we agree on what we are actually building. This is much easier than trying to explain the outcome of a long AI conversation or reviewing a large amount of generated code after the fact.
Once agreed, those artifacts become the structured context the agent implements against, while the resulting specifications eventually become the durable source of truth.
I still keep durable repository level context and guardrails in AGENTS.md: architecture boundaries, ownership rules, coding conventions and build/test requirements. OpenSpec then adds the change specific context on top of that.
Its tasks.md also gives every change a focused implementation and verification checklist. So the agent is not simply asked to “implement authorization”. It works through smaller tasks and has explicit things to verify before the change is considered complete.
tasks.md
## Policy Evaluation
- [x] Add decision context mapping based on user claims from the JWT token
- [x] Evaluate global policy definitions before delivery team policies
- [x] Evaluate delivery team policies against the resolved authorization context
- [x] Return a deterministic allow/deny decision
## Verification
- [x] Verify global policies are always evaluated first
- [x] Verify delivery team policies cannot override global restrictions
- [x] Test allow and deny scenarios with different JWT claims
- [x] Verify the evaluation fails closed when required context is missing There was another benefit I didn’t really plan for when I started using SDD.
The authorization platform I am building eventually needs to be consumed by delivery teams. Those teams will own domain specific Rego policies, but we don’t want every developer to first become an OPA expert before they can onboard their application.
So I have also been working on reusable agent skills that can inspect a delivery team’s repository, understand its authorization requirements and help generate and test the required Rego policies. And this is where the durable specifications became useful again.
Instead of teaching those agents the authorization architecture from scratch, the accepted specifications became part of their reference context. In that sense, SDD also became part of how I approach context engineering. Keeping important engineering knowledge structured, durable and reusable across different agents and workflows.
For me this is where SDD becomes more interesting than simply generating better documentation. The specifications start becoming an interface between humans, coding agents and other engineering workflows.
Of course, I don’t think every change needs this. SDD introduces some upfront overhead. If I need to make a tiny and obvious change, going through proposal, specification, tasks and archive can quickly feel like ceremony :) Good engineering judgement still matters here.
For me, the question is becoming less about “Should we use SDD everywhere?” and more about “Does the intent behind this change need to survive the conversation?“.
The more I work this way, the more I think the interesting shift with AI assisted software engineering is not simply that AI can write more code.
We are gradually spending more time defining the system around the code. The architecture, intent, context, constraints, specifications and verification criteria. So the agent can then iterate against those boundaries and produce the implementation.
There is already a lot of discussion around this, but maybe the developer’s main output is slowly changing from only writing code to really designing a system that can reliably produce the right code.
In my previous article, I tried to show how we can build a simple but practical AI…
Nowadays wherever I look, everyone talks about AI coding agents, agentic systems or LLM powered…
In the first two parts of this DevEx series, I tried to show how golden…
In the first part of this DevEx series, I tried to explain Platform Engineering and…
As an architect involved in platform engineering and DevEx transformation within a large-scale organization for…
{:en}In today’s technological age, we typically build our application solutions on event-driven architecture in order…