My first real attempt at agentic coding was the two-step version everyone recommends: plan and brainstorm with the agent, write a spec, then hand the whole spec back and let it execute. It never gave me results I wanted to keep. I’d end up throwing away entire implementations — not broken exactly, just off in ways that took longer to untangle than to rewrite from scratch. I tried several harnesses and both frontier and self-hosted models, and the pattern held regardless of which one was driving. Without something else constraining scope, I kept having to bolt guardrails onto CLAUDE.md/AGENTS.md just to stop the agent from wandering into files it had no business touching.

What actually fixed it wasn’t a better model or a sharper prompt — it was digesting the spec into tightly scoped tickets before an agent ever touched code. Instead of holding an entire feature in its head and improvising a path through it, the agent got one narrow task with exactly the context that task needed. It stopped trying to solve the whole problem and started solving the one in front of it, and the output got noticeably better. I’ve since checked this holds across setups that don’t share much else in common — Claude Code, and OpenCode driving Qwen3.6-27B on my own Blackwell box — and the pattern is consistent: tight scope beats a bigger, smarter model working off a loose brief.

Here’s the workflow that came out of that.


The Workflow Overview

[Idea / Feature Goal]
        │
        ▼
[1. Spec Preparation] ── (Collaborate with Agent) ──► Spec as Source of Truth
        │
        ▼
[2. Work Breakdown]   ── (Decompose via Agent)   ──► Jira Tickets (Atomic Scope)
        │
        ▼
[3. Agent Execution]  ── (Fed 1 Ticket + Spec)   ──► Isolated Code Changes
        │
        ▼
[4. Atomic PR]        ── (1 Ticket = 1 PR)       ──► Fast, Clean Code Review

Step 1: Establish Spec-Driven Development as the Foundation

Before writing a single line of code, write down the spec. It becomes the source of truth for the feature’s architecture, API contracts, edge cases, and data models — the thing every later step points back to instead of re-litigating.

Don’t write it alone. Feed the agent your raw requirements, constraints, and the existing codebase patterns it should follow, then work it like a brainstorming partner: ask it to poke holes, surface edge cases you didn’t think of, and call out architectural trade-offs or security implications. Once you’ve argued it out, have it draft the actual spec as a Markdown file (docs/specs/feature-x.md) covering system architecture and data flow, API/interface definitions, schema changes, and success criteria.

Commit that file. From here on, it’s the reference every ticket and every agent invocation points back to.


Step 2: Break Specs into Tightly Scoped Tickets

A common pitfall is handing an agent the entire 10-page spec and saying “build this.” Instead, use the agent to decompose the spec into linear, self-contained sub-tasks, and push each one into your tracking system (Jira, Linear, GitHub Issues) with a rigid scope.

The difference between a good and bad ticket comes down to how narrow it is:

  • Good: “Implement the DB migration and ORM models for User Preferences as defined in specs/user-prefs.md#schema.”
  • Bad: “Build the User Preferences backend.”

A ticket is agent-ready when it touches exactly one layer — a migration, or an API route, or a UI component, never several at once — when its acceptance criteria point at exact spec sections instead of paraphrasing them, and when the change can be verified on its own with a dedicated test.


Step 3: Drive the Agent with Single-Ticket Context

When it’s time to write code, treat the ticket as the agent’s entire mandate — nothing more. Whatever you’re driving it from (CLI, Cursor, the Claude API), restrict its focus to three things: the feature spec for context, the ticket’s acceptance criteria for scope, and the specific files this ticket touches.

claude -p "Implement only the acceptance criteria in JIRA-1024.
Use docs/specs/feature-x.md for architectural context.
Do not touch files outside this ticket's scope."

A narrower context produces sharper output — fewer hallucinations, and code that actually follows existing conventions instead of inventing its own.


Step 4: Generate the Atomic PR

With the task done, the agent opens a PR tied to that single ticket. Because the ticket was scoped tightly to begin with, the diff stays short — ideally under 200 lines — CI runs fast, a reviewer can hold the whole change in their head in under five minutes, and a revert (if it comes to that) is surgical instead of a multi-feature untangling job.

Merge, refresh your local branch, feed the agent the next ticket, repeat.


Why This Works

None of this makes the agent smarter — it’s a side effect of scope discipline. Treat the spec as the source of truth and the ticket as the agent’s execution boundary, and the sprawling-PR problem mostly goes away, because the agent never sees enough of the codebase at once to wander off scope. Reviewers look at one focused change instead of a multi-file overhaul. Progress against real tickets is easy to track. And when something does slip through, reverting one atomic PR doesn’t take unrelated work down with it.