AI-Friendly Architecture: How to Keep AI Coding Agents Under Control in a Project

15.09.2026

Christoph Bergen

Christoph Bergen

Team Leader, CoE GenAI

Robert Bauer

Robert Bauer

Senior Data Scientist

An AI agent is supposed to implement a new feature. But it spends a long time searching through the codebase or rewriting functions that already exist. Why does this happen, and what can be done about it?

Christoph Bergen and Robert Bauer explain how to identify architectural problems and which processes can help with further development. They also discuss how the harness—that is, the agent’s working environment—can be improved based on completed tasks.

 

What makes architecture AI-friendly?

An AI-friendly architecture helps coding agents find existing functions and implement and test changes—as much as possible—within the affected module. Well-defined development processes help maintain these characteristics: changes are reconciled with the architecture, documentation is updated as needed, and required checks are performed automatically. The “Advanced Harness” approach also involves evaluating completed tasks and refining the agent’s instructions, skills, and workflows based on these experiences.

The interview has been edited for length and organized by topic.

Interview

1. Recognizing When an Architecture Is Not AI-Friendly

Christoph: Robert, in practice, how can you tell that an architecture isn’t AI-friendly?

Robert: I notice it most clearly when I give the agent the next feature and it can no longer find its way around the system. It spends a long time searching the codebase, doesn’t know which subsystem to work in, or implements functions that already exist elsewhere. Eventually, the same logic ends up duplicated throughout the system. Then it’s no longer possible to make changes centrally.

Development might continue, but every new task becomes more tedious. For me, that’s a pretty clear warning sign.

Christoph: Does that depend on whether humans or AI wrote the code?

Robert: It can happen with both. While on vacation, I continued working on some older personal projects and deliberately tested how far I could get by simply assigning tasks to the agent and barely looking at the code myself. After three or four days, I reached this point: The next feature couldn’t be implemented as easily as it had been at the beginning.

I was also using more affordable models at the time. Still, I was surprised at how quickly duplicates and clutter had accumulated. For me, that was a good reminder of how important the agent’s structure and guidance are.

Christoph: What helps the agent get up to speed faster?

Robert: They need a clear description of the architecture. What subsystems are there? What are their responsibilities? What dependencies exist between them? And why did we make certain architectural decisions?

Let’s take a new front-end feature as an example. The agent should be able to quickly identify where it belongs, how that area is structured, and how it connects to the back end. Of course, they can figure out a lot from the code as well. But that takes time and context every single time.

In practice, we usually solve this by automatically providing the agent with references to the descriptions of the architectural building blocks. The agent checks there at the start of a task and gets a brief overview of the system. This allows them to find the relevant folders and components quite quickly for routine tasks. Getting started is then pretty easy.

Christoph: We talk a lot about documentation. What does that mean for the structure of the software itself?

Robert: Modules that are as clearly defined as possible help enormously. Ideally, an agent can work on a task using just two or three files as context. Then they don’t need to know much about the rest of the system, and the change can be tested within that scope.

This requires clear interfaces: What goes into a module, what comes out, and what conditions must apply? Such boundaries make the work manageable. Of course, not every change can be isolated so neatly. But where possible, I would work toward that goal.

Read more: The article “Token Efficiency in AI Coding Assistants: 10 Strategies for Reducing Costs and Context” delves into how unnecessary searching and overloaded context can be reduced in coding workflows. (HMS Analytical Software)

 

Processes That Preserve Architecture in Everyday Life

Christoph: Let's assume the modules are structured logically and the architecture is documented. How do we maintain this state as we continue to develop the system?

Robert: For that, we need a fixed process. We have to define how a new feature is created and how we fix a bug. Otherwise, we’ll have to explain to the developer all over again what they’re supposed to do for every single task.

Whether a team uses Spec-Driven Development, Test-Driven Development, or variations of these is, to me, of secondary importance at first. What’s important is that certain steps are carried out reliably. A codebase can also lose its “AI-friendly” nature over time. If we clean it up once and then continue working without a structure, we’ll eventually face the same problems again.

Christoph: How much process does this require? That quickly sounds like extra work for every small change.

Robert: It can remain manageable. As a minimal approach, I’d recommend four steps: First, we align the task with the architecture and clarify where the change belongs. Then we document a brief plan outlining the necessary changes. Next comes the implementation. Finally, we verify whether it was actually integrated into the architecture as intended.

This final step also includes verifying the documentation. If something has been added or if we’ve made a deliberate exception, it needs to be noted there. That way, the description remains useful for the next task.

The process needs a clear starting point. For a feature, I initiate the designated workflow; for a bug fix, I use the corresponding one. To start with, this can simply be a prepared prompt. The key is that I initiate this workflow intentionally.

Christoph: How binding are such guidelines when the agent has to follow them itself?

Robert: It’s worth making a precise distinction here. If I write in a prompt, “Please run check XYZ after coding,” that’s primarily an instruction. I rely on the agent to remember it and implement it correctly.

In a pipeline, I can make the check mandatory. It runs automatically, and if an error occurs, the process won’t proceed beyond that point. The agent must resolve the issue. Especially with checks like these, I want to rely as little as possible on whether the agent initiates them on its own.

These technically enforced rules help ensure that the development process is actually followed.

Christoph: What else should a reviewer pay attention to?

Robert: How the change fits into the overall system. A function might look good on its own. But I can only tell whether it’s in the right module or whether it’s reimplementing something we already have elsewhere if I understand the architecture.

It’s precisely this kind of review that requires attention. I need to understand how the affected parts are connected. A glance at the changed lines of code often doesn’t answer these questions.

Background: The article “Harness Engineering: How AI Coding Agents Become Controllable in a Project Context” describes the working environment surrounding a coding agent and the interplay of instructions, tools, checks, and feedback.

Advanced Harness: Applying Experience to Future Tasks

Christoph: During our preliminary discussion, you mentioned a third point—“Advanced Harness”—and that takes things a step further. What do you mean by “Advanced Harness”?

Robert: I’m particularly interested in the system’s ability to reflect on itself. We’ve defined a work process with instructions, skills, and checks. Now there should be a step that examines whether this process is still appropriate and where we need to improve it.

That’s different from checking whether the architecture documentation is still accurate. There, we’re just making sure the code and documentation match. With self-reflection, we look at how the agent operates: Are its skills up to date? Do the instructions still match the libraries being used? Are there any rules missing that we’ve had to repeatedly point out to it in the past?

One example would be a library whose usage has changed. The agent encounters a warning and figures out how to handle it while working on the task. This insight should then be incorporated into the relevant skill. Otherwise, the agent will encounter the same error the next time.

Another example would be new style guidelines that we’ve defined. If, after a few weeks, I have to explain again where they are and that they need to be followed, then we haven’t properly incorporated the lessons learned from the previous task.

Christoph: So that would be an outer loop in the context of loop engineering?

Robert: Exactly. The inner loop tackles a specific task and corrects the result based on feedback. The outer loop examines the way we work across multiple tasks.

Self-correction and self-optimization thus pertain to two different levels. In one case, we improve the current change. In the other, we adjust the skills, instructions, or processes used to create future changes.

Christoph: How do you approach this in practice today?

Robert: My approach so far is pretty simple, and I don’t apply it consistently everywhere yet. By the end of a task, there’s already a lot of context in the chat: which skills were loaded, which steps the agent executed, and where I had to correct it.

I have another skill review that data. It’s supposed to write a brief retrospective: What worked? Where were there difficulties? Did any tool calls fail? Did script calls from the instructions not work?

This summary is stored separately. If such retrospectives are generated regularly, you can build an overarching reflection loop on top of them. We then have concrete insights from the runs that can be used to improve the workflow. That’s the direction I’d like to continue in.

Read more: “Loop Engineering: How to Create Reliable AI Coding Agents” explains the various feedback loops and distinguishes, among other things, between checking individual results and improving the system over multiple runs.

Selection of Additional Tools and Skills

Christoph: What role does the selection of additional tools and skills play in this?

Robert: They should be tailored to the project. This can include support tools, MCP servers, or curated information about the libraries being used.

However, I’m not a fan of massive skill collections. For a library, I prefer a compact core skill that contains the most important information and refers to more detailed documentation that’s easy for agents to read. Then the agent can look it up if needed. After all, we also have to maintain and keep a large number of individual skills up to date.

Christoph: To what extent can we already rely on off-the-shelf coding environments for this?

Robert: In the tools I’ve tried, I’ve seen some approaches to this. In some cases, they retain information across tasks or perform reflection in the background. But I haven’t yet been able to rely on them to produce the improvements I need for my project.

I’d also like more insight. I want to be able to see what information has been incorporated and how the system has adjusted its behavior. For me, that’s a key priority for the future development of Harness tools.

But even with better tools, configuration remains an engineering task for me—one I don’t want to simply leave to AI. For a personal project, I would choose different workflows than for a client project with specific quality requirements. We still need to consciously define which rules apply, which tests are mandatory, and how we want to work with the codebase.

Highlights from the conversation

  • Long search runs and duplicate code are warning signs. If the agent overlooks existing functions or doesn’t know which module to work in, it’s worth taking a look at the architecture and its documentation. Such difficulties can occur in both human-written and AI-generated code.
  • The agent needs an introduction to the architecture. At the start of a task, it should be provided with a reference to the architecture description. This explains which tasks the modules handle and how they depend on one another. For the interfaces, it should be clearly defined what inputs they expect, what outputs they provide, and what conditions apply.
  • Architecture checks are part of the development process. Robert suggests four steps: align the task with the architecture, plan briefly, implement, and finally test. This also includes updating the documentation as needed. Binding tests can be stored in a deterministic pipeline so that their execution does not depend on the agent.
  • Reviews of completed tasks can improve the harness. A brief retrospective documents what worked, where tool calls failed, and what corrections were necessary. From this, adjustments can be made to the prompts, skills, and workflows for future tasks.
  • Configuration remains an engineering task. Which rules apply and which checks are required depends on the specific project. Even with better coding tools, these requirements must be deliberately defined and incorporated into the harness.
Christoph Bergen
Christoph Bergen
GenAI Team Lead

An experienced representative is here to assist you.

Questions about the article?

Get in touch