An AI coding agent is not an engineering system.
It is an input to one.
Most teams start by inserting an agent into the development process they already have. The agent gets a ticket, writes a patch, perhaps adds tests, and opens a pull request. Then the old machinery takes over: a human reconstructs intent, fixes the branch, chases CI, explains repository conventions, resolves conflicts, answers review comments, and waits for the merge queue.
The model may have written the code faster.
The organization may not have shipped anything faster.
A faster generator attached to a slow, implicit, human-dependent workflow mostly produces a larger queue.
The more interesting approach is to redesign the workflow so humans and agents run on the same rails: the same source of truth, operational playbooks, branch and review rules, release gates, evidence, and institutional memory. The agent can take the wheel. A human can take it back at any point. Neither should need a translation layer.
The operating model I trust is:
the model owns heuristics
the workflow owns invariants
the human owns judgment
the repository owns memory
That is what I mean by agentic development.
Not autocomplete.
Not a chat window next to an IDE.
A software delivery system designed for agents as first-class contributors.
Generation is one step. Delivery is the system.
The unit of productivity is the landed change
Code generation is only one step in a much longer path:
intent → isolated workspace → implementation → testing → review → CI → merge queue → release proof → archive → learning
Each transition has state. Each state has evidence. Each transition can fail for a different reason.
This matters because the bottleneck moves as generation gets faster. When code is expensive, we optimize code creation. When code becomes cheap, review, integration, testing, release, and human attention become the scarce resources.
A workflow that needs a human to re-prompt the agent after every external wait is not autonomous. It is interrupt-driven delegation.
A workflow that lets an agent produce ten pull requests while senior engineers manually reconstruct what happened is not necessarily productive. It may simply be converting model tokens into review inventory.
The development system has to carry the change, not merely generate it.
The relevant unit of output is a change that lands with evidence, release proof, and retained learning.
1. Skills, not prompts
A prompt is a conversation.
A skill is an operating asset.
Prompts disappear into chat history. Skills live with the code. They are versioned, reviewed, discoverable, and available to the next engineer or agent without asking anyone to remember what worked last time.
A useful skill does one thing well: create an isolated workspace, deploy to a development environment, resolve a merge conflict without erasing someone else’s work, write a test that will not flake, review a change against known failure modes, or carry a pull request through the merge queue.
The important part is discovery. The agent should not have to remember that a skill exists. Intent should route to the skill automatically:
“deploy this change” loads the deployment procedure
“review this pull request” loads the review discipline
“add a browser test” loads the test-design rules
“resolve the conflict” loads the conflict-resolution playbook
The principle is simple:
do not let the agent improvise an operational sequence that the organization already knows
There is also a useful split inside every skill.
Put deterministic mechanics in deterministic code: branch validation, workspace creation, naming, parsing, status checks, and machine-readable output.
Leave only the genuinely non-deterministic parts to the model: interpreting intent, choosing among safe options, explaining a tradeoff, or deciding when to escalate.
This reduces token use, but the bigger benefit is behavioral consistency. A human and an agent invoke the same operation and get the same rails.
Skills can also encode architecture, not just procedure. Reaching for a one-off UI element can route the contributor toward the shared component. Adding a new capability can load the feature-flag convention. Touching state management can surface the rules for where that state belongs.
That is how consistency scales. You do not wait for review to catch every local invention. You make the shared primitive the default at the moment intent is detected.
One more practical detail matters: author the skill once.
Different agent tools consume instructions differently, but the institutional knowledge should have one canonical source. Generate the thin adapters each tool needs. Do not maintain three drifting copies of the same operating rule.
And keep the skill itself lean. A large instruction body is paid for repeatedly as context. The core file should route and disclose. Heavy detail should sit in references that are loaded only when the task actually needs them.
Agent context is a budget.
Operational knowledge should be durable, but it should not be noisy.
2. Planning should scale to the work
Agentic development needs written intent.
It does not need a design document for every typo.
The useful pattern is a ladder:
A one-line cleanup item for work too small to deserve a ticket.
A plan for one change that carries durable context, sequencing, or a multi-session handoff.
A design for broader implementation strategy across several changes.
A specification for the problem, users, and intended outcome of a substantial capability.
The default at every rung should be the lightest artifact that can safely carry the work—including no artifact at all.
This is not just documentation hygiene. The artifacts are the agent’s durable memory.
A fresh session should be able to pick up a ticket, find the relevant intent, understand what decisions have already been made, and continue without reconstructing the world from chat history. A different model should be able to do the same.
That is why planning artifacts have to be the source of truth rather than a ceremonial layer beside the “real” work.
And when the work lands, the artifact should not disappear.
Archive it with a short retrospective:
what shipped
what was cut or deferred
where implementation diverged from the plan
which pull request landed it
what a future maintainer should know
A forward-looking plan without the outcome is an aspiration.
A plan plus a shipped record is institutional memory.
The same principle applies to the tracker. Ticket state should follow the real state of the pull request through automation, not depend on a person remembering to drag a card. The repository should tell the truth even when nobody updates a dashboard manually.
3. The workflow is the guardrail
Conventions that live only in a document are suggestions.
Conventions enforced by machinery become the way work happens.
Every independent task should get its own isolated workspace and branch. That gives parallel agents the same isolation parallel engineers need. One task, one branch, one traceable unit of work.
The branch should identify the work. The tracker should identify the intent. The pull request should carry the evidence. The merge should close the loop.
Destructive shortcuts should be unavailable by default. Do not let an agent casually rewrite shared history, force-push over another contributor, or bypass the merge path because it is “almost done.” The right workflow should be easier than the dangerous one.
CI should follow the same pattern.
Large systems often need more than one build and test system. That is fine. What matters is presenting one clear contract to the merge machinery: a single required gate computed from the underlying evidence.
The merge queue then has to test against reality.
A green pull request is green against a snapshot.
A green merge candidate is green against the mainline plus the changes ahead of it plus itself.
That distinction catches the failures individual pull requests cannot see: two correct changes that become wrong when combined.
The queue should also be honest about blame. A red build can come from the change, a known flaky test, or infrastructure. Treating all three as the author’s fault wastes time and trains people to ignore CI.
But “probably not your fault” is not enough. Retaining a change in the queue should require positive evidence. When the system cannot establish innocence, it should fail toward ownership rather than wave the change through.
That asymmetry matters.
Automation should be generous with diagnosis and conservative with authority.
4. Review against failure modes, not vibes
A change is not correct because it is internally coherent.
A mock can agree with the implementation and still model the wrong system. A test can inspect source text and still prove nothing about runtime behavior. A design can match the code and still miss the user’s intent.
Self-consistent is not the same as correct.
Review should therefore start with intent discovery.
The reviewer walks from the richest source to the poorest:
acceptance criteria → change description → title and branch → commits → diff alone
It should state what it was able to establish and never invent conformance where the intent was unavailable.
With intent in hand, review becomes much more useful. It can find not only bugs, but also unmet acceptance criteria and undeclared scope growth.
The next improvement is to review against concrete failure modes rather than generic taste. Each domain should have a catalog of ways it has actually broken: cleanup that is narrower than the read path, timers that outlive a test, readiness checks that pass before the service is usable, unordered collections asserted in a fixed order, or release code that reads stale state.
Each checklist entry should come from an observed incident.
Speculative rules create bureaucracy. Remembered failures create leverage.
For larger changes, review should converge in passes rather than run once and emit forever:
re-read the original change, not the previous review prose
subtract, merge, or demote weak findings before adding new ones
replace hedged language with evidence, mark it unverified, or remove it
raise the severity bar on later passes
stop when new material findings disappear
escalate when repeated findings point to a design problem rather than an implementation problem
The result should become sharper and smaller over time.
Review depth should also scale to risk. A documentation fix does not need a seven-pass investigation. A change touching identity, persistence, release infrastructure, shared types, or test machinery may deserve specialist review in parallel.
Those specialist reviewers should be read-only. The system that judges the change should not quietly edit the thing it is judging.
Automated findings also need a disposition path. A serious finding is not cleared because the author typed “looks good.” It is cleared because the issue was fixed or because the disagreement contains a reason the system can evaluate.
And if automated approval is introduced, the policy should be deliberately boring:
veto first → grant a narrow class → default deny
High-risk paths go to a human. Eligible changes must pass deterministic corroboration. Missing signals default to false. The policy is read from trusted code outside the change under review, so a pull request cannot rewrite the logic that approves it.
Run the policy in shadow mode first.
Trust-sensitive automation should earn authority by producing evidence before it is allowed to exercise authority.
5. Autonomy lives across the waits
Writing a patch is the easy part of autonomy.
The difficult part is carrying the change across everything that does not happen immediately:
waiting for CI
waiting for review
responding to findings
resynchronizing when the mainline moves
resolving conflicts
entering the merge queue
surviving an eviction
verifying that the merge actually landed
A useful autonomous loop should not hold the world in model memory. Every time it wakes, it should read the live state again.
The shape is:
observe → decide → act → wait or escalate → wake → observe again
Observation should be read-only. Decision should be side-effect-free. Actions should be explicit and ordered.
That makes the loop restartable. A crash does not corrupt hidden state. A model switch does not lose the workflow. A stale head commit causes re-derivation rather than an action against yesterday’s world.
Waiting is not failure.
A clean pull request that only needs an approval should park silently and wake when something changes. An agent that keeps asking “should I continue?” is transferring coordination cost back to the human.
Escalation should also be narrow.
One ambiguous security question should not stop every other safe action on the pull request. Park the uncertain item, label it for a human, and keep working on the rest.
The load-bearing rule is:
escalate, do not guess
A useful autonomous loop re-reads live state on every wake and escalates only the uncertain item.
Low confidence, destructive operations, security-sensitive changes, ambiguous intent, architectural drift, and actively disputed human feedback belong with a person. Routine synchronization, evidence gathering, bounded retries, and mechanical review cleanup belong with the agent.
The human should not be in the gears.
The human should be at the gates.
6. Test where the code runs
A test is only meaningful in the runtime it is meant to protect.
Modern products may span server logic, browser components, containers, deployment templates, end-to-end flows, and agent behavior. Some tests run locally. Some require a live environment. Some exist only in shared CI.
The test-authoring system should route the contributor to the correct layer before work starts. Knowing that a change requires a slow remote cycle is part of planning, not a surprise after the code is written.
New tests should also clear a determinism gate.
The first tier is cheap: screen the test against known flake smells for its layer.
The second tier is selective: when a smell is present, repeat the test on the cheapest appropriate runner.
But be honest about what repetition proves.
Repeated green runs can catch high-frequency nondeterminism inside one test. They do not prove the absence of inter-test failures caused by leaked state, order dependence, shared databases, or sharding. Those appear only in the real suite.
This is a recurring theme in agentic development: use automation aggressively, but describe its evidence precisely.
When the product itself contains an agent, conventional assertions are not enough. “Did the agent behave well?” is often a rubric question, not a string-equality question.
Evaluation cases should therefore be first-class test assets:
a prompt or scenario
a rubric describing the desired qualities
a captured transcript
a score and explanation
a versioned place in the regression suite
Production traces can become new evaluation cases. A surprising interaction is reviewed, converted into a fixture, and replayed on future versions.
That is how a production failure stops being an anecdote and becomes a permanent test.
The caveat matters: rubric-graded evaluations are noisier than deterministic assertions. Some should trend quality rather than block every merge. Judge the distribution and the direction, not one stochastic run.
Performance tests need the same discipline. Gate on a distribution, not one lucky or unlucky sample.
7. Build once, prove it separately, promote by identity
The artifact that passed should be the artifact that ships.
Do not rebuild it for release. Do not rename it into trust. Freeze it, identify it by its inputs, and promote that exact object through independent quality gates.
This separates three ideas that are too often conflated:
The change merged.
The artifact is releasable.
The artifact is deployed.
They are not the same event.
Build once, prove separately, and promote the same immutable artifact.
A release pipeline should run its own proof: performance, security, coverage, code quality, software approval, and whatever else the product requires. Those gates—not a vague belief that the mainline looked healthy—are the release bar.
Even a blocked release should leave an audit record of what would have shipped. The gate should block the release, not erase the evidence.
Security follows the same pattern.
Start with a hardened, consistently pinned base so the scanners have less inherited risk to find. Scan broadly. Unify the findings. Be explicit about what is advisory during development and what becomes blocking at the release boundary.
Automate safe dependency updates. Escalate major changes, ambiguous fixes, and modifications to the trust machinery itself.
And fail closed on coverage drift. Adding a new scanner or dependency surface without adding it to the automation’s coverage map should make the system red rather than silently incomplete.
The model can classify a finding.
The release system decides whether the artifact moves.
8. Observe the development system—and account for it
An automated workflow that cannot explain itself will not remain trusted.
Observe four layers:
the running product
each agent turn and tool call
CI and merge-queue health
the economics of the development loop
The last one is easy to underbuild.
Agent spend should be attributable to the unit of work: ticket, pull request, person, agent tool, model, and automated review. The pull request is a useful source of truth because it already anchors intent, code, evidence, review, and outcome.
But token cost alone is not the cost model.
Track:
cost per accepted change
attempts per task
human interventions
model switches
review latency
queue retries
escaped defects
repeated codebase reads
duplicated agent work
percentage of incidents that improve a skill or evaluation
This is where model routing becomes engineering rather than vibes.
Routine, bounded work should use the cheapest model that can complete the entire loop safely. Ambiguous architecture, security-sensitive changes, release-critical work, and adversarial review should spend more when the stronger model reduces rework and senior attention.
The cheapest model call can still produce the most expensive development loop.
Context size deserves the same scrutiny. A bloated skill that re-enters context on every turn can cost more than its author realizes. Measure it. Move rarely used details behind progressive disclosure. Verify that references remain live.
Do not merely record agent cost.
Make it optimizable.
9. The real self-improvement loop
The most important rule is about where learning goes.
When a human or an agent learns something reusable, write it back into the shared system in the same change that exposed it.
A flaky test becomes a new entry in the flake-smell catalog.
A merge-queue failure becomes a diagnostic rule.
A deployment surprise becomes a hardened step in the operating skill.
A strange production interaction becomes an evaluation case.
A repeated review finding becomes an architectural convention.
Do not put the learning in a personal note.
Do not leave it in a chat session that will disappear.
Do not create a vague “lessons learned” document nobody will load at the moment of action.
Put it where the next run will discover it automatically.
The catalog should grow only from observed need. That keeps it credible. A skill registry full of speculative warnings becomes noise; a skill registry built from real incidents becomes compressed organizational experience.
This is the practical version of a self-improving engineering system.
The model does not need to remember the incident forever.
The organization does.
The model does not retain institutional memory. The workflow does.
The stable equilibrium
The models will improve.
The coding tools will change.
More of planning, implementation, testing, review, diagnosis, and release preparation will move into the agent loop.
Good.
We should want that.
But the durable boundary remains:
more intelligence inside the model
more authority outside the model
The agent can propose.
The workflow enforces.
The agent can diagnose.
The evidence decides what happens next.
The agent can learn a pattern during one task.
The repository turns it into institutional memory.
The advantage is not the percentage of code an agent writes.
The advantage is a development system that can absorb better models without giving away judgment, release authority, or the history of why the organization works the way it does.
The model is replaceable.
The compounding workflow is not.
Agentic development begins when the agent stops being a novelty bolted onto an old process and becomes a first-class contributor to a workflow designed for both humans and machines.








Ruslan, thank you for this thoughtful and practical article. I strongly agree with your central point: AI-native development is not simply about inserting a coding agent into an existing process. It requires redesigning the entire delivery workflow so humans and agents operate from the same source of truth, follow the same rules, and produce the same evidence.
I’m currently going through a major transition in the way I build software and work with coding agents. Your article provides the North Star guidance I need during this transformation—not only for adopting the tools, but for building the right workflows, guardrails, and organizational habits around them.
Your formulation—the model owns heuristics, the workflow owns invariants, the human owns judgment, and the repository owns memory—captures an essential division of responsibility. The point that resonated with me most is that productivity should be measured by the change that actually lands, not by how quickly code is generated. Faster implementation means little when review, testing, integration, release, and organizational learning remain slow or dependent on constant human intervention.
I also appreciated your emphasis on turning lessons from incidents, reviews, and deployments into durable skills, tests, playbooks, and repository knowledge rather than leaving them in temporary conversations. That is how AI-assisted development becomes a compounding organizational capability instead of a collection of isolated coding experiments.
Your conclusion is especially powerful: more intelligence inside the model, but more authority outside it. This is one of the clearest descriptions I have read of how agentic development can become both scalable and trustworthy. Thank you for sharing it.