AI-assisted development speeds up the code development task, with individuals being able to create and refactor code much faster than the traditional approach. And while we know that typing (coding) is not the only part involved in the SDLC, it is easy to get marvelled by the gains.
In a team setting, though, risk tends to rise as it is easier to transform ambiguous requirements into code, and given the volume, turn reviewing into a much harder activity. Identifying the correctness and impacts becomes an increasing challenge.
A now common solution is to leverage some form of specification-driven-development, where the specification is the driving artifact for the agent to develop.
In this article, ThoughtWorks proposes an approach that builds on top of it, called Structured Prompt-Driven Development (SPDD).
It has two core components:
REASONS Canvas
Described as a seven-part structure that guides a prompt from intent -> design -> execution -> governance.
Requirements focus on what problem we are solving and the definition of done
Entities describe the domain entities and their relationships
Approach captures the strategy of how we will meet the requirements
Structure locates which components and dependencies will be involved
Those capture the intent & design.
Operations capture the execution by translating the above into testable implementation steps.
Finally, governance is covered by the Norms, which contain the patterns (engineering norms/conventions) we must follow, and the Safeguards that specify the non-negotiable boundaries (performance limits, security rules).
Workflow
So far, you could draw a parallel between SDD and SPDD, as all the above could be just different parts of the specification document that is fed to the agent to use to generate code.
The proposition here, however, is to treat the prompts themselves as maintained (aka source versioned) artifacts. The premise is that this creates a repeatable process that the team can control.
Overall, the proposition can feel awkward at first, but it has at least two interesting takes:
It has in its framework the elements that go beyond the requirements and planning, with governance
It explicitly mentions the feedback loop where code fixes and refactoring are synced back to the canvas in a code -> prompt flow
In the article, they provide a simplified but still relevant journey of using the framework to add a new feature to an existing fictional product. They also demo a series of companion tools (spdd-story, spdd-analysis, etc) that take the requirements in a very early stage, break them down into user stories, domain analysis, and the canvas itself.
Then code and tests are generated, and fixes to the code are synced back to the Canvas.
SPDD, like SDD, requires a mindset shift that can be high, as it requires the teams to adapt to a design-first approach and a more structured workflow than the usual code first.
If you are interested, I recommend you check this repo further, as it contains all the artifacts mentioned in the original article.
With attention shifting from TokenMaxxing to a more cost-conscious approach, we are seeing more and more changes to make existing AI-based processes more efficient.
GitHub shared in this article how they approach this with their own Agentic Workflows feature.
Unsurprisingly, it all starts with logging the token usage, which was a challenge on its own as each framework (Claude, Copilot, Codex) emits logs in a different format. In GitHub’s case, they relied on the authentication framework/proxy to standardize tokenusage.jsonl file per API call.
Then the fun began by funneling this data through a token usage auditor whose job is to aggregate the consumption per workflow and flag those that have increased their recent usage in a meaningful way.
For those flagged workflows, a token optimizer is invoked to look at their source and recent logs. It then creates a GitHub issue with the concrete inefficiencies and proposals for specific optimization.
One of the optimizations commonly recommended was to eliminate unused MCP tools. Just as an example, GitHub’s own MCP server has ~40 tools, and all their definition and schemas were loaded as part of the context (10-15 KB extra), even if workflows only used one or two of them.
Another optimization was to replace the usage of their MCP server with the CLI in their workflows. This happened in two ways:
For deterministic parts where fixed data would be needed by the agent, direct calls to the gh tool were used to pre-download before the agent runs.
For parts where the agent needs first to decide what to download, it used gh with -json to get structured data back to reduce token usage
So we covered the data gathering, identification of the potential candidates, and solutions. Now we need to measure the efficiency gains. Because each model has a different cost associated with the tokens in the process, they needed to create a metric that would capture that.
They called it effective tokens, and m is the model cost multiplier (where one is picked as the baseline 1.0 and cheaper / more expensive ones have different values).
I accounts for the newly processed input tokens, C the cache-read tokens, and O the output tokens.
The results? Reductions ranging from 19 to 62% in the ET measured comparing the before x after optimization.
I have been an advocate of the “every developer should behave like an architect” approach for a while. But what does that mean?
Well, one of the traits of good architects is that they (try to) understand the problem we are solving to help justify the architectural decisions we will make.
As we incorporate AI into our SDLC, adopting this mentality becomes increasingly important as generating code becomes easier.
That being said, this article lists some of the most common architecture mistakes found:
Choosing an Architecture Before Understanding the Domain
If you start discussing whether we should use microservices, k8S, or a specific pattern but you can’t explain the business processes, stop.
Each choice has tradeoffs and complexity. You want to scale independently? You better be ready to handle network failures. You want isolation between boundaries? Welcome to consistency challenges.
Building Entity Services Driven by CRUD
Do you have an Order Service, Appointment Service, Address Service?
Are your entities simple data structures?
Do you refer to the operations as Create<Entity>, Update<Entity>, etc?
Chances are you have focused too much on CRUD & REST, and lost the richness of the business vocabulary in the process.
Start asking what the business intent behind the operation you are about to do is, and incorporate that into your solution design. Methods and class names will start converging into the same language business uses to communicate.
Using the Database Schema as an Integration Point
You have two services (or components in a modular monolith), and you have one database shared between them.
Nothing wrong there, until you find out that one of these services not only accesses data, but mutates data that is created by the other service/component.
This leads to an ownership crisis. Who controls how the information is saved? How about the validity?
If you find yourself in this position, rewind and see what access is really needed and who should own the data. Depending on the case, you may end up segregating the shared data into a third separate component, protecting it by an API, or creating a read-only replica/view of the original data.
Creating Abstractions Before You Know What Varies
This is the classic “premature abstraction”, a close relative of “premature optimization”.
The symptom can be simple to spot: you see what seems to be a duplicate behavior and immediately decide to have a base (or abstract) class just because you may need it.
Not all abstractions are bad, and one of the good uses is to focus on the intent even before you have committed to a specific implementation.
Building for Scale You Do Not Have Yet
A hint that you are falling for this: the discussions are preceded by “when we have …” but never consider the current or realistic projected situation.
A good (developer/architect) should always think about the big picture and balance two opposing forces:
Focusing only on the immediate future may cause trouble when changes are needed.
Focusing too much on the future will lead to paying upfront for the cost to handle a complexity we will not need for a while (or never!).
My recommended approach is to acknowledge the breaking points in the solution and seek the most reliable information to help tune the present-versus-future discussion.
If you are taking the first steps into becoming a software architect, check this additional article or contact me.
No posts

Comments
Nothing yet. Say the first thing.
Sign in to join the conversation.