Restructure a document — add a chapter, move a section, rewrite the whole thing
Hand this whole page to your agent. Copy it from your
Blenau dashboard and it arrives with
your workspace’s repos already in it; blenau playbooks install restructure-a-document
writes it straight into your agent’s instructions folder; or an agent connected
over MCP can fetch it itself with get_playbook("restructure-a-document").
There is no tool named “replace document” or “move section”, and that has misled agents into refusing work Blenau can do. Every structural change is one of the four moves below. If you are about to tell someone that a change needs editing the Markdown in GitHub by hand, read this first: it almost certainly does not.
Your workspace’s own values are not filled in here. Copy this playbook from your Blenau dashboard (or
blenau playbooks get <id>) and it arrives with your workspace slug and your connected repos already in it. Ask your agent to runlist_reposfirst if you are working from this generic copy.
The model you are editing
Section titled “The model you are editing”- The raw Markdown is canonical. Sections are addressed by their heading
text plus their occurrence (
position, 1-based), resolved against the raw at call time. A write splices the raw, so every byte outside the section you named is left exactly as it was — heading levels, code fences, whitespace. get_document(path)returns the whole raw Markdown. That is your starting point for anything that spans more than one section.- A table of contents is not special. It is a section like any other,
usually called
Contents. Reordering it means rewriting that one body. - Every write accepts
dry_run=trueand returns the unified diff without committing. Use it for anything structural, and read the diff before you repeat the call for real.
Move 1 — Rewrite one section’s body
Section titled “Move 1 — Rewrite one section’s body”edit_section(path, heading, new_content, expected_version, position=…)
Read it first with get_section, pass the version you got back as
expected_version, and send the body WITHOUT its heading line.
edit_section replaces a body and refuses a new_content that opens with a
different heading — that is a rename, and it has its own tool,
rename_section(path, heading, new_heading). The refusal is deliberate: a
rename smuggled through an edit orphans the old section and duplicates it.
Move 2 — Add a new chapter at the end
Section titled “Move 2 — Add a new chapter at the end”patch_section(path, heading=<the LAST section's heading>, content, op="append")
patch_section appends to a section’s body, and a new ## Chapter heading
inside that appended text becomes a new section of the document. So appending to
the last section is how a document grows at the bottom. Get the last heading
from get_document_structure(path) — it is the last entry.
If the new chapter belongs after some other section rather than at the very end, append to THAT section instead. The new heading ends the section you appended to, so the chapter lands between it and whatever followed.
Move 3 — Move a section somewhere else
Section titled “Move 3 — Move a section somewhere else”A move is a delete plus an insert, and it is the one case where you must carry the text yourself:
get_section(path, heading, position=…)— keep the content it returns. Itsversionis the lock for step 2, andpositionis what tells two sections with the same heading apart.delete_section(path, heading, expected_version, position=…)— splices it out, heading and all.patch_section(…, op="append")on the section it should now follow, with the text from step 1 (heading line included, so it stays a section).
Run step 2 and step 3 back to back. Between them the document is missing that section, and its readers see that state.
Moving a subsection (###, ####) moves only that block: sections run from
their own heading to the NEXT heading of any level, so a parent heading does not
carry its children along. To move a chapter with its subsections, take each
block in document order, or use Move 4.
Move 4 — Reorder or rewrite the whole document
Section titled “Move 4 — Reorder or rewrite the whole document”ingest_document(path, title, content) on a path that already exists replaces
that document completely. Same path, new content: this is the full-rewrite
tool, and it is how you reorder chapters wholesale or apply a restructuring that
touches everything at once.
The safe sequence, which is also the honest answer to “can you reorganize this document?”:
get_document(path)→ takeraw.- Rearrange that text locally. Keep the parts you are not moving byte-for-byte; you are restructuring, not rewriting prose nobody asked you to touch.
ingest_document(path, title, content, dry_run=true)→ read the diff. It tells you exactly what would leave the document.exists: truein the response confirms you are replacing, not creating.- Repeat without
dry_runonce the diff is what you meant.
Keep the title the document already has unless the human asked for a new one.
The failure mode to avoid: sending content you assembled from memory or from
a search result instead of from raw. A full replace cannot lose what it was
never given — and that is precisely why it is dangerous when the input is not
the document itself.
Before you say “Blenau cannot do this”
Section titled “Before you say “Blenau cannot do this””Check the request against the four moves above. The ones that have been refused wrongly, and what they actually are:
| The request | The move |
|---|---|
| ”Add a new chapter at the end” | Move 2 |
| ”Put this section after the appendix” | Move 3, or Move 4 for a whole chapter |
| ”Reorder the table of contents” | Move 1 on the Contents section |
| ”Reorganize the whole document” | Move 4 |
| ”Replace the document with this version” | Move 4 |
| ”Rename this heading” | rename_section |
| ”Delete this section” | delete_section |
What Blenau genuinely will not do for you: change a document you have no write
access to under its path, and rename a section through edit_section. Say that
plainly when it applies, and name the tool or the access that would.
Locking, and why a structural edit fails halfway
Section titled “Locking, and why a structural edit fails halfway”Every section write takes an optimistic lock. expected_version comes from the
version in get_section (or get_document_structure), and a stale one is
answered with error: "version_mismatch" and the current content — the write
did not happen. Re-read, reconcile, retry.
A sequence of writes on one document invalidates its own versions as it goes: every step changes the raw, so the versions you read at the start are stale by step two. Re-read right before each write, and never run two writes on the same document in parallel.