Building the foundation for AI-native software engineering.

Your AI Doesn't Know Your Codebase

After spending a considerable amount of time working with AI in software development, I've noticed a recurring problem. AI is incredibly capable of writing code, but it often struggles to understand how an organization actually builds software.

It might know TypeScript, React, PostgreSQL, and countless architectural patterns, but it doesn't know why your team made a particular architectural decision six months ago. It doesn't understand which parts of your system are fragile, which business rules are critical, or why certain conventions exist.

Sometimes it doesn't even read the files it should have read before making changes.

As developers, we compensate by providing context, explaining architectural decisions, and correcting assumptions. Unfortunately, we often end up repeating this process across different conversations, tasks, and team members.

This raises an important question: why are we spending so much time teaching AI things our organization already knows?

Context Is Infrastructure

Most developers interact with AI through conversations. We describe a task, provide some context, review the result, and correct whatever the model misunderstood. This works reasonably well for individual tasks, but becomes increasingly inefficient when applied across an engineering organization.

Two developers using the same AI model can get significantly different results simply because they provided different context. One might get an implementation that follows the existing architecture, while another receives something that technically works but introduces entirely new patterns.

The problem isn't necessarily the model. It's the environment in which the model operates.

I believe we should start treating context as engineering infrastructure. Something that is deliberately designed, documented, versioned, and maintained rather than manually recreated in every conversation.

This doesn't mean feeding every document and source file into an enormous context window. It means organizing knowledge so that AI can find the right information when it needs it.

1. Make Your Architecture Understandable

One of the first things we've realized is that having access to the codebase isn't enough. AI can explore source code, but understanding a complex system requires more than reading individual implementations.

Consider authentication, for example. An agent might successfully identify the authentication middleware and understand how a request is validated. But that doesn't necessarily explain why certain endpoints require additional authorization, how permissions relate to business rules, or which architectural constraints should apply to new implementations.

We need documentation that captures this knowledge explicitly.

Not enormous documents describing every detail of the application, but focused Markdown files explaining important architectural decisions, business concepts, and established conventions.

For example:

docs/ ├── architecture.md ├── authentication.md ├── domain.md ├── integrations.md └── testing.md 

These documents should explain responsibilities, boundaries, important decisions, and common pitfalls. They should also be maintained alongside the code, preferably as part of the normal development process.

The purpose isn't to prevent AI from exploring the codebase. It's to give it a reliable starting point and reduce the amount of unnecessary exploration required for every task.

Source code describes how a system is implemented. Good documentation provides the context needed to understand why it was implemented that way.

2. Turn Repeated Instructions Into Skills

Another problem becomes obvious when AI is used regularly across a team: developers repeatedly provide similar instructions.

How should an API endpoint be implemented? Which architectural conventions apply? How do we write integration tests? What should happen when an external service fails?

These are questions that an engineering team has often already answered.

We've invested quite heavily in shared AI instructions and specialized skills, including maintaining a separate repository for them. The idea is to make our engineering knowledge reusable rather than depending on individual developers remembering which instructions to include.

A skill can describe how to approach a particular type of task, which documentation to consult, which tools to use, and how to verify the result.

For example, a skill for implementing an API endpoint might instruct an agent to inspect existing routes, follow established patterns, use the appropriate validation utilities, and run relevant tests before considering the task complete.

The important part is that this knowledge becomes shared and maintainable.

When we discover a better approach, we update the skill. When architectural conventions change, we update the relevant instructions.

This is much more sustainable than having different developers maintain their own collections of prompts that gradually become inconsistent.

3. Give AI Tools, Not Just Instructions

Instructions and documentation provide knowledge, but an effective harness also needs capabilities.

There's a significant difference between explaining how to perform a task and providing the tools necessary to perform it.

Consider an agent implementing a ticket from a project-management system. Without an integration, a developer might need to copy the requirements into the conversation, locate relevant documentation, and manually supply additional context.

With the right tools, the agent could retrieve the ticket through an API, identify relevant documentation, load the appropriate skills, and inspect the affected parts of the codebase.

It could then implement the changes, run tests, and collect the results for review.

This doesn't necessarily require a complicated agent framework. In many cases, a well-designed script with a predictable interface is sufficient. The important thing is that the agent has access to reliable, reusable capabilities rather than depending on manual interaction.

We're currently taking this idea further by developing our own internal AI harness application. It's still under development, but the ambition is to bring shared knowledge, specialized capabilities, and engineering workflows together into a consistent environment.

The long-term goal is to reduce the amount of manual coordination required from developers while maintaining control over how work is performed.

4. Build Security and Compliance Into the Architecture

An AI harness also introduces responsibilities that go beyond developer productivity.

In our case, working in an environment with GDPR requirements means we need to think carefully about which information agents can access, how that information is processed, and which external services are involved.

An agent capable of retrieving documentation or interacting with internal systems should not automatically have unrestricted access to everything.

We need to consider authentication, authorization, data minimization, access boundaries, auditability, and appropriate human approval mechanisms.

For example, an agent working on an integration might need access to technical API documentation and test fixtures, but should not require access to real patient information or production credentials.

These concerns shouldn't be handled exclusively through instructions telling the model to behave responsibly. They need to be enforced through the tools and infrastructure surrounding it.

As we give agents more autonomy, the quality of these controls becomes increasingly important. The objective is to enable useful automation without compromising the security and privacy requirements of the organization.

5. Treat the Harness as an Internal Product

One of the most important lessons I've taken from this work is that an AI harness shouldn't be treated as a collection of configuration files that someone creates once and forgets.

It's an internal engineering product that requires ownership, maintenance, and continuous improvement.

When an agent repeatedly makes the same mistake, we should investigate why. Perhaps documentation is missing, an instruction is ambiguous, or a tool doesn't provide enough information. Sometimes the solution is a better test or an additional validation step.

Rather than correcting the same problem in individual conversations, we can improve the shared environment.

Over time, those improvements benefit everyone using the system.

This also creates an opportunity to evaluate how effective our AI workflows actually are. Are agents following architectural conventions? How often do implementations require manual corrections? Which tasks consistently fail? Where are developers still spending time providing missing context?

Answering these questions gives us a way to improve the harness based on evidence rather than assumptions.

Building the Foundation for Software Factories

In my previous article, Stop Writing Software. Start Building Software Factories, I explored the idea that software engineering is moving toward environments where specialized AI agents handle increasingly large parts of the development process.

I believe building a reliable AI harness is one of the most important steps toward that future.

Before we can expect multiple agents to collaborate autonomously, we need to give them a shared understanding of our systems, reliable tools, clear responsibilities, and mechanisms for verifying their work.

Some of these capabilities are already practical today. Others, particularly more autonomous workflows, still require experimentation and careful engineering.

We don't need to wait for the next generation of AI models to begin. We can improve our documentation, introduce reusable skills, connect existing tools, and establish appropriate security boundaries with the technology we already have.

As these foundations mature, we can gradually automate more of the development process without losing visibility or control.

I believe the future of AI-powered software engineering will depend not only on increasingly capable models, but also on the quality of the environments we build around them.

And for engineering teams, that's something we can start working on today.