Write Knowledge
write_knowledgeCreate, revise, patch or supersede durable knowledge. Describe its required shape before composing.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| echo | No | action='patch' only — opt-in post-write self-verification. When true, the response (patched AND supersede-by-delta) adds echo: [{ slug, header, level, hash, markdown }] with the post-write rendered section per touched node (paragraph ops echo their parent section); removals return { slug, removed: true }; rename_section returns the new slug + renamed_from. Default absent: response unchanged. Rejected on other actions. | |
| slug | Yes | Unique slug for the record. Must match the category's slug_format (see manifest). | |
| tags | No | Tags as an array of strings — pass as JSON array ["a","b"] or comma-separated string. | |
| title | No | Record title. Required on create (validated against the category's template metadata); optional on update. | |
| action | No | Pre-flight, pre-send check, full write, or partial patch. 'describe' returns the category contract + per-record state — no body required. 'validate' runs the exact write-path validation (slug format, status, immutability, template sections, metadata, summary max_length) on a candidate payload WITHOUT writing — returns { valid, missing_required[], over_cap: [{field, len, cap}] }; use it before committing a long compose so an over-cap field costs one cheap check, not a rejected write. Default 'write' commits in one call. 'patch' applies targeted section/paragraph edits to an existing record via `patches[]` without sending the whole body — supported on any category whose template declares a section_schema (all authored categories today: manual, reference, decision, milestone, note). On immutable categories (decision, milestone) the patch reconstructs the successor and supersedes (returns action='superseded'); on mutable categories (manual, reference, note) it edits in place (action='patched'). Pre-flight with describe to fetch the current section_tree + hashes. | |
| domain | No | Domain — optional. If supplied, must be declared in the manifest's domains block. | |
| status | No | Status. Must be one of: the category's default_status, 'draft', a declared live_state, or 'archived'. Transitioning into a live_state fires the manifest's on_promote side-effects. | |
| patches | No | Array of patch ops for action='patch'. Level-2 ops: replace_section / replace_section_intro / append_section / insert_section_after / remove_section. Level-3 ops: replace_paragraph / append_paragraph / insert_paragraph_after / prepend_paragraph / remove_paragraph. Both levels: rename_section — { section_slug, new_header, expected_hash? } renames a heading + its slug without resending the body; body and children untouched, child slugs cascade on a level-2 rename; required frame sections reject (REQUIRED_SECTION), slug collisions reject (DUPLICATE_HEADER). Section slugs are doc-local addressing, not a stable cross-doc contract — a rename that changes a slug raises a repair signal for cross-record references (warning in the response). Addressing: level-2 ops take section_slug=<bare slug> (insert_section_after takes after_section_slug). Level-3 ops take section_slug=<parent's BARE slug> PLUS the child's compound 'parent/child' slug in paragraph_slug (after_paragraph_slug for insert_paragraph_after) — never put the compound slug in section_slug (exception: rename_section on a level-3 child takes the compound slug directly in section_slug); append_paragraph / prepend_paragraph create a new child under section_slug=<parent> with the title in header. See section_tree.addressing in the describe response. Each op also carries content/header as applicable. content is BODY-ONLY: never include the section's '## …'/'### …' heading line — the heading is emitted from the slug (replace ops) or the header param (append/insert ops); a content opening with a heading line is rejected with HEADER_IN_CONTENT. Ops without a header param reject a stray header field (UNEXPECTED_HEADER) — renaming goes through rename_section, never a header on replace_section. replace_section_intro edits ONLY a level-2 section's own lead text and preserves its level-3 children — use it to fix a parent section's intro when it has subsections (replace_section refuses such a section with CHILDREN_PRESENT). replace_section / replace_section_intro / replace_paragraph / remove_paragraph / rename_section accept optional expected_hash for optimistic concurrency. Pass as JSON array; the worker also accepts a JSON-encoded string. Supported on any category whose template declares a section_schema (all authored categories today: manual, reference, decision, milestone, note). On immutable categories (decision, milestone) a patch reconstructs the successor and supersedes rather than editing in place. | |
| summary | No | Short summary (used as the stage-1 search summary). Required on create per most category templates; optional on update. | |
| audience | No | Audience — defaults to internal. | |
| category | No | Category — must be declared in the manifest (note, decision, reference, manual, milestone). 'knowledge' is reserved. Immutability + locking are derived from the manifest's transitions on promotion. | |
| contract | No | Help mode — return the complete contract with no operation performed. | |
| supersede | No | Supersession-with-shared-slug. When true, the call retires the canonical immutable record at this slug and atomically writes the successor in its place at the same slug. Required: full body fields for the successor (raw_markdown, title, summary, etc.) per the category template. The slug must already hold an immutable record; otherwise the call errors. Use this on a decision rewrite, not on a routine update. | |
| container_id | Yes | Container ID — required. Scopes the record to the correct container. | |
| raw_markdown | No | Full content in markdown. Validated against the category's template sections. Optional on update — omit to keep the existing body. Pre-flight with action="describe" to fetch the category-specific contract (slug format, required sections, metadata caps, on_promote effects) before composing. | |
| superseded_by | No | UUID of the record that supersedes this one. Sets the chain pointer on an immutable record (chain-pointer-only path; no body fields). For supersession-with-shared-slug — retiring an immutable record and writing its successor at the same canonical slug — use `supersede: true` with full body fields instead. | |
| expected_chapter_hash | No | Optional chapter-level hash for optimistic concurrency. If provided and the chapter has changed since you computed it, the patch is rejected with a re-read tip. Get the current value from describe response's section_tree.raw_chapter_hash. |