# The Ticket Is the Contract: Specifying Work for Coding Agents

> 🗓️ **Last updated: August 2026**

The ticket says, "Improve the checkout flow." A coding agent changes validation, renames a response field, adds a dependency, and redesigns the error page. Every change is plausible. None can be confidently accepted because the requested outcome was never defined.

The team calls this agent unpredictability. The ticket was six words long.

Coding agents turn vague intent into code faster than most teams can discover that the intent was vague. The quality of the task contract therefore becomes a delivery constraint. A good contract does not prescribe every line. It defines the outcome, the permitted surface, the evidence of completion, and the limits within which engineering judgment may operate.

## From ticket to executable contract

A useful task contains six elements.

1. The observable outcome
2. The current behavior
3. The allowed change surface
4. The constraints that must remain true
5. The verification commands
6. The conditions that require escalation

Consider a stronger version of the checkout request:

```text
Outcome: Reject expired promotion codes before payment authorization.
Current behavior: Expired codes fail after payment authorization begins.
Scope: Checkout application service and its tests.
Constraints: Do not change the public CheckoutResponse schema.
Verification: Run the checkout unit and integration test suites.
Escalate: Stop if the payment provider contract must change.
```

The agent still chooses the implementation. The team has defined what success means and where independent judgment ends.

## Acceptance criteria must observe behavior

Avoid criteria that merely restate implementation wishes. "Use a validator" is not an outcome. "An expired code returns the existing invalid promotion response before any payment authorization call" can be tested.

Good criteria describe externally visible behavior, important invariants, and failure cases. They can be checked by tests, static analysis, contract comparison, or a human observing a defined result. This matters because an agent needs a stopping condition. Without one, it may stop when the code compiles or continue improving the neighborhood until the task becomes a renovation project.

## Control the change budget

State the expected surface of change. A small defect should not modify twelve projects without explanation. A migration may legitimately touch hundreds of files. The task should distinguish expected breadth from suspicious breadth.

Use a diff budget as a review signal, not an arbitrary line limit. Ask the agent to stop and report when it needs to change a public contract, add a production dependency, create a migration, weaken a test, or edit outside the named modules. These are architectural transitions. They deserve conscious acceptance rather than energetic autocomplete.

## Separate discovery from implementation

Some tickets contain unknowns that should be investigated before code changes begin. Create a discovery phase with a concrete output: relevant files, observed behavior, likely root cause, proposed change, affected contracts, and verification plan. Review that output for high risk work before authorizing implementation.

This is not mandatory ceremony for every typo. It is a way to spend human attention before the expensive decisions become a large diff. Teams already do this with design notes and technical spikes. The agent has not abolished planning. It has merely made skipping planning impressively fast.

## Make the environment part of the contract

A task is only verifiable in a stable environment. Record fixture assumptions, required services, feature flags, seed data, and commands. If a test is flaky, say so and fix it. Do not teach the agent to rerun a failing test until statistics become acceptance criteria.

Research benchmarks such as SWE-bench frame repository work as resolving real issues against tests in a defined environment. The broader lesson is more useful than any leaderboard score: task quality, environment stability, and verification quality are inseparable when judging coding work.

## Define escalation as success

An agent that stops at an unexpected boundary has behaved correctly. Write explicit escalation conditions and reward them operationally. Examples include ambiguous product behavior, contradictory tests, missing credentials, a suspected security issue, or a change requiring data loss.

If every escalation is treated as failure, the system will optimize for confident improvisation. Humans do this too, although we usually promote it under a different name.

## Failure modes

The first failure is solution shaped work: the ticket names a class and method but never defines the user outcome. The implementation can be completed exactly and still solve the wrong problem.

The second is hidden acceptance. A reviewer holds critical requirements in memory and reveals them after the pull request arrives. The agent cannot satisfy criteria it never received. Neither can a new engineer.

The third is self verification. The agent writes a test that matches its implementation and treats agreement between the two as independent evidence. Existing behavior, contract tests, and external acceptance criteria must anchor verification.

## The architect's checklist

1. Define an observable outcome and the current behavior.
2. State the permitted modules and protected contracts.
3. Supply exact verification commands and failure cases.
4. Identify changes that require approval before implementation continues.
5. Use a discovery phase for ambiguous or high risk work.
6. Treat a justified escalation as a correct result.

A task contract does not remove judgment. It gives judgment a boundary. That is useful for agents and mildly revolutionary for several backlog grooming meetings.

## Sources

1. [SWE-bench repository and benchmark documentation](https://github.com/SWE-bench/SWE-bench)
2. [Anthropic on evaluating AI agents](https://www.anthropic.com/engineering/demystifying-evals-for-ai-agents)

