Skip to main content

Command Palette

Search for a command to run...

The Ticket Is the Contract: Specifying Work for Coding Agents

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

Updated
•5 min read•View as Markdown
The Ticket Is the Contract: Specifying Work for Coding Agents
A
AI Architect. I design the boring control plane plumbing that keeps your impressive demos from quietly setting themselves on fire in production.

🗓️ 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:

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

  2. Anthropic on evaluating AI agents

Engineering With Coding Agents

Part 2 of 6

Four series of The Pragmatic Stack have explored the architecture and operation of LLM-powered systems: the discipline inside the agent, the systems around it, the operational practices that keep those systems running in production, and the .NET runtime used to implement them. All four series focused on systems that contain agents or agents that serve users. Series 5 examines a different kind of agent: one that opens your repository, understands your codebase, makes changes, and commits code. Coding agents are more than a new developer experience. They are a new actor in the software delivery system. Most delivery systems, including repositories, task backlogs, branching strategies, test suites, review processes, and deployment pipelines, were designed around human authors. Introducing automated authors changes the assumptions behind those systems. Some of those assumptions will need to evolve. Engineering With Coding Agents is a six article series focused on what needs to change and how engineering teams can adapt. This is the fifth series in The Pragmatic Stack. Series 1, Architecting Agents, covered the discipline inside an agent. Series 2, System Design, Reimagined, covered the systems around the agent. Series 3, Shipping AI Systems, covered how those systems are operated in production. Series 4, AI for the .NET Architect, covered what all of the above looks like in .NET. Series 5, Engineering With Coding Agents, covers what your software delivery system needs to handle agents as authors. What You Will Learn By the end of the series, you will have: A framework for making any repository legible to a coding agent without creating an extensive instruction manual. A task contract format that prevents vague intent from becoming production code faster than the team can identify and correct it. An isolation model for parallel coding agent work based on one branch, one worktree, and one environment per task. A six layer verification ladder that distinguishes software correctness from LLM benchmark performance. A code review approach designed for generated diffs at scale, with an emphasis on risk, provenance, and test evidence. A seven stage delivery loop that produces accepted, verified, and reviewable changes rather than raw generated output. The Articles 1. The Repository Is the Prompt: Preparing a Codebase for Coding Agents 2. The Ticket Is the Contract: Specifying Work for Coding Agents 3. One Agent, One Worktree: Isolation and Concurrency for Coding Agents 4. Tests Are the Verification Layer: Proving Agent Generated Changes 5. Reviewing Code Nobody Typed: Human Judgment in an Agentic Workflow 6. The Pull Request Is the Product: A Delivery System for Coding Agents Read the articles in order if you are building an agent ready delivery system from the ground up. If your organization has already begun adopting coding agents, start with the article that addresses the constraint you are currently encountering. The agent writes the code. The delivery system determines what reaches production.

Up next

The Pull Request Is the Product: A Delivery System for Coding Agents

Within a month there are several teams, several tools, several permission models, and several definitions of done. Management asks how much faster engineering has become. Nobody can say, but the token dashboard is exceptionally detailed.

More from this blog

T

The Pragmatic Stack

31 posts

The Pragmatic Stack is a no-nonsense engineering blog on AI, LLMs, agentic systems, .NET, and system design. I share practical patterns, hard-won lessons, and architecture insights from building real software. No hype. No fluff. Just engineering that ships.