Structure
A writ is a YAML file. This page gives each field of the file.
A complete writ
Section titled “A complete writ”writ: bug-fixerholder: defaultmandate: "The failing test {failing_test} passes without breaking other tests."
grants: - read: { paths: ["**/*"] } - shell: { commands: ["pytest *", "git diff"] } - edit: { paths: ["src/**"] } - open_pr: { requires: assent }
bounds: iterations: 40 cost: $2.50 wall_clock: 20m edits: { max_files: 5, max_changed_lines: 200 }
invariants: - { layer: letter, no_edits_outside: ["src/**"] } - { layer: judgment, clause: "Changes stay minimal.", checkpoint: each_edit }
obligations: - { on: satisfaction, require: { run: "pytest -x -q", exit: 0 } }
satisfaction: all: - { layer: letter, run: "pytest {failing_test} -x -q", exit: 0 } - { layer: judgment, clause: "The diff addresses the cause, not the symptom." }
remedies: on_bound_breach: { do: halt, inform: issuer } on_invariant_breach: { do: revert, inform: holder, strikes: 3 }The fields
Section titled “The fields”| Field | Necessary | Purpose |
|---|---|---|
writ |
Yes | The name of the writ. |
mandate |
Yes | The goal, as a condition on the world. |
grants |
Yes | The actions that the agent can do. |
holder |
No | The name of the holder in the engagement configuration. |
bounds |
No | The quantity that the agent can spend. |
invariants |
No | The conditions that must stay true during the run. |
obligations |
No | The checks that must pass before satisfaction. |
satisfaction |
No | The proof that the work is complete. |
remedies |
No | The response to a breach. |
A writ file must contain writ, mandate, and grants. A writ file must not
contain other fields, because the schema refuses an unknown field.
The name of the writ. The record uses this name, and the writ record command
uses this name.
The name must start with a lowercase letter. After the first letter, the name can contain lowercase letters, numbers, and single hyphens.
writ: bug-fixerholder
Section titled “holder”The name of the holder in the engagement
configuration. The default value is default.
holder: defaultDefault values
Section titled “Default values”If you do not write a bound, the registrar applies a default value:
| Bound | Default value |
|---|---|
bounds.iterations |
25 |
bounds.cost |
$1.00 |
bounds.wall_clock |
15m |
There is no default for bounds.edits. If you do not write bounds.edits,
the registrar counts no limit on the number of files or lines.
To see each default value that applies to your file, use the --explain flag:
writ check bug-fixer.yaml --explainReserved fields
Section titled “Reserved fields”The schema accepts these four fields, but this runtime cannot run a writ that contains them:
issued_byrequiresyieldsholder_must
These fields belong to delegation, which is the procedure that lets a writ issue a weaker writ. Delegation ships in version 2.
The writ check command gives a warning for these fields. The writ issue
command stops with an error.
Schema
Section titled “Schema”The schema is https://writ.build/schema/writ-v0.schema.json. To get editor
completion and editor validation, name the schema in the file:
$schema: https://writ.build/schema/writ-v0.schema.jsonwrit: bug-fixerThe writ check command validates the file against the same schema. The
command needs no network connection.