Primers
Writing a Ticket an Agent Can Finish Without You
The three things a written task needs before an AI agent can finish it without you: where the truth lives, what not to touch, and a finish condition someone else can check.
The one-line version
A ticket is a written task an agent works from without you in the room. An agent can finish one — not just produce something that looks responsive — only if someone else could check whether it’s done without asking the person who wrote it. That’s the whole test. What actually makes something an agent is that it acts on whatever it’s handed, which is why what it’s handed matters. A ticket that passes the test carries three things: where the truth lives, what’s off-limits, and a finish condition a stranger could verify.
The same request, two ways
Here’s a request written the way people write them: “Make the login page better.”
Here’s the same idea, written so an agent — or anyone else — could finish it:
“Fix the layout bug on the login page: the password field overlaps the error message below 400px of width. Work only inside LoginForm and its stylesheet (where both live); the signup form shares the same component but is out of scope. Done when the password field and the error text don’t overlap at any width from 320px to 1200px, and the existing login tests still pass.”
Same problem, three sentences longer, and the extra length is doing all the work. The first sentence is only the bug, described tightly enough that nobody has to ask which one. The middle sentence carries two ingredients: LoginForm and its stylesheet is where the truth lives, and the signup form is what’s off-limits. The last sentence is the finish condition — no overlap at any width from 320px to 1200px, checkable by resizing a browser, tests still passing besides.
The one that surprises people: non-goals
The line that gets skipped is the one that says what not to touch. It costs one sentence, and it buys two things: the diff stays where it belongs, and whoever reviews the result can say “that shouldn’t be in here” without arguing about what you meant. Picture a ticket that says “clean up error handling across the app” and nothing else — an agent working from that has no way to know if a three-file fix or a forty-file rewrite is in scope, and neither does whoever reviews it. The non-goals line answers that question before anyone has to ask it.
What it can’t do: substitute for a finish condition. “Don’t touch the payment code” bounds where the work happens. It doesn’t say when the work is finished. A finish condition you can’t test isn’t scope — it’s a hope.
How we write ours
Ours has four sections: Task, Context (where the truth lives), Definition of done (the finish condition, written so a stranger can check it), and Output. One real example, sanitized, from a ticket on the Wordy Royale codebase: “no credential enters the repo: roles are created against a throwaway container destroyed with the job; nothing is added to secrets; the test database URL stays exactly what it was.” It states what has to stay unchanged, not only what changes — specific enough that someone who didn’t write the code could check both halves.
The same discipline covers a stronger claim: “this fixes X” isn’t a finish condition unless it fails on the broken version first. One of ours found a proposed pass condition would have arrived by luck 47% of the time at the rate the un-fixed code was already failing — a coin flip, not a fix.
One piece needs a second person: the reviewer is kept blind to why the ticket asked what it asked.
One caution
Here’s where this usually goes wrong: a finish condition only the person who wrote it can check. “Make the login page look right” passes that test for exactly one reader — the one who knows what “right” means. The fix is one move: swap the feeling for something a stranger could observe — a width, a count, an error message, a command that exits zero instead of one.
Try it, then the next step
Try it on three lines from a made-up ticket:
- Source: the signup form’s validation rules live in
SignupForm. - Non-goal: don’t touch the login form.
- Done when: the email field rejects anything without an
@, and the error message looks better than before.
One of those three smuggles in something a stranger couldn’t check. Which line — and which half of it?
Source, non-goal, finish condition — copy that shape outright. The part that still needs a second person is the review: someone who wasn’t in the room for your reasoning, testing the file instead of trusting you. Run more than one agent and that job gets bigger fast — coordinating it is the next piece.