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: inform, 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 review 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: defaultOmitted bounds and managed defaults
Section titled “Omitted bounds and managed defaults”If you do not write a bound, the writ is authored-unbounded for that value. The omitted value is not a clause.
The managed writ issue adapter adds these operational limits to its model
loop when the writ omits them:
| Bound | Managed operational default |
|---|---|
bounds.iterations |
25 |
bounds.cost |
$1.00 |
bounds.wall_clock |
15m |
These values do not become authored clauses. There is no managed default for
bounds.edits.
Use --explain to see the authored terms:
writ check bug-fixer.yaml --explainUse writ plan to check whether one adapter can enforce each authored term.
Do not put secrets in a writ document. An attached activation stores the bound document in Writ state.
Reserved 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.