It has now been 18 months since the release of Claude Code (as of September 2026), and for some developers, the way they work on code has certainly changed a lot. However, once you step outside of your AI bubble, many teams are still facing the challenge of how to use Claude and others efficiently in their day-to-day development work.

This blog post aims to summarize my experiences from the last 1 1/2 years of agentic coding in daily project work and in customer trainings.

At the end of last year, I already wrote a blog post on the topic of AI in software development. The capabilities of the models have improved further since then, and more tasks can be implemented automatically. My conclusion, however, remains the same: Coding is not the bottleneck

Agentic Coding

AI-assisted software development is not agentic coding. AI agents aim to complete a task autonomously. These can be different kinds of digital tasks; in agentic coding it concerns software development, or rather the creation of an artifact.

Besides the actual AI model, agentic AI systems consist of a harness. The harness is the software environment in which requests are sent to the model and the response is received. The harness provides tools and implements an agentic loop, in which the AI system iterates over a result in multiple passes, for example to work through several tasks one after another or to fix failing tests. Guardrails and instructions that we give to an AI model are also part of the harness (e.g. AGENTS.md or CLAUDE.md).

No Pair Programming with the AI

As long as you regard a coding agent as an AI chatbot integrated into your IDE, you will not achieve any major efficiency gains. Constantly playing ping-pong may answer my questions or generate individual code blocks or methods, but I have to keep my attention on the current chat conversation the whole time.

The advantage that an agentic approach brings is that an AI works on its own until a required result or a result interpreted as required, is available. In doing so, I do not have to look over the AI’s shoulder and can turn to other tasks in parallel.

What matters when defining the end state is describing it. For an AI to deliver the result I expect, I first have to be aware of it myself. The more precisely I describe a task, the better the generated result will be. That description can happen on several levels of abstraction:

  • Information about the system as well as the context in which the feature is being developed
  • Description of user personas and target audience
  • Precise definition of the feature, e.g. from the corresponding user story
  • Acceptance criteria
  • Technical details and requirements
  • Required class or method names

If the result the AI delivers deviates from my mental model of how I imagined the result, action is needed. Perhaps my initial prompt was not specific enough, or implicit assumptions were not communicated to the AI. Or maybe the task was simply too large for a single prompt and a single agent run.

Slicing requirements into small, self-contained tasks is not a new insight, and it remains a good tool in agentic coding too for achieving the desired results in a short amount of time.

Learning: Don’t babysit the AI

Making Implicit Decisions Explicit

When using AI for software development, we frequently see that developers are not satisfied with the result the AI delivers. In most cases this is not due to the capability of the model. That is good enough for most coding tasks. The problem is missing context.

When developing by hand, you continuously make decisions while implementing a feature: where do I place this class, how do I name this method, how do I structure the tests for this code. All of these decisions are made implicitly and often without much reflection. Because that’s how it has always been done, or “because it’s obvious”. This information, however, is not obvious to an AI unless you tell it.

To get a good result from an agent, you have to make all of these decisions explicit. Some things can be derived from the existing codebase. Tell your AI to follow the example of a specific existing class. Other things apply to the entire project and can therefore be handled well via an AGENTS.md file. Everything that is relevant for implementing the current task belongs in the prompt or has to be made accessible to the AI in some other way (e.g. access to the user story).

Instead of deciding implicitly during implementation, the process of making these decisions now has to happen beforehand. Take the time to write the prompt. Think about all the eventualities that will come up during implementation. Prompts that end up being several dozen lines long are not uncommon here. The work of developers now consists of describing a task to an AI so precisely that they no longer have to be present during its implementation.

Learning: Make implicit decisions explicit

Feedback

Give the AI feedback when the result does not match your expectations. This can be directly in the next prompt while you iterate in the right direction. If a problem occurs repeatedly, that is a good candidate for an entry in your AGENTS.md file.

Feedback also means, however, that an AI can check on its own whether the generated code meets certain quality requirements. Static code analysis, linters and, above all, good test coverage are an efficient foundation for obtaining code that is not only syntactically but also semantically correct. The most valuable tests have always been end-to-end tests. This holds for agentic coding as well. And an agent can deliver very good end-to-end tests to you right along with the feature implementation. Tests that might have been too costly to write by hand.

If you develop test-first, you can pass that on to an AI too. Before implementing a feature or fixing a bug, have a test generated that initially fails and turns green after successful implementation.

Learning: Good test coverage is the foundation for agentic coding

Review

We keep hearing that code review is the new bottleneck. Some teams wonder whether a review is even necessary anymore, or whether an AI should take that over as well.

The question is not whether the result is reviewed by a human, but when. If I don’t do code reviews, my AI-generated code ends up on a staging environment (or directly in production), and my product owner, product manager or other project stakeholders carry out the review and the testing of the deployed artifact. If I spot errors at that point, I have to run through the entire implementation pipeline again: define expected behavior, implement the fix, create a pull request, continuous integration run and deployment.

Even when the coding is done by an AI, depending on the deployment setup it still takes minutes, hours or days until the fix is rolled out and can be tested again.

Even in times of agentic coding the rule holds: the earlier I find a potential error, the cheaper the fix.

Even before the age of AI, many people found code reviews time-consuming and draining. AI only amplifies this. And the problem is not the AI either, but how code reviews are handled. Large pull requests with dozens of changed files that follow no clear line are simply not reviewable in any meaningful way.

So for reviewing AI-generated code as well:

  • Slice stories small enough that the pull requests stay manageable.
  • Break stories down into implementable tasks
  • A PR changes only one thing
  • Do reviews synchronously together with colleagues
  • Do reviews promptly and in batches. Don’t let PRs sit around for hours or even days

Another advantage of synchronous reviews: several people on the team have read the affected code and developed an understanding of it, and project knowledge is shared more widely.

Learning: Make code reviews as pleasant and efficient as possible

Non-Determinism as an Opportunity

Large Language Models do not work deterministically. Sending the same prompt repeatedly yields slightly to strongly differing results. This is not a bug but a feature of LLMs, and it is controlled via the temperature. The temperature allows a certain degree of randomness in the output.

For software developers this is sometimes not easy to accept; after all, the programs we otherwise work with do behave deterministically. For the development process, on the other hand, things look different. Depending on which person implements a feature, the result will look different. Even the same person will arrive at a solution that differs in detail at different points in time. The solutions will often not differ fundamentally, but sometimes they do and one variant is actually much better suited to the specific problem than the other.

Something similar happens with the program code generated by an LLM. The solutions vary somewhat, and sometimes there is one among them that you would not have thought of yourself. And for the code once it has been generated, the promise of deterministic behavior applies again, of course.

Learning: Take advantage of non-determinism