Unit 17 · lesson

Specification-Driven Agent Work

A vague coding task gives an agent room to invent architecture, scope, and even the meaning of “done.”

Before a tool can act, write a task another developer could review.

A task specification has more than a goal

Weak:

Improve search.

Bounded:

TASK: add rank search

GOAL
Allow callers to find players whose rank matches a requested value.

CURRENT BEHAVIOR
Player objects already contain name, score, and rank.
search_by_name() exists in player.py.

REQUIREMENT
search_by_rank(players, rank) returns matching Player objects.
Match rank case-insensitively.
Return [] when there are no matches.

CONSTRAINTS
No new dependencies.
Do not change Player fields.
Do not weaken existing tests.

ALLOWED FILES
player.py
tests/test_player.py

VERIFICATION
normal match
case-insensitive match
no-match case
existing suite still passes

The task now defines behavior, protected boundaries, and evidence.

Agent Task Boundary
Agent Task Boundary

Diagrams open at a readable shape-aware scale. Zoom or expand when you need more detail.

Requirements describe behavior; implementation is usually negotiable

This is a requirement:

Rank matching is case-insensitive.

This is one implementation choice:

Call .casefold() on both values.

Do not prescribe implementation details unless the architecture or constraint genuinely requires them.

A specification should leave room for engineering while preventing the project from drifting away from the goal.

Require inspection before a plan

A strong agent workflow does not begin with editing.

Ask it to inspect the relevant context first:

Read player.py and tests/test_player.py.
Find the existing search behavior and current Player interface.
Do not edit files yet.
Report the current boundary and propose the smallest plan.

Then compare the plan with the repository yourself.

If it claims a function exists that you cannot find, stop.

If it proposes changing storage for a search function that only needs in-memory data, question the scope.

Review the plan before tools get write permission

Use a simple classification:

REQUIRED
SUPPORTING
UNNECESSARY
OUT OF SCOPE
DANGEROUS / NEEDS EXPLICIT APPROVAL

Example plan:

1. Inspect existing search helpers.                 REQUIRED
2. Add search_by_rank in player.py.                REQUIRED
3. Add boundary cases in tests/test_player.py.     REQUIRED
4. Rename Player.rank to tier across repository.   OUT OF SCOPE
5. Add fuzzy-search dependency.                    OUT OF SCOPE

Reject steps 4 and 5 before any patch exists.

Interactive model

Capability stops at the human approval gate

An agent may inspect and propose a plan, but permission to act is a separate decision. The rejection path remains visible because technical capability is not authority.

Drag nodes to inspect the relationships. Motion shows the active path; the plain background keeps attention on the relationships instead of graph-paper decoration.

View static diagramStatic coding agent plan approval gate

Establish a baseline without blindly staging everything

Before agent edits, inspect your working state:

git status
git diff

If the working tree is already dirty, do not automatically run:

git add .

That can mix unrelated or sensitive changes into a checkpoint.

Instead:

  1. identify which current changes are yours;
  2. finish and commit the coherent work, or deliberately preserve it using your approved workflow;
  3. verify which files should be clean before the agent task;
  4. run the relevant baseline tests; and
  5. record the baseline commit/state.

A checkpoint is useful only when you know what it contains.

Protect tests and requirements from goal hacking

If the task is “make the tests pass,” an agent could alter the tests.

Write protected behavior explicitly:

Existing tests are evidence of current requirements.
Do not modify or delete them unless the task explicitly identifies a requirement change.
New tests may be added for the new behavior.

That is not an absolute rule for all software development. Requirements sometimes change and tests must change with them.

The point is that a requirement change is a separate decision, not a convenient side effect of a failing test.

Define completion before execution

A useful Definition of Done might be:

DONE WHEN
- only allowed files changed;
- search_by_rank satisfies all three required cases;
- existing tests are unchanged and still pass;
- new tests pass;
- no dependencies/configuration changed;
- git diff contains no unrelated edits;
- implementation can be explained by the reviewer.

Now “done” means more than the agent reaching the end of its own loop.

Ask for evidence, then reproduce it

An agent report can include:

Files changed: player.py, tests/test_player.py
Tests: 18 passed
No dependencies added

Treat that as a useful index of claims.

Then independently check:

git status
git diff
python -m pytest

The report tells you where to look. It does not replace looking.

No-agent exercise

Use this supplied plan:

Task: add active-player filter.
Plan:
1. change player.py
2. add tests
3. update README
4. replace list return with generator everywhere for efficiency

Requirement:

filter_active(players) returns a list.
Allowed files: player.py and tests/test_player.py.

Classify every step.

Step 3 may be harmless but outside the allowed file boundary. Step 4 changes the return contract and creates unrelated migration work.

The correct review is allowed to say no to technically interesting changes.

Create your task card

Before Lesson 3, prepare one task card:

TASK NAME
GOAL
CURRENT STATE
REQUIREMENTS
CONSTRAINTS
ALLOWED FILES
PROTECTED FILES / BEHAVIOR
STOP CONDITIONS
VERIFICATION COMMANDS / CASES
DEFINITION OF DONE

If you cannot fill one of those sections, that is a useful signal that the task may not be ready for delegation.

Vocabulary lab

Flip the idea, not just the card

Explain the term before you reveal the back. Then compare your explanation with the definition, example, and warning.

1 / 5
Read all terms without animation
Agent Task Specification
A bounded development task defining goal, current state, requirements, constraints, permitted scope, verification, and completion criteria. Example: A rank-search task limited to player.py and its tests. Do not confuse it with: A vague command such as improve the project.
Protected Behavior
Existing behavior or evidence that the task is not authorized to change. Example: Current tests remain unchanged while a new search function is added. Do not confuse it with: Behavior explicitly being redesigned by a separately approved requirement change.
Baseline
The known repository and test state recorded before a bounded change begins. Example: Clean relevant files and 15 passing tests before the agent edit. Do not confuse it with: Blindly staging all working-tree changes.
Definition of Done
Observable conditions that must be satisfied before the task may be considered complete. Example: Allowed files only, required cases pass, no dependency changes, reviewable diff. Do not confuse it with: The agent saying it has completed the task.
Plan Review
Inspection and classification of proposed actions before they are executed. Example: Rejecting a repository-wide rename from a two-file feature plan. Do not confuse it with: Reviewing only after all changes have already happened.