Skip to content

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").

Download the raw Markdown


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 run list_repos first if you are working from this generic copy.

  • 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=true and returns the unified diff without committing. Use it for anything structural, and read the diff before you repeat the call for real.

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.

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.

A move is a delete plus an insert, and it is the one case where you must carry the text yourself:

  1. get_section(path, heading, position=…) — keep the content it returns. Its version is the lock for step 2, and position is what tells two sections with the same heading apart.
  2. delete_section(path, heading, expected_version, position=…) — splices it out, heading and all.
  3. 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?”:

  1. get_document(path) → take raw.
  2. 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.
  3. ingest_document(path, title, content, dry_run=true) → read the diff. It tells you exactly what would leave the document. exists: true in the response confirms you are replacing, not creating.
  4. Repeat without dry_run once 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 requestThe 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.