Skip to content

Knowledge vs custom pages

What this is

ComStack has two editable page types behind the MCP tools, and picking the wrong editor is the most common first-run mistake. This page explains how the server classifies a page as knowledge or custom, which tool edits each, and the guardrails that refuse a cross-type edit. (There is a third surface — the live voice agent — but it is not edited as a page.)

How it works

Every document exposes a page_type of knowledge or custom, returned on each get-project-state live/draft entry and on get-page-content. The server derives it — you never set page_type directly:

  • custom when metadata.type is "custom" or the document uses the custom-page template.
  • knowledge otherwise (the default).

The type maps one-to-one to an editor:

page_typeWhat it isEdit withBody shape
knowledgeMarkdown on a structured template (docs, blog, product, FAQ…)create-page / update-pageMarkdown in content
customVibe-coded Astro/HTML with full layout freedomupload-custom-pageOpaque body_source + <T> / data-t-key markers

The guard is fail-closed in both directions:

  • update-page on a custom page is rejected: ”… is a CUSTOM page (metadata.type=“custom”). Edit it with upload-custom-page (body_source + <T key=…> markers), not update-page. update-page edits knowledge (markdown) pages only.”
  • upload-custom-page on a knowledge page is rejected with error code wrong_tool_knowledge_page: ”… is a KNOWLEDGE (markdown) page, not a custom page. upload-custom-page would overwrite its body with opaque body_source. Edit it with update-page, or pick a different slug for the custom page.”

So read page_type before you choose a tool.

When to use it

  • Deciding which tool edits an existing page you were handed by URL
  • Choosing a template for a new page (markdown structure vs total layout freedom)
  • Diagnosing a wrong_tool_* rejection

Page type vs template

page_type is coarse — it picks the editor. The doc template is fine-grained — it picks the fields and structure. A knowledge page still chooses a template (technical-doc-page, blog-post, solution-page, …), each with its own required metadata; a custom page always uses the custom-page template. List templates via get-project-state.available_doc_templates; inspect one with get-doc-template.

Example

get-page-content(project_id, slug: 'pricing', language: 'en')
-> { page_type: 'knowledge', path: '...', metadata: { ... }, content: '## ...' }
(knowledge -> markdown editor)
update-page(project_id, slug: 'pricing', content: '## ...') (accepted)
(the same call on a custom page is refused:)
update-page(project_id, slug: 'home-hero')
-> InvalidRequest: 'home-hero' is a CUSTOM page (metadata.type="custom").
Edit it with upload-custom-page ...

Common errors

  • update-page on a custom page — rejected with a redirect to upload-custom-page. Re-issue the edit as a custom-page upload, or confirm you meant a different page.
  • upload-custom-page on a knowledge page (wrong_tool_knowledge_page) — would overwrite markdown with opaque source. Use update-page, or pick a new slug for the custom page.
  • Assuming page_type is writable — it is derived from metadata.type / the template. To make a page custom, author it through upload-custom-page; you cannot flip an existing knowledge page by setting a field.

Last updated: