Technical blog
Opinions on Agentic Coding
Opinions on trust, verification, and time cost formed from real-world experience. Part 3 of a series on working with Claude Code in a large brownfield enterprise codebase.
TL;DR: Opinions on trust, verification, and time cost in agentic coding, formed from day to day agentic usage at pretty much everything one does as a software engineer. On a well-scoped implementation story, Claude Code is a clear win. On an open-ended design investigation, the benefit shows up with initial drafting, but after you understand the system well enough to steer it confidently the read-verify-correct cycle becomes the biggest time cost. This draws on one long-running case study — removing one payment method for specific customers across many services, DB migrations, and back-office tooling — as the extract behind three things I formed opinions on: the /specs folder pattern I ended up with covers agents knowledge managment, the recurring agent’s failures (context compaction, code/test loops, mis-scoped work), and an honest accounting of whether any of it actually saved time.
For the mechanics of memory, skills, and subagents referenced throughout, see Part 2: Teaching Claude Code Your Standards.
Delegation
Claude Code does not replace development work. In a large brownfield system, it shifts effort from manual execution to steering and verification. It speeds up search, drafting, branch setup, data digging, writing code, ad hoc queries, scripts, commands, and other repetitive work, but only when the setup around the model is curated.
That setup matters as much as the model itself: context lives outside the chat, permissions define boundaries, memory captures repeated corrections, skills turn workflows into pipelines, and subagents isolate exploration. The time cost and cognitive load do not disappear; they move from typing and browser tab-switching to steering, reading, verification, and agent maintenance.
A long term Case Study On Design Work
Dozens of sessions. 5,000+ user turns. Many millions of tokens.
The generic requirement was to remove one payment method for specific customers, with specific exceptions, across many services, multiple DB migrations, the payment-method type system, and back-office account tooling. Claude could search repos, draft comparison tables, and surface contradictions quickly, but each claim still had to be checked against code, SQL, and data evidence. The loop became: read, verify, correct the spec, then read again.

Here is the example of the knowledge base structure. This simple structure grew organically out of this project. It became personally a useful standard for multi-service design investigations. More complicated frameworks do this with agent swarms, but I mostly need something simpler: a way to manage a huge volume of context and build a knowledge base across sessions and agents.
specs/<epic>/
├── todo.md ← Entry point. Work queue + open question tracker.
├── design.md ← Final design doc. Written LAST.
├── requirements.md ← Verbatim requirements + product clarifications.
├── test.md ← Test data and selected cases.
├── systems/ ← Q&A research. One file per system area.
│ ├── first_deposit.md
│ ├── withdrawal_call_chain.md
│ └── balance_fields.md
└── flows/ ← PUML diagrams for deposits and withdrawal flows
todo.md is the anchor file. It has four sections: Index (links to every doc in the folder), Current Starting Points (specific code file paths that are the ground truth right now), Open Questions by category (product/implementation/.NET/waiting), and Resolved Questions with evidence and dates. Initial questions are based on what is in the requirements.md. I write section headers and question stubs first and then let Claude fill in verified content inside that frame. Those headers and questions limit where Claude can drift. The questions also helped me frame the problem better.
The Resolved section shows the history of decisions, the evidence, and if I have confirmed its correct.
The systems/ pattern: one file per system area, with tags to questions numbered within (Q1, Q9, Q11), referenced from todo.md and design.md. Instead of asking Claude to re-explore a system area mid-session, link to the file: “reparenting mechanics are in systems/reparenting_mechanics.md.”
The design.md document: the final design doc from which the Jira tickets are created. It outlines the general approach across multiple systems. I had initially AI draft it through discovery sessions and then edit it by hand. The editing was substantial because the model kept drifting away from facts. At times I seriously questioned whether AI was saving any time here or whether it would have been faster to write the doc by hand.
The agent added more work for me: structural edits, duplication removal, factual corrections (“this call chain is not correct, update all references and logic”), noise removal, invented-term corrections, abbreviation fixes, style fixes, and assumption fixes. Every correction slowed the process and increased token burn.
Assumptions, Requirements, Source of Truth
One default AI-agent behavior that I have noticed is to turn missing context into assumptions or into some version of “yes, that’s totally fine, carry on.”
Persistent memory rules helped me override Claude’s default behavior with something like “do not assume, use code or Confluence docs to verify.” It is simple and obvious to me, but not really to the model. It loads every session, and it works more often than I expected. It nudges the model from “state the assumption confidently” toward “verify, then state.”
Assumptions still creep in over long sessions. During the long term design work, Claude would sometimes drift toward confident statements about code behavior that needed correction once the actual code was read. I started using a dedicated /specs folder as a source of truth for findings, and that helped in long-running investigations. The systems/ files capture verified answers, and todo.md tracks resolved questions with evidence so settled points do not get reopened.
It is also useful to get the agent to challenge my assumptions:
“I think we should do hard delete in the xxx table, try to prove me wrong.”
This prompt gives Claude a specific verification task: look for evidence that contradicts my decision. I still own the decision. Claude checks code, documentation, logs, or data and reports what it found. It is still a bit of a dice roll, but it can surface unexpected issues around the change.
Additionally, mechanical proof matters when writing code. Pre-commit hooks run the full test suite with the race detector and linters locally as well as in CI. If a hook fails, the commit does not happen, and the model has to investigate. That gives me evidence, not just the model’s word that everything is fine.
Where the Agent Breaks
The weak points mostly show up when the agent has too much freedom, too little evidence, or too little visibility into its own progress. It often self-corrects when pointed at a particular code file or doc.
Context compaction loses the thread. When a long session fills the window, /compact summarises it and carries on, but the summary is not lossless. After a compaction, the agent may re-ask something settled 400 lines earlier, drop an assumption, or reintroduce a term I already tried to get rid of. The “wait, we already covered this” moment is common.
The fix is to externalise live state into todo.md, design notes, or memory so it survives the summary. In my experience compaction happens quite often, overflowing a 1 million token window is not hard during design work or nasty bugs. A 200K window can go through multiple compactions even on a medium implementation task.
It loops between code and test. When a test fails, the agent can fall into a rut: patch the code, rerun the test, fail again, and patch the same area another way. Without close supervision, it can circle the same few edits instead of stepping back to question the broader fixture or the assumption underneath it. Better models behave better at this.
The same shape appears in design work when the agent revisits the same flow again and again. Not all cognitive load can be delegated; some problems still need a human to work through them and steer the agent.
It mis-scopes work. If the prompt says “improve this” or “review this” without a boundary, the agent may turn a local fix into an audit, a refactor, or a new architecture pass. For big vague work, the same problem shows up inverted: it may stay too shallow or avoid the design question that matters. I try to give it a maximum scope: files it may touch, files it must not touch, the exact output I want, and the definition of done.
It writes before it understands the repo. Large codebases have old implementations, duplicated code, generated code, shared templates, stale code, particular environment configs, baked-in assumptions, and feature-specific overrides. The agent can start working on the first plausible-looking file instead of taking the wider view, or it can go too wide and veer into deeper infrastructure than the task requires. Before implementation, it should trace the entry point, list the files it plans to change, and explain why those files are in scope.
Subagents can go dark. A subagent handed too much in one go can read many files, hit a limit, retry, or stall without a clear signal to the main thread. Parallel agents also make it harder to see which branch of the work is burning tokens or following a bad assumption. Smaller, single-purpose subagent calls with structured results avoid that failure mode. More on subagent handoff risk in Part 2: Teaching Claude Code Your Standards.
The agent sometimes ignores memory. Sometimes the agent just does not use memory that is already in context and decides to do something else. First-principles-wise that is not surprising because it is still a statistical model, but in practice it feels like the dice rolled the wrong way.
Do I Actually Save Time?

The answer, as always, is “it depends.” Yes, I save time when the scope is well defined, and less so when there is a lot to design from scratch. Modern development has a lot of overhead: Jira management, complex release processes, maintenance, version control, inconsistent environments, flaky tests, complex workflows, and the cognitive overhead of navigating multiple services, database tables, procedures, and libraries while comparing them to requirements. The agent starts paying off here after the initial time invested in curating it to my processes.
Task types fall on a spectrum. At one end, work is a clear, repeatable win:
- Ritual work — branch creation, MR setup, timesheet logging, deploy ticket creation. Always mechanical, now automated. This saves time directly. Some of it could also be solved with Bash scripts, including scripts written once by the agent and reused later.
- Ad hoc draft work and one-off scripts — one big win is work that does not need to be production-grade: querying a database, testing performance, checking a hypothesis, or producing a disposable report. If I have an idea and want to test it, Claude can write a script, run it, produce the output, and let me ask follow-up questions in the same interface. I still read the result, but the whole loop can take minutes instead of hours. That feels powerful.
- Cross-repo search — finding every caller across 198 repos used to mean manual Sourcegraph passes; now it can be a single prompt. The agent does not get bored on the 40th file, and it can move across Go, .NET, and SQL. It can still miss obvious points, which is why the harness and verification loop matter.
- Data digging — schema discovery, table linking, multiple queries to land on a valid test user from db. Tedious by hand, and exactly the kind of query generation it’s good at.
The middle category is first-draft work. The agent gets to a draft quickly, but verification and correction can consume the time it saved:
- First-draft code and specs. It gets you 80% of the way quickly, but in a brownfield system with settled conventions the last 20% carries the real cost. The 542-exchange design doc was “written” in an afternoon and finished a week later. It might have been faster by hand.
At the far end, work where it can actually cost you time if you’re not careful:
- Anything you accept without reading. A confident-but-wrong call chain that you take at face value doesn’t just waste the minute it took to generate — it can send a whole exploration down the wrong path for hours or longer.
Faster Does Not Mean Hands-Off
“Did it save time?” mixes two measurements:
- Have I done this task faster?
- Could I work on something else while the agent was running, or did I need to keep watching?
Agents usually improve the first. They search, compare, and draft faster than I can. They do not always improve the second. If I need to correct drift every few turns, the task may finish sooner, but I still spend the day watching it. So while the agent is running, I mostly read the code, specs, docs, and tests so I can review its output and judge the wider impact and risk.
Some effort relocates rather than disappears:
- Verifying agentic output. Every factual claim about the code is worth checking. The model can get call chains wrong, invent terms, or place logic in the wrong file. In the removal project, the read-verify-correct cycle was the single biggest time cost over the weeks — it didn’t remove the hard part of the work, it changed its shape.
- Knowledge you did not build yourself. If Claude reads a subsystem and you do not, you do not yet know that subsystem. You cannot reliably steer the agent or verify its work unless you stay in the driver’s seat. I can delegate code writing, but I still need to understand the system, and understanding takes time and effort. I don’t have a clean fix for this yet beyond staying in the loop — if I land on one, it’ll be its own post.
- Agent knowledge curation. Spotting a pattern, writing the rule, updating memory, changing configuration, writing new skills, and curating shared conventions all take time. The payoff comes later.
- Reading. Agentic work still creates a lot of reading. Reading chat output all day adds its own cognitive load because every answer raises the same question: what can I trust, and what needs evidence?
That difference showed up in my own work. I could delegate mechanical tasks: branch setup, cross-repo search, timesheet updates, and SQL investigation where mistakes were easy to spot. I stayed close to design and migration work because wrong claims there could change the plan. I read each claim against the code before trusting it. Steering pays off over time: the agent starts following rules such as “do not assume”, “verify in code or docs”, and “ask before making a design choice.” Inside a session it can adjust to direct corrections. The tiring sessions were mostly just long, and they were the ones where I had to keep pulling the agent back to the facts and re-reading the same points repeatedly. The task maybe finished sooner, but I still spent the day reading, checking, and correcting. On some design work I think I would have been faster by myself, but at the time I had not curated the model well enough for those workflows.
The first time through a subsystem is slow because the agent does not know your terminology, style, or process rules. The second time is much faster if those corrections went somewhere durable. That is the point of memory files, /specs folders, and skills: they turn this session’s corrections into next session’s defaults.
In my use, the correction overhead on naming, style, and process dropped close to zero once I captured it. On a well-scoped implementation story, that made the agent a clear win. On an open-ended design investigation, the benefit came later, after I understood the system well enough to steer confidently.
What is Next?
Currently I am looking into loops and dispatch, so the agent can pick up new work, do implementation and a first-pass review, and prepare reports for me. Part of that is figuring out how to use subagents efficiently. Recently I switched to Opus 4.8, and yes, it is much better than previous models. When I go back to Sonnet 4.6 to save on costs, it feels different and sometimes hurts. The most expensive model wins, and that worries me a little. The dark version is a future where a few large players run the ultimate models at a scale that smaller businesses and individuals cannot match. The differentiator stops being skill and becomes who can afford the access. I hope falling per-token prices keep pushing against that, but the cost gap is real if one wants to run agents at scale. Back in everyday work, would be interesting to figure out how I can read less code or agents output more surgically. Reviewing code line-by-line is a bottleneck, but skipping the review entirely would be too risky: approving changes to a system I only understand through a summary. One idea around that is to have risk-weighing on the changes and impact blast radius. How far I can push that depends on how much I can trust the report the model produces. Practically I dont think we there yet. The next generation should be better, but it is worth being clear about where the progress is coming from. Almost all the recent gains are in agentic coding: scale, more data, and a better harness around the model. There are no new core algorithms. People like Yann LeCun are chasing different approaches like World Models, and that research is the real crux. For now we have LLMs, and even a very smart LLM — which today’s are not — still needs ground truth supplied to it. An LLM is a statistical system, so variance will always be there no matter how big the model is. Until a better algorithm arrives, hallucinations will persist, and the harness will be crucial in minimizing them.
For how this fits into the wider skill catalogue across the SDLC, see Part 4: Setting Up Claude Code Across the Whole SDLC.