Skip to main content
Glama

PCD (Portable Context Deck)

Write Knowledge

write_knowledge

Create, revise, patch or supersede durable knowledge. Describe its required shape before composing.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
echoNoaction='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.
slugYesUnique slug for the record. Must match the category's slug_format (see manifest).
tagsNoTags as an array of strings — pass as JSON array ["a","b"] or comma-separated string.
titleNoRecord title. Required on create (validated against the category's template metadata); optional on update.
actionNoPre-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 — for a flow, its stage structure too — 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, flow). On immutable categories (decision, milestone) the patch reconstructs the successor and supersedes (returns action='superseded'); on mutable categories (manual, reference, note, flow) it edits in place (action='patched'); on a flow the stages are re-checked on the patched body first. Pre-flight with describe to fetch the current section_tree + hashes.
domainNoDomain — optional. If supplied, must be declared in the manifest's domains block.
statusNoStatus. 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.
patchesNoArray 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, flow). On immutable categories (decision, milestone) a patch reconstructs the successor and supersedes rather than editing in place.
summaryNoShort summary (used as the stage-1 search summary). Required on create per most category templates; optional on update.
audienceNoAudience — defaults to internal.
categoryNoCategory — must be declared in the manifest (note, decision, reference, manual, milestone, flow). 'knowledge' is reserved. Immutability + locking are derived from the manifest's transitions on promotion. A record never moves into or out of 'flow' — write a new record instead.
contractNoHelp mode — return the complete contract with no operation performed.
supersedeNoSupersession-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_idYesContainer ID — required. Scopes the record to the correct container.
raw_markdownNoFull 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_byNoUUID 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_hashNoOptional 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.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed3 schema fields changed
    • changedInput schema / properties / action / description
      Previous value: -"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."New value: +"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 — for a flow, its stage structure too — 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, flow). On immutable categories (decision, milestone) the patch reconstructs the successor and supersedes (returns action='superseded'); on mutable categories (manual, reference, note, flow) it edits in place (action='patched'); on a flow the stages are re-checked on the patched body first. Pre-flight with describe to fetch the current section_tree + hashes."
    • changedInput schema / properties / category / description
      Previous value: -"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."New value: +"Category — must be declared in the manifest (note, decision, reference, manual, milestone, flow). 'knowledge' is reserved. Immutability + locking are derived from the manifest's transitions on promotion. A record never moves into or out of 'flow' — write a new record instead."
    • changedInput schema / properties / patches / description
      Previous value: -"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."New value: +"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, flow). On immutable categories (decision, milestone) a patch reconstructs the successor and supersedes rather than editing in place."
  2. Changed2 schema fields changed
    • addedInput schema / additionalProperties
      Added value: +false
    • changedInput schema / properties / contract / description
      Previous value: -"Help mode — pass true to receive this tool's full _meta.contract (all variants) with NO operation performed."New value: +"Help mode — return the complete contract with no operation performed."
  3. First observed

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, destructiveHint=false, and openWorldHint=false, so the agent knows this mutates local state without external side effects. The description adds the describe-first workflow and the supersede verb, but says nothing about immutability, in-place vs supersession behavior, permission needs, or the rejection/validation model — all of which live only in the schema. Supersession retires a canonical record, which sits in mild tension with destructiveHint=false, though the record is preserved for restore_version, so this is not a clear contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, zero filler, with the verb set front-loaded before the workflow instruction. It is well-structured, though its extreme brevity is under-specification for a four-action, 17-parameter tool rather than model conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool of this complexity — four actions (describe/validate/write/patch), immutable vs mutable category behavior, supersession, and patch addressing — the description omits the action model, immutability consequences, and sibling routing entirely. The unusually rich schema compensates for most parameter-level gaps, but the description itself does little to orient an agent before it opens the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the schema documents all 17 parameters in exceptional detail (action semantics, patch ops, supersede vs superseded_by, expected hash concurrency). The description adds only the "describe the required shape first" hint and no parameter-level meaning beyond the schema, so baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names specific verbs (create, revise, patch, supersede) and the resource (durable knowledge), so an agent immediately knows this is the authoring/mutation entry point for the knowledge store. It does not differentiate itself from closest siblings such as manage_knowledge, update_deck, or restore_version, which leaves some ambiguity about scope among the write-family tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

"Describe its required shape before composing" gives one concrete workflow instruction (pre-flight with describe before authoring), which is genuine usage guidance. However, there is no statement of when to use this tool versus manage_knowledge/commit/restore_version, and no exclusions or prerequisites beyond that single hint.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources