Aug 10, 202615 min read

Why AI Coding Isn't Enough: Spec Coding & Context Engineering

Every engineering team has a project that seems straightforward during the planning meeting. Ours started exactly that way.

We were building an internal discount approval workflow used by several teams across the company. Sales representatives needed a way to request discounts, managers had to approve or reject those requests based on predefined rules, and the finance system had to receive the final decision automatically. The existing process relied on emails, spreadsheets, and manual verification, so automating it felt like an obvious improvement.

When we broke the work into tasks, nothing looked particularly risky.

The initial scope was clear:

  • Accept discount requests through an internal API.
  • Validate requests against existing business rules.
  • Route approvals to the correct manager.
  • Send the approved request to the finance system.
  • Record every approval for future auditing.

It wasn't a large project, and it certainly wasn't the most technically challenging system our team had built. Like many engineering teams, we decided to use AI to speed up the implementation of the repetitive work. There was no reason not to, AI was already helping us write boilerplate code, generate API endpoints, and scaffold validation logic for other internal services.

The first results were exactly what we hoped for.

Within a short time, we had a working implementation running in our development environment. The API behaved correctly, the validation logic matched the requirements we had discussed, and the workflow passed our initial integration tests. Even our first code review went smoothly because the generated code was clean, readable, and easy to follow.

By the end of the sprint, everyone believed the difficult part of the project was behind us.

Looking back, that assumption turned out to be our biggest mistake.

The first version of the feature wasn't the challenge.

Keeping every future version consistent was.

The Problems Didn't Start with the Code

The first release went into internal testing without any major issues. The workflow behaved exactly as we had designed it, and the feedback from the teams using it was positive. From a technical perspective, we had delivered what the original requirements asked for.

Then the users started asking for changes.

None of the requests were unreasonable. In fact, they were the kind of improvements every successful internal system eventually receives. Different departments had slightly different approval policies, some discount requests needed additional validation, and a few scenarios required exceptions that hadn't existed when we built the first version.

Over the next few weeks, the requirements continued to evolve.

Some of the new requests included:

  • Different approval limits for different business units.
  • Temporary promotional discounts that followed separate rules.
  • Customer-specific exceptions for long-term contracts.
  • Additional approval steps for high-value requests.
  • More detailed audit information for compliance reviews.

On their own, each change was relatively small. The challenge was that different developers started working on different enhancements at the same time.

Like most modern engineering teams, we used AI to help implement those changes. Each developer explained their assigned requirement, generated the code, reviewed it, and committed the update. Every individual implementation looked reasonable because each one solved the problem it had been asked to solve.

The inconsistency only became visible when those changes came together.

The same discount request could be validated differently depending on which workflow processed it. Similar approval rules existed in multiple places, but they weren't implemented exactly the same way. During code reviews, we found ourselves discussing how the application should behave rather than code quality because every implementation reflected a slightly different understanding of the requirements.

The surprising part was that AI wasn't making random decisions.

It was faithfully implementing the information each developer had provided.

For the first time, we realised that the growing complexity of the project wasn't exposing weaknesses in the code.

It was exposing differences in our own understanding of the business.

We Weren't Solving a Coding Problem Anymore

Our first reaction was simple.

We assumed we could solve the inconsistency by writing better prompts. We even explored how Spec Coding vs Vibe Coding approaches differ in maintaining consistency across team projects.

Developers started adding more technical details before asking AI to generate code. Some included examples from existing services, while others copied validation logic from previous implementations. A few even saved their prompts so the rest of the team could reuse them.

For a while, it looked like things were improving.

The generated code became more detailed, and individual implementations looked closer to what we expected. But every time a new business rule appeared, the same pattern repeated itself. Different developers explained the requirement differently, AI interpreted those explanations, and we ended up with another variation of the same business logic.

It became clear that we were treating the symptom instead of the cause.

One afternoon, while reviewing yet another pull request, the discussion stopped being about code entirely. We weren't debating naming conventions, performance, or architecture. We were trying to answer a much simpler question.

"What is the correct business rule?"

That's when the real problem finally became obvious.

"We weren't dealing with a coding problem anymore. We were dealing with a knowledge problem."

If you have questions about this approach, our ASCA FAQ covers many common scenarios and solutions.

The knowledge already existed.

It was just scattered across different places.

Some business rules lived in old Jira tickets. Others were buried in meeting notes or design documents. A surprising number existed only because senior engineers remembered why certain decisions had been made months earlier.

Every developer had access to part of that knowledge.

No one had access to all of it.

AI wasn't creating inconsistent implementations because it lacked programming ability. It was creating inconsistent implementations because each developer was giving it a different version of the project's history.

That realisation completely changed how we looked at AI-assisted development.

Instead of asking ourselves,

"How can we write better prompts?"

We started asking a different question.

"How can we make sure every developer and every AI assistant starts with exactly the same understanding before anyone writes code?"

That question led us in a completely different direction.

We Changed the Way We Started Every Feature

Once we understood that the problem wasn't AI, we stopped looking for better prompts.

Instead, we started asking a different question: How could every developer begin with exactly the same understanding of the feature? If the business rules kept changing depending on who explained them, no AI model could consistently generate the implementation we expected.

Our next sprint looked very different from the previous ones.

Before writing any code, we documented everything we knew about the feature:

  • The business objective.
  • The complete approval workflow.
  • Validation rules that could never change.
  • Known exceptions and edge cases.
  • Expected behaviour for every approval scenario.

Only after the team agreed on that specification did anyone start implementing the feature.

The change was surprisingly simple, but it affected every part of development. Instead of asking AI to interpret evolving requirements, we asked it to implement requirements that had already been discussed, reviewed, and agreed upon. Every developer worked from the same document, so everyone, and every AI assistant started from the same context.

Later, we discovered that this specification-first approach is commonly known as Spec Coding. Instead of treating prompts as the primary source of instructions, Spec Coding treats the specification as the source of truth. AI becomes an implementation partner, while the engineering team remains responsible for defining the problem, documenting business knowledge, and agreeing on how the system should behave. This connects directly to context engineering principles and broader AI software engineering practices.

Around the same time, we came across SAM (Spec Agent Manager), an open-source project that follows the same specification-first philosophy. This approach is a core part of Agentic Engineering. Rather than explaining the entire project here, it's worth exploring the repository yourself to see how specification-driven AI workflows are structured in practice.

👉 SAM (Spec Agent Manager): https://github.com/sam-agents/sam

At that point, our conversations changed completely.

We no longer spent time asking whether AI understood the requirements. We already knew it did, because every implementation started from the same shared specification instead of a different interpretation of the project.

The Difference Became Visible in Everyday Development

The first thing we noticed wasn't faster development.

It was fewer conversations about what the feature was supposed to do.

Before adopting a specification-first approach, code reviews often turned into requirement review sessions. A pull request would begin with implementation feedback, but it usually ended with someone asking whether the business rule itself had been interpreted correctly. Those discussions were valuable, but they were happening too late, after the code had already been written.

That gradually started to change.

Because every developer worked from the same specification, reviews became much more focused on engineering decisions rather than business interpretation.

Instead of debating requirements, reviewers spent their time discussing things like:

  • API design and consistency.
  • Error handling.
  • Performance improvements.
  • Code readability and maintainability.
  • Test coverage for new scenarios.

The discount approval workflow also became much easier to extend.

When users needed another approval rule, we didn't start by opening an AI coding assistant. We updated the specification first. Once the new requirement had been reviewed and agreed upon, implementation became far more predictable because every developer and every AI assistant was working from exactly the same understanding.

The biggest improvement wasn't measured in lines of code or development speed.

It was measured in confidence.

Developers no longer wondered whether they had interpreted a requirement differently from someone else. New team members could understand the feature without relying on tribal knowledge. Even months later, when we revisited the workflow, we weren't trying to remember why a particular decision had been made. The reasoning was already captured in the specification.

Looking back, AI hadn't become more accurate.

Our engineering process had become more disciplined.

That discipline made AI-generated code more consistent, easier to review, and much simpler to maintain as the project continued to evolve.

The Lesson We Carried Forward

When we started building the discount approval workflow, we thought the biggest advantage of AI would be faster development. That assumption didn't last very long.

The project taught us that AI is remarkably good at implementing instructions. What it cannot do is replace the shared understanding that engineering teams build over time. If every developer begins with a different interpretation of the requirements, AI will faithfully generate different implementations for each of them.

Looking back, the turning point wasn't discovering a new AI model or writing more detailed prompts. It was recognising that our business knowledge needed to be documented before implementation began. Once that knowledge became part of a shared specification, AI stopped filling in the gaps and started producing code that aligned with the way our team wanted the system to behave.

That experience changed how we approach every new feature today. We now teach these methodologies in our Founder AI Bootcamp to help teams avoid the same pitfalls.

Before discussing architecture or implementation, we first make sure the problem is clearly understood. The specification becomes the foundation of the conversation, and AI becomes a tool that accelerates implementation rather than a system that interprets requirements on our behalf.

The biggest lesson wasn't about artificial intelligence.

It was about engineering discipline.

Projects become easier to maintain when every developer starts from the same understanding. AI simply amplifies that consistency. When the specification is clear, the generated code becomes more predictable, reviews become more focused, and the software evolves without accumulating unnecessary differences between implementations.

For us, that was the real value of Spec Coding.

Not because it changed how AI writes code.

Because it changed how we, as engineers, build software together.