Writing Work Orders for Agents

Agents cannot interpret vague tickets. Every ambiguity becomes a guess. Every guess is a potential failure.

The problem

A human reads "fix the auth bug" and infers: which service, which bug, what the expected behavior is, where to look, what "fixed" means. An agent reads the same ticket and has none of that context. It will either ask (wasting a round trip), guess (risking wrong work), or stall (wasting time).

Most tickets — Jira, Linear, GitHub Issues, internal trackers — are written for humans. They assume shared context, tribal knowledge, and the ability to ask clarifying questions at a desk. Agents have none of this. A ticket that works for a human team is often useless for an agent.

A vague ticket is not incomplete — it is unsafe for an agent to execute.

This is not an agent limitation. It is a contract failure. If the ticket is vague enough that an agent cannot execute it, it was vague enough that a new team member couldn't either — the existing team just compensated with context the ticket never captured.

What agents need in a work order

Nine fields. Not all are required for every ticket, but the more you provide, the less the agent guesses.

1. Repository — where the code lives

The agent needs to know where to work before anything else. A repo URL, a local path, or both. Without this, the agent cannot even start.

Repo: github.com/ppiankov/chainwatch
Local: ~/dev/ppiankov-github/chainwatch
Branch: main

For monorepos, include the subdirectory. For multi-repo changes, list all repos and which part of the change goes where.

2. Title — what, not how

Imperative, specific, bounded. The title should describe the outcome, not the process.

Bad

Good

3. Description — the full context

What is happening. What should be happening. When it started. What changed. Include error messages, log snippets, reproduction steps. The agent was not in the room when this broke — give it everything a new hire would need.

JWT refresh tokens issued after key rotation return 401.
Affects users whose tokens were issued before the rotation
at 2026-03-25 14:00 UTC. The /auth/refresh endpoint validates
against the new key but the token was signed with the old key.
Expected: refresh succeeds if the original token was valid at
time of issuance. Started after deploy abc1234.

4. Acceptance criteria — what "done" means

Explicit, testable conditions. Not "it works" — specific assertions the agent can verify.

Acceptance:
- Tokens issued before key rotation refresh successfully
- Tokens issued after rotation also refresh successfully
- Expired tokens (regardless of key) return 401
- Test covers both pre-rotation and post-rotation tokens
- No regression in existing auth_test.go

If the agent cannot verify "done" without asking a human, the acceptance criteria are incomplete.

5. Scope boundary — what NOT to touch

Same principle as SKILL.md "What this does NOT do." Tell the agent what is out of scope so it doesn't over-engineer or make collateral changes.

Scope:
- Fix the refresh validation only
- Do NOT refactor the auth middleware
- Do NOT change the key rotation schedule
- Do NOT modify the token issuance flow

6. Files and locations — where to look

Agents waste enormous token budgets searching for the right file. If you know where the problem is, say so.

Files:
- internal/auth/refresh.go (the validation logic)
- internal/auth/refresh_test.go (add test cases here)
- config/keys.go (key rotation config, read-only context)

7. Verification command — how to prove it works

A command the agent runs after making changes. If it passes, the work is done. If it fails, the work is not done. No interpretation needed.

Verify:
  go test -race -count=1 ./internal/auth/...

8. Priority and severity — how urgent, how broken

Not "high priority" — that means nothing to an agent. Use a scale it can act on.

Priority: P1 (production users affected, fix before next deploy)
Severity: degraded (auth works for new tokens, fails for pre-rotation)

9. Handover — what happens after done

The agent finished. Now what? If the ticket doesn't say, the agent will either stop and leave artifacts scattered, or guess what comes next. Define the exit path explicitly: what to commit, where to push, who to notify, what the next agent or human should pick up.

Handover:
- Commit with message: "fix: accept pre-rotation JWT tokens in refresh"
- Push to branch: fix/jwt-rotation
- Create PR against main
- Notify: #platform-oncall
- Next: reviewer approves PR, deploy pipeline handles the rest

For multi-agent workflows, handover is the link between agents. Agent A's handover becomes Agent B's starting context. If handover is vague, the chain breaks.

The complete example

Repo: github.com/ppiankov/authservice
Branch: main

Title: Fix JWT refresh returning 401 after token rotation

Description:
  JWT refresh tokens issued before key rotation at 2026-03-25
  14:00 UTC return 401 on /auth/refresh. The endpoint validates
  against the current key, but pre-rotation tokens were signed
  with the previous key. Started after deploy abc1234.

Acceptance:
  - Pre-rotation tokens refresh successfully
  - Post-rotation tokens refresh successfully
  - Expired tokens return 401 regardless of key
  - Tests cover both cases
  - No regression in auth_test.go

Scope:
  - Fix refresh validation only
  - Do NOT refactor auth middleware
  - Do NOT change key rotation schedule

Files:
  - internal/auth/refresh.go
  - internal/auth/refresh_test.go
  - config/keys.go (context only)

Verify:
  go test -race -count=1 ./internal/auth/...

Priority: P1
Severity: degraded

Handover:
  Commit, push to fix/jwt-rotation, create PR against main.
  Notify #platform-oncall. Reviewer approves, deploy pipeline
  handles the rest.

Why this works

Every field exists to eliminate a category of guessing:

The same principle as every other ANCC convention: collapse expensive exploration into cheap lookup. Tokens are decision receipts. A well-written work order is the cheapest way to reduce agent decision cost.

Common anti-patterns

For existing trackers

You don't need a new system. These fields map to what Jira, Linear, and GitHub Issues already support:

The structure is the same. The discipline is writing it explicitly instead of assuming the reader knows.

The rule

If an agent has to ask a clarifying question to start work, the ticket failed — not the agent. Write it once, write it completely, and the agent executes without a round trip.

Every ticket is a contract. Treat it like one.