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.
State the result and the limits
Section titled “State the result and the limits”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.
Set up Writ once
Section titled “Set up Writ once”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.
Write the task
Section titled “Write the task”Create bug-fixer.yaml in the project root:
writ: bug-fixermandate: "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? |
Check the task file
Section titled “Check the task file”Run this command before you spend model tokens:
writ check bug-fixer.yamlWrit prints this line when the file is valid:
bug-fixer.yaml: validThe check finds invalid fields, invalid values, and terms that Writ cannot apply in this mode.
Run the work
Section titled “Run the work”Run this command:
writ issue bug-fixer.yamlWrit 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.
Know the result
Section titled “Know the result”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 defaultcost $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 satisfiedThe final line means that the declared completion checks passed. It does not mean that Writ proved a result that the checks do not cover.
Review the run
Section titled “Review the run”Run this command:
writ review bug-fixerThe 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:
writ review bug-fixer --webWhat advanced mode adds
Section titled “What advanced mode adds”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.
Adapt this task
Section titled “Adapt this task”- 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.