I’m pushing my teams toward this on purpose. As CTO, one of my jobs is getting each engineer to run more agents in parallel, for three reasons:
- they build the muscle for context switching
- they learn to spend their energy on the highest-leverage work
- the faster we ship, the more bottlenecks show up, and we only fix the ones we can see
The bigger shift is where their time goes. Code became a commodity, so I want them writing less of it and making more decisions.
for those of you not in tech, you probably don't realise what has happened and why it's so significant.
ai can now write most of the code itself. and it's split engineers into two groups.
the first group use ai as a helper. they still work the same way they always have, one task at a time. not much has changed for them.
then you get the 20x. engineers who've realised working on one task at a time is prehistoric. they run several ai assistants at once, each working on a different job, and act as the manager checking it all.
imagine your GP, who sees one patient every 10 minutes. now they're seeing five at once in the same slot and do better diagnosis than human GPs, and the tools helping them get noticeably better every month. that's how extreme it is.
which means companies can now get more done with fewer engineers. but not every engineer can become the 20x.
I removed myself from code review. Every merge got safer.
The problem: my agents open PRs faster than I can read them. Every PR waiting on me gathers conflicts, and a review done in a hurry checks less than it looks.
Again, a review done in a hurry checks less than it looks.
The principle: the author never verifies its own work. A separate agent reviewer judges the change, and the code host (GitHub in my case) enforces the verdict, so no agent can argue its way past it.
How it runs:
1. When a PR’s checks pass, a scheduled job starts a fresh agent session to review it. That session did not write the change and is not allowed to fix it.
2. The verdict is a commit status, flow/review, on the exact commit it read. A new push needs a new verdict.
3. Branch protection requires "flow/review", and only the reviewer’s identity can set it.
4. With every gate green, the scheduler merges.
5. Findings send the PR back for one automatic round. If it fails again, it comes to me.
6. Every PR states how to undo it. If the pipeline breaks after the merge, the scheduler reverts first and fixes after.
Agents cannot merge changes to the CI checks and to the agent instructions.
A PR that waits two days for me collects two days of changes on main to conflict with. Reviewed in the next hourly run, it waits an hour.
I’ve been using this rule for the last month and haven’t had any serious problems in my projects, mainly because a bad merge only lives until the next pipeline run.
I think if you opt to not review your code anymore, you must have observability to watch what you ship on production.
That’s what I did with my agents. A task only closes when:
- I see its effect in e2e tests
- live validation works
- production logs shows what I expect
I don't see the point to review AI generated code anymore.
AI agents are the new compiler.
We don't review bytecode. We just trust the output of the compiler.
I don't think we should treat AI output differently.
However, the authoring layer cannot be markdown. I feel like there's a paradigm just around the corner that we have missed so far. Maybe a new "language", which won't look like a programming language at all.
My rules in building software with AI:
1. Keep all state outside the agent’s conversation. Store each task’s status, blockers, PRs and decisions in a shared record. If an agent did not write it there, treat it as not done.
2. Give each stage one owner. Only the owner of a stage may change a task’s status in that stage, so two agents never act on each other’s stale view.
3. Separate the author from the reviewer. Review every change in a fresh agent session that did not write it and is not allowed to fix it.
4. Close tasks on observed results. Have the implementer state what to check, where and when. A separate check confirms the effect in production before the task closes.
5. Cap the automatic fix attempts. After a set number of failed rounds, hand the change to a person.
6. Let reversibility set the agent’s freedom. Agents act alone on what can be undone and noticed in time. A person approves the rest.
7. Never let an agent guess an open decision. Record it as a question for the person who decides, and block only the work that depends on it.
8. Order the work by the cost of waiting, read from its stage. A broken main branch first, then urgent items, then high-priority bugs, then deploys nobody has verified, then due follow-ups, then open PRs, and new work last.
9. Limit the work in review and release. When that queue is full, agents stop starting new tasks and help finish the open ones.
10. Enforce merge rules in the code host. Use branch protection and required checks, and require a person’s approval for any change to the checks or the agent instructions.
11. Start every agent session from a schedule. A scheduled job wakes the agents, and each session reads the current state from scratch.
12. Write down why each rule exists. A rule you cannot justify with a principle is one to remove.
Yesterday, I finished the order my agents pick up work. New features come last.
The main principle: Do first the job that is most expensive to leave waiting (cost of delay).
The problem: agents start work faster than anyone can finish it. If they pick new features, half-done work queue increases and value doesn't reache users.
The rule comes from Reinertsen: order work by cost of delay. My agents read it from the stage the work is in. Every tick works in this order:
- main branch red: fix it first, it holds every change in the repo
- anything a person marked very high
- bugs marked high
- merged work nobody has validated in production
- waits that came due
- open PRs: conflicts, fix rounds, reviews
- new work
A small example: main is red and 6 PRs wait on it. One repair frees these six changes. A new feature started in that hour frees nothing.
The priority labels only order work inside a stage. A high-priority feature still waits behind an unmerged low-priority PR. Only “very high” jumps stages.
I tell clients they can build it themselves with AI.
The question I ask back: do you want to spend your energy on architecture, security, tests and servers, or on your product and your customers?
Whoever picks the second one will continue hiring a software engineer.
I tell them yes, they can. But they own the rest:
- define the architecture
- review security
- maintain it
- add observability
- write tests
- run the deploy and the servers
If they’d rather spend their energy there than on the product, their customers and their brand, they should do it themselves with AI.
I decided to solve everything around the model.
An agent that serves customers needs memory of each one, search over your documents, a WhatsApp channel, a schedule, a rule for which actions need a person, and a record of what every run cost.
I’m building naturali to be that infrastructure. Each piece is a module behind one API: agents, knowledge, memories, channels, workflows, guardrails, evaluations. An AI app becomes a set of API calls.
The first real test is inside OneClick Ads. We’re using naturali’s knowledge and memories to build a second brain of our customers, so the ad recommendations know each account.
What this buys a builder:
- you start from the part only you can build
- every run is traced with its cost from day one
- the SDK, the CLI and the MCP server share the same API, so you can build by talking to Claude
In naturali, you can attach a guardrail on agent's tools. The guardrail is a versioned rule document, and it sorts the call into four tiers:
A: read-only, it runs
B: runs only if its guard passes
C: waits for a person to approve
D: blocked, and the model is told so
I taught my agents to estimate cost of delay. They read it from the stage the work is in.
The stage gives a ranking that holds for every project:
- a defect in production hurts users every hour
- an open PR gathers conflicts
- a deploy nobody validated lets a regression run
- a new task loses little by waiting one more round
So an agent can flag a critical bug and move it to the front without any math. The only override is a person marking something top priority, because that is their own word that waiting costs most.
It’s the principle behind the rule I: validations and merges first, new work last.
I set one priority rule with my team: post-deploy validations and merges come before any new task.
The rule is simple: when you can’t do everything at once, do first the job that is most expensive to leave waiting.
My experience with tests and AI:
Requiring 100% test coverage made my agents' test quality worsen.
I set that target in my agent workflow months ago. CI got slower on every release, implementations took longer, and the agent started writing tests that existed only to reach the number. The suite stayed green and proved little.
This is Goodhart’s Law: when a measure becomes a target, it stops being a good measure. The cheapest path to 100% for an agent is a test that asserts almost nothing.
The principle I cite most often: the author never verifies its own work. An agent judging its own change will turn the checks green whether or not the problem is solved.
So I dropped the coverage target and moved verification up a level:
- end-to-end tests on the behavior a user would notice
- observability across the whole system, to see the effect after it ships
What it buys:
- CI time goes to tests that catch real breakage
- green starts to mean the change actually worked
Same principle as before: the author never verifies its own work, and a coverage number written by the agent is still the agent’s verdict.
The fastest way we found to explain our UI was to let users skip it.
At @oneclick_ads , our biggest problem was people getting lost configuring the optimization parameters. The engine worked. The settings screen was where users gave up.
Two months ago we opened the same engine through an MCP. Now users set up optimizations by telling their AI assistant what they want.
Retention seems to have gone up since then.
For an AI product, the assistant your customer already uses can be the interface.
The better my agents get, the harder the work they hand back to me.
A British psychologist wrote a paper in 1983 that predicted every single problem we’re having with AI in 2026.
It's called “Ironies of Automation”
More advanced and reliable an automated system gets, the more crucial the human operator becomes.
When engineers build an autonomous system, they automate the predictable tasks. What do they leave for the human?
Only the most complex, chaotic, and dangerous edge cases that the engineers themselves couldn't figure out how to code.
We are rapidly turning developers, writers, and operators into "AI supervisors."
But cognitive skills deteriorate when they aren't actively used. If an AI agent or Copilot does 99% of the work, the human loses their deep mental model of the codebase or the system.
When the AI inevitably hallucinates or fails, it hands control back to the human. But the human is now totally out of practice, right at the exact moment they have to step in and solve a catastrophic edge case.
The Monitoring Illusion We expect humans to just "supervise" AI output. But humans are biologically terrible at maintaining vigilance while waiting for rare errors.
Worse, if an AI is deployed because it processes data faster and handles more variables than a human, it is physically impossible for the human to check the AI's logic in real time.
You cannot supervise a black box that thinks faster than you.
We aren't removing human error with AI. We are just delaying it to the absolute worst possible moment.
As we shift heavily into vibe coding and agentic workflows, the warning from 1983 is urgent.
If you just mindlessly supervise the AI and stop practicing the core skill yourself, you won't be able to step in when the machine breaks.
The principle I cite most often: the author never verifies its own work. An agent judging its own change will turn the tests green whether or not the problem is solved.
A lot of new SaaS products are shipping agents that are too advanced for the people buying them.
The problem is the person who's holding the wheel.
We learned this at OneClick Ads. Our first product was an algorithm that optimized Meta and Google campaigns on its own: pause, scale, shift budget. The intelligence worked. We found few customers who really wanted it.
Most people running ads were still beginners. Optimization is like shifting gears at exactly the right moment. A driver only cares about that once steering, signaling and checking the mirrors are second nature. Our users were still learning to steer.
So we flipped it. Same intelligence, delivered where they actually were. The OneClick MCP plugs into any assistant, and you run your campaigns by asking in plain language. A beginner gets a copilot while learning to drive. An advanced user can set the optimization rules by talking to it.
Agent SaaS is about to hit the same wall. A fully autonomous agent solves the last stage of a problem. Most of the market is still on the first one: understanding the problem, doing it by hand, learning what good looks like. An agent that skips those steps has nobody ready to absorb it.
Before you build the most autonomous agent in your category, find out where your customers are on the learning curve. Build the agent that helps with that step, and let it grow with them.
Vibe-coded apps built by non-technical people usually hit a barrier once security becomes important.
Anyone can launch an app today, but only technical people have the experience to properly address the security issues that arise.
Non-technical founders can learn to fix those problems, but it isn't the best use of their time. Their strongest contribution is usually marketing and talking to customers.
A rule with no reason gets followed literally, right up to the edge case where it shouldn’t be.
The agent needs the why at the edges. For example, I can instruct the agent to “Prioritize merges over new implementations.” It comes from queue theory and cost of delay: unmerged work is inventory, and every hour it waits is value nobody gets. The agent can’t work that out from the rule alone. With the reason written down, it can make the call when the rule doesn’t quite fit.
But keep the reason to one sentence. Instructions are paid for on every turn, so a page of theory in them costs too much. Put the long explanation somewhere the agent can load when it needs it.









