AI-Native Development: A Working Blueprint
A structured process for building software with coding agents — from raw idea to a self-running backlog. Based on the workflow described in Alexey Grigorev’s “AI-Native Development: Specifications, Loop and Graph Engineering” (AI Dev Tools Zoomcamp, DataTalks.Club).
Source: https://alexeyondata.substack.com/p/ai-native-development-specifications
Why this matters
Coding agents can now produce code faster than a human can review it. The bottleneck has shifted: it’s no longer typing, it’s specifying precisely what you want and verifying what comes back. A vague instruction to a weak agent produces a small mess. A vague instruction to a strong agent produces a large, well-tested, confidently-wired mess that still isn’t what you needed.
This blueprint lays out a repeatable system to close that gap: write specs before code, decompose work into small tasks, assign the work to a “team” of specialized agent roles, and run the whole thing as a loop instead of a manual back-and-forth.
The building blocks:
- Spec-driven development
- Context engineering
- Loop engineering
- Graph engineering
Prompt Engineering Context Engineering Loop Engineering Graph Engineering
(what you say in -> (what the agent -> (how often it runs, -> (who does what, when
one message) knows before it on what, when there's more than
starts) it stops) one agent)
1. Specs Before Code
Before an agent writes a single line, work out what you actually want. This is spec-driven development: the specification is the canonical source of truth, and code is derived from it.
Two levels of spec:
| Level | Scope | Lifespan |
|---|---|---|
| Project-level | What the project is | Written once, rarely revised (e.g. plan.md, process.md, AGENTS.md) |
| Feature-level | What one change should do, and how you’ll know it worked | Written per task, discarded once done (e.g. a GitHub issue) |
2. Start in a Chat Assistant — Not a Coding Agent
Don’t open a coding agent first. You don’t yet know exactly what you want, and coding agents are built to write code, not to help you think — so you’ll waste time and tokens.
Instead, open a plain chat assistant (voice/dictation mode works well — it keeps you “explaining” rather than “specifying too early”) and talk through:
- What the thing is
- Who it’s for
- What it should do
- What it shouldn’t do
- What you’re still unsure about
- What already exists, so you’re not rebuilding a solved problem
Once the shape of the idea is clear, ask the assistant to save the conversation as a downloadable markdown file. That file becomes your spec — typically covering:
- What the project is, in a couple of sentences
- Who it’s for and what they’re trying to accomplish
- What it deliberately does not do
- The tech stack and constraints
- A rough architecture: the main pieces and how they relate
Open chat assistant
|
v
Talk through the idea: what / who / does / doesn't / unsure
|
v
Check what already exists
|
v
Ask assistant to save as markdown
|
v
plan.md (the spec)
3. Bootstrapping the Project
Turn the spec into a repo with a working backlog.
Set up the repo:
mkdir project-name && cd project-name
git init
mkdir _docs
mv ~/Downloads/plan.md _docs/plan.md
Decide the tech stack (if not already settled) by asking the coding agent to propose and explain options — without writing any code yet. Left undecided, the agent will pick for you, which is fine only if you don’t care how it’s implemented.
Break the plan into tasks. Ask the agent to generate a tasks.md backlog where:
- Each task is small enough to finish in one session
- Each task is independent enough to hand to someone who hasn’t seen the others
- Each task follows a template: number, title, one-line goal, 2–3 sentence description
- The very first task is always: set up an empty project with one passing test
Then review the generated tasks yourself — merge ones that are too granular, split ones that are too big, and mark anything out of scope. Once satisfied, convert them into a task tracker (e.g., GitHub issues via the gh CLI).
Finally, execute task #1: set up the empty project — folder layout, dependencies, one passing test, no features. Every task after this starts from a project that already runs, so a failing test signals a broken task rather than “nothing exists yet.”
plan.md in _docs/
|
v
Agent proposes tech stack options
|
v
Agent drafts tasks.md backlog
|
v
Human reviews: merge / split / descope
|
v
Convert tasks to GitHub issues
|
v
Task 1: empty project + 1 passing test
|
v
Backlog ready for real work
4. Context Engineering
Context engineering means making the project understandable to an agent before it starts a task. It’s distinct from prompting: a prompt is one message in one session; context is everything the agent needs to know walking in.
AGENTS.md
A short, plain-Markdown file at the repo root that every coding agent reads at startup. It does not describe the project (that’s the README’s job). It holds:
- Non-obvious commands (e.g., how to run a single test, not just the whole suite)
- Tooling rules (package manager, exact command forms)
- Constraints and cautions (what must never be committed or printed)
- Pointers to other documents (where the spec, process, and tasks live)
- Corrections you’ve had to repeat more than once
Avoid heavy markup (headings, bold, tables) — it adds token cost without adding value. Keep it under a couple of screens; if it grows past that, split content into separate docs.
Claude Code reads CLAUDE.md rather than AGENTS.md. A simple fix if you use multiple coding tools is to make CLAUDE.md a one-line import of AGENTS.md.
What never belongs in AGENTS.md:
- Transient state (“currently working on X”) — that’s a session note, not a project fact
- Secrets — keys, tokens, internal URLs, customer names (use
.envinstead) - Long explanations
Supporting documents
Beyond AGENTS.md, keep a small library of docs in _docs/, linked from AGENTS.md so the agent knows they exist but only pulls them in when a task needs them:
process.md— how work is actually done in this projecttesting-guidelines.mddesign-system.mdsetup.md,api.md, and anything else that keeps getting re-explained
Repo Root
AGENTS.md (short, always read at startup)
|
| points to ->
v
_docs/
|- plan.md
|- process.md
|- testing-guidelines.md
|- design-system.md
|- api.md
5. The Agent “Team”: Three Roles
Rather than one agent doing everything — writing code and then grading its own work — split the work into three defined roles, each with its own file under _docs/team/.
_docs/team/
|- pm.md
|- software-engineer.md
|- qa-engineer.md
Role 1 — Product Manager (grooming)
Purpose: turn a rough task into something an engineer can implement without asking a single question.
Responsibilities:
- Read the issue as filed
- Rewrite it using a fixed 4-part template
- Make acceptance criteria checkable — something you can point at and call yes/no
- Surface edge cases the original filer missed
- Never write code
- If something doesn’t belong in this task, don’t silently drop it — spin it into a follow-up issue and note it under “out of scope”
Groomed task template (_docs/task-template.md):
- Goal — one or two sentences on what should be true afterward
- Acceptance criteria — checkable, one line per case, including awkward edge cases
- Out of scope — what this change must not do
- Constraints — files to stay inside, libraries to use or avoid, prior decisions to respect
Definition of done for grooming:
- All four sections filled in
- Every criterion is checkable by looking at the result
- Anything moved out of scope links to its own follow-up issue
- A different engineer, with zero prior context, could implement it from the issue alone
Grooming is the cheapest point in the whole pipeline to catch a misunderstanding — fixing a misread paragraph costs a sentence here; the same mistake found after implementation costs a rewrite, and found after release costs much more.
Role 2 — Software Engineer (implementation)
Purpose: implement exactly one groomed task.
Responsibilities:
- Implement what the issue describes — don’t rewrite the acceptance criteria
- Stay inside the named files and constraints
- Write tests for new behavior
- Commit regularly
- Leave the issue open (closing isn’t the engineer’s call)
- If a criterion turns out wrong, impossible, or self-contradictory, flag it in a comment rather than silently deviating
Definition of done:
- Every acceptance criterion is implemented
- New tests exist, and the full suite passes
- Work is committed
- Issue stays open, with a comment summarizing what was done
Frequent commits matter here: if the last commit was five minutes ago, discarding and rewinding a failed attempt is cheap; an hour old, and you’re re-doing real work.
Role 3 — QA Engineer (verification)
Purpose: independently check finished work against the original acceptance criteria — without touching the code.
This role exists because an agent asked “is this correct?” about its own work will tend to say yes, having missed the same edge cases the first time around.
Responsibilities:
- Read the acceptance criteria from the issue
- Check each one against what the code actually does, not what the engineer’s summary claims
- Run the tests and report exactly what was run
- Look for cases the criteria imply but the tests don’t cover
- Never fix anything — only report
Verdict format: PASS or FAIL, posted as an issue comment. A single failed criterion makes the whole verdict FAIL. Example shape:
QA: FAIL
- [x] Criterion A — PASS
- [ ] Criterion B — FAIL (describe what broke)
Tests: <command>, X passed, Y failed
Definition of done:
- The comment opens with PASS or FAIL
- Every criterion gets its own verdict
- Every FAIL states what was tried and what happened
- The test command and its result are included
- No code was changed
6. Loop Engineering
So far, every prompt has been typed by hand — three sessions per task. That’s the right way to learn the system, but it doesn’t scale across a large backlog.
Loop engineering is designing the harness that runs an agent repeatedly against a task, instead of you driving it prompt by prompt. The harness decides what the agent picks up next, checks the result, and decides whether to go again.
The critical requirement: the stop condition must be something a model can actually evaluate.
- ✅ “All tests pass” — checkable
- ✅ “No file in
src/costover 200 lines, tests stay green” — checkable - ❌ “Make the code better” — not checkable; the agent will either run forever or stop too early
If a coding tool doesn’t ship loop primitives natively, two ways to build them:
- Stop hooks — a hook fires when the agent finishes a turn, checks the condition, and re-prompts if unmet
- Scheduled pings — if the agent runs in a persistent terminal session (e.g., tmux), send it keystrokes on a timer
Set checkable goal (e.g. "all tests pass")
|
v
+-> Agent works
| |
| v
| Agent runs the suite
| |
| v
| Condition met?
| / \
| No Yes / turn limit hit
+---+ |
v
Stop
7. Graph Engineering
Even with three defined roles and a loop mechanism, someone still has to move work between the roles manually — reading the QA verdict and deciding whether it goes back to the engineer or the next task starts.
Graph engineering is structuring work across multiple specialized agents: defining what each one owns, what order work moves in, and how results get passed along. Any such workflow can be drawn as a graph — each agent is a node, each handoff is an edge.
(Note: this term surfaced publicly in mid-July 2026, shortly after “loop engineering” was coined — but the underlying idea, specialized workers passing structured handoffs, predates the label by a long way.)
The three-role process already built is, in effect, a small graph:
Groom (PM) --> Implement (Engineer) --> Test (QA) --> Done
^ |
+------- FAIL --------+
Three nodes, four edges — including the one that routes failed work back for another pass. Each node:
- Has a file defining what it does and doesn’t do
- Has its own definition of done
- Takes another node’s output as its input
- Hands off via the issue itself (not a conversation), so each role can run as an isolated session with full context
The Orchestrator
One piece is still missing: something that picks the next issue, dispatches each role in order, reads the verdict, and routes accordingly. That’s the main/orchestrator session — it dispatches roles as subagents but never grooms, implements, or tests itself.
Lifecycle (goes into process.md):
- Pick the next open issue from the backlog
- PM grooms it
- Engineer implements it
- QA verifies it
- On FAIL → back to step 3, with the QA comment as input
- On PASS → commit and close the issue
- Repeat until the backlog is empty
Ground rules:
- One issue at a time
- Never skip grooming, even for “obvious” tasks
- The engineer never closes the issue; QA never fixes code
- Never commit before tests pass
Orchestrator (main session)
|
v
Pick next open issue <-------------------+
| |
v |
PM grooms it |
| |
v |
Engineer implements it <---+ |
| | |
v | |
QA verifies it | |
| | |
FAIL | PASS | |
+------------------+ |
| |
v |
Commit + close issue ---------------------+
With all of this wired up, the entire system reduces to a single instruction:
/goal work through the backlog
The agent reads AGENTS.md, follows process.md, and dispatches the roles defined in _docs/team/ — every part of that one sentence maps back to something built earlier in this blueprint.
Quick-Reference Checklist
- Talk the idea through in a chat assistant → save spec as
plan.md -
git init, create_docs/, drop inplan.md - Agent proposes tech stack (no code yet)
- Agent drafts
tasks.md; you review and convert to issues - Task 1: empty project + one passing test
- Write
AGENTS.md(commands, rules, constraints, doc pointers) - Write
process.md, plus any recurring supporting docs - Write three role files:
pm.md,software-engineer.md,qa-engineer.md - Write
task-template.md(Goal / Acceptance criteria / Out of scope / Constraints) - Run Groom → Implement → Test manually a few times to validate the process
- Wire up a loop with a checkable stop condition
- Add the orchestrator lifecycle to
process.md - Run
/goal work through the backlog
Blueprint adapted from Alexey Grigorev’s “AI-Native Development: Specifications, Loop and Graph Engineering” (Part 1, AI Dev Tools Zoomcamp series, DataTalks.Club, July 2026). Original article: https://alexeyondata.substack.com/p/ai-native-development-specifications