Blog / The ticket is the prompt: how to write tickets for AI coding agents

The ticket is the prompt: how to write tickets for AI coding agents

The Kevta team6 min read

Acceptance criteria were process theatre for twenty years because no human read them first. An agent does. How to write tickets for AI coding agents, and what to leave out.

Every ticket template you have ever used has a numbered list near the bottom. Acceptance criteria. In our experience nobody read it before starting. The developer read the title, asked whoever filed it a question in chat, and got on with it. The list existed for the ritual: the refinement meeting, and the person who would ask later whether this was really done.

That stopped being true the moment the work went to a machine. An agent reads the list, first and literally, and often reads nothing else. Which means writing tickets for AI coding agents is less a new discipline than the first time the old one has been load-bearing.

Who this is for, and what done looks like

This is for a small team running work through a coding agent and noticing the same thing twice: clean work on the ticket somebody wrote carefully, something adjacent-but-wrong on the one dashed off between meetings.

Done, here, is a ticket you can hand over without a follow-up conversation: the agent opens a pull request you review on its merits, not one you have to re-brief and run again.

The objection, which has a real edge

You could reasonably say specs are the wrong move entirely. Open the terminal, describe the change in a sentence, correct it twice, ship. For a one-file change that is faster, and nothing here applies.

The objection is sharper than it looks: a ticket written in advance is a guess about a codebase the agent is about to read more carefully than you have in a month, and a guess written as instructions can be worse than none.

It stops holding in two situations. The first is when the work outlives the session. Steve Yegge's argument for a structured tracker over a markdown plan is the clearest statement of why: "Markdown TODOs are fine for humans who can hold context across sessions and manually track dependencies. But agents have context limits, no persistent memory, and work best with structured data and explicit semantics" (steveyegge.spicytakes.org, November 2025). The second is when the person writing the ticket is not the person running the agent, which is most tickets on most teams.

What changes when you write tickets for AI coding agents

Three things.

The criteria became the plan. They used to be an audit performed at the end. Now they are the first thing read and the order in which the work happens.

Ambiguity stopped resolving itself. A developer handles an underspecified ticket by asking, or by already knowing. An agent handles it by choosing, silently, and you find out in the diff.

Length stopped being free. Manveer Chawla puts the constraint plainly: "The primary bottleneck in 2026 isn't code generation anymore. It's context injection" (manveerc.substack.com, January 2026). Every paragraph you add competes with the code the agent needs to read.

The shape

  1. Write the goal as an outcome. Johannes Millan's version is the one to steal: describe the measurable need — "keep p95 profile-page server response time below 300 ms" — rather than the solution (parallelcode.app, July 2026). An agent handed an instruction follows it past the point where it stops making sense.
  2. Give context by pointer, not by paste. Millan again: "Follow the validation pattern in src/routes/account/update-email.ts." Matt Pocock's handoff skill states the same rule as an absolute — "Anything captured in a spec, plan, ADR, issue, commit, or diff is referenced by path or URL, never copied" (aihero.dev). A path stays current. A pasted file is stale by Thursday.
  3. Make each criterion observable. "Handle errors gracefully" is not a criterion. "A revoked refresh token signs the user out instead of looping" is one, because you can watch it happen or fail to.
  4. Name the repo, the branch and the base. This is the part humans omit because they know it, and the part an agent cannot guess. If your tracker generates branch names off the issue key, use that one — the pull request then matches back to the issue with no linking step. The parsing rules are in a branch naming convention your tracker can parse.
  5. Write a done-when something can check. Chawla's ordering is right: "Formatting, linting, type-checking, and tests" run before a human looks at anything, and the human pass goes on business logic, edge cases and security (manveerc.substack.com).

Most of that is assembly, not writing

Read those back and notice how little is authorship. The goal is the title. The context is the description. The steps are the criteria you already wrote. The repo, the branch and the base are facts the tracker holds. Only the done-when needs a sentence of its own.

So we made it mechanical. Every issue with a key in Kevta carries an agent prompt, drafted from its own title, description and acceptance criteria, in a fixed shape:

## Goal
KEV-142 — Refresh the OAuth token before it expires

## Context
Sessions drop after an hour: the access token expires and nothing renews
it. The refresh token is already stored.

## Steps
1. Renew the access token in the background before it expires.
2. A tab left open overnight is still signed in the next morning.
3. A revoked refresh token signs the user out rather than looping.

## Repo
Repo: acme/web
Branch: feature/KEV-142-refresh-the-oauth-token-before-it-expires
Base: main

## Done when
Every step above holds, covered by tests, with the existing suite still green.

The criteria become the numbered steps. Kevta finds them two ways: under an "Acceptance criteria" heading, or as a trailing run of bullets at the end of the description. Everything above them is context. The repo, branch and base appear when the board is linked to a GitHub repository, and the branch is the one the Copy Branch Name button gives you. The done-when is one of two fixed sentences, picked by whether criteria were found at all.

Four honest limits. It is string assembly, not a model, so it cannot supply context you did not write, and a ticket with no criteria gets three generic steps that read like boilerplate — which is the ticket telling you something. An issue with no description gets no draft at all. Once someone edits the prompt by hand it is marked edited and never silently regenerated. And Kevta neither runs the agent nor reviews what it produces; an issue tracker for Claude Code covers what a board is for once a machine does the writing, and the task docs cover descriptions and criteria.

What to leave out

The file, when a path will do. The implementation, unless a constraint genuinely binds — protect the interface, not the variable names. And the conversation that produced the ticket, the largest and least useful thing you could paste. Pocock's framing of a good handoff holds here: the conversation "squeezed down to just its resumable core, so a fresh agent inherits the momentum, not the noise" (aihero.dev).

The uncomfortable part is that none of this is new. A ticket an agent can execute is a ticket a new contractor could execute on their first morning. Teams wrote the other kind for two decades without paying an obvious price. The price is obvious now, which is the only reason anyone will fix it.

If a tracker that drafts the hand-off for you sounds useful, Kevta is in beta and you can join the waitlist for an early invite.

Kevta is in beta