Skip to content

Fix a bug under limits

Basic use records the tool calls reported by an existing agent. Normal use limits those calls. Advanced use makes Writ run the model and tools under rules for one task.

Suppose one test fails. You want an agent to fix the source code. You do not want it to edit the tests. You also want a cost limit and proof that the fix works.

This page runs that task from start to finish.

The task has six rules:

Need Rule
Result Make tests/test_sync.py::test_retry pass.
Allowed reading Read and search the repository.
Allowed changes Edit files under src/**.
Protected files Do not change tests/**.
Limits Stop after 40 model turns, $2.50, 20 minutes, 5 files, or 200 changed lines.
Completion Run the failed test and the full test suite. Both commands must pass.

Writ gives these rules to the model. It checks each requested action before it runs the action. It counts model turns and cost. It checks the workspace after a tool changes it. It runs the completion commands before it accepts the work.

This mode needs a model and a sandbox. Set up advanced use once on each machine.

Basic and normal use through writ connect do not need a model configuration.

Create bug-fixer.yaml in the project root:

writ: bug-fixer
mandate: "Make tests/test_sync.py::test_retry pass without breaking other tests."
grants:
- read: { paths: ["**/*"] }
- search: { scope: repo }
- shell: { commands: ["pytest *", "git diff"] }
- edit: { paths: ["src/**"] }
bounds:
iterations: 40
cost: $2.50
wall_clock: 20m
edits: { max_files: 5, max_changed_lines: 200 }
invariants:
- { layer: letter, untouched: "tests/**" }
satisfaction:
all:
- { layer: letter, run: "pytest tests/test_sync.py::test_retry -x -q", exit: 0 }
- { layer: letter, run: "pytest -q", exit: 0 }
remedies:
on_bound_breach: { do: halt, inform: issuer }
on_invariant_breach: { do: revert, inform: holder, strikes: 3 }

Each section answers one question:

Section Question
mandate What result must the model produce?
grants Which actions may run?
bounds How much may the run use or change?
invariants What must remain unchanged?
satisfaction Which commands prove completion?
remedies What must Writ do after a rule fails?

Run this command before you spend model tokens:

Terminal window
writ check bug-fixer.yaml

Writ prints this line when the file is valid:

bug-fixer.yaml: valid

The check finds invalid fields, invalid values, and terms that Writ cannot apply in this mode.

Run this command:

Terminal window
writ issue bug-fixer.yaml

Writ now calls the configured model. The model selects each action. Writ checks and records the action before it runs the tool.

If the model requests an edit to tests/**, Writ stops that edit and tells the model which rule failed. The model can choose another action. The run continues while it remains within its limits.

The run can end in these ways:

Event Result
The model requests an action outside the grants. Writ stops the action and returns the failed rule to the model.
A protected file changes. Writ reverts the change and informs the model.
A turn, cost, time, file, or line limit is reached. Writ halts the run.
A completion command fails. Writ returns the failure to the model while the run has budget left.
Both completion commands pass. Writ marks the run as satisfied.

A completed run has output with this shape. The meter values depend on the run.

bug-fixer · satisfied · holder default
cost $0.84 / $2.50 · iterations 7 / 40 · wall clock 3m12s / 20m0s
...
✓ satisfaction pytest tests/test_sync.py::test_retry -x -q · exit 0
✓ satisfaction pytest -q · exit 0
✓ writ satisfied

The final line means that the declared completion checks passed. It does not mean that Writ proved a result that the checks do not cover.

Run this command:

Terminal window
writ review bug-fixer

The record shows:

  • Each model turn and its cost.
  • Each requested action and its arguments.
  • Each rule that Writ checked.
  • Each blocked action and the reason.
  • Each completion command and its result.
  • The final state of the run.

Open the same record in a browser when you need to inspect more lines:

Terminal window
writ review bug-fixer --web

With writ connect, the agent owns the model loop and tool execution. Writ sees the built-in, local MCP, remote MCP, and hosted events that the agent sends to its hook. Coverage differs by agent.

With writ issue, Writ runs the model loop and tools. It can count turns and cost, check managed workspace changes, apply run limits, and run completion commands.

Use the connected modes to record or limit reported tool calls. Use a writ when Writ must apply rules to the full run.

  • Change the result in the mandate.
  • Change the allowed actions in grants.
  • Change the spending and change limits in bounds.
  • Change protected files in invariants.
  • Change the proof of completion in satisfaction.