Files
Nicolò Boschi 4d22a882f5 docs(knowledge-pages): document Knowledge Pages and Mental Models, and manage them from the CLI (#3151)
* docs(knowledge-pages): document Knowledge Pages and Mental Models

Knowledge Pages shipped in #2455 with no documentation at all — no
architecture page, no API page, no mention in the sidebar. Mental models
had an API page but nothing explaining what they are or why they are
fast. Add both, as top-level entries under Architecture and API.

- Architecture: how pages are mental models with a simplified,
  document-shaped configuration; the folder hierarchy; the `hindsight fs`
  filesystem projection; page-level search; and why a projected view over
  reconciled memory is not the same thing as a folder of raw files.
- Architecture: mental models as standing answers built in the background,
  so an application reads the current version instead of paying for
  synthesis on the request path.
- API: the full knowledge-base endpoint surface, the page defaults and
  what each one buys, staleness gating, what a refresh reads, and how
  delta mode edits a structured document instead of regenerating prose.
  The mental-model trigger table gains the seven settings it was missing.
- FAQ: mental model vs knowledge page. Also corrects the neighbouring
  answer, which described mental models as built automatically during
  retain — that is observations.

The API examples use the maintained clients like every other API page, so
this adds the knowledge-base surface to the Python and TypeScript wrappers
(kept at parity, with request-mapping tests on both sides) and runnable
Python/Node/Go examples.

* feat(cli): manage knowledge pages from the CLI

The knowledge base was reachable from every client except the CLI, where
the eight endpoints were listed as deliberate coverage skips ("managed in
the control plane UI"). That left `hindsight fs` able to mirror pages
read-only but nothing able to create, edit, search, or delete them — and
it meant the API docs could not show a CLI tab alongside Python/Node/Go.

Adds `hindsight knowledge-base` with tree, create-folder, create-page,
get-page, search, update, delete, and export, removing the skips so
cli-coverage-check enforces the surface from here on.

`create-page` sends no trigger unless --mode or --fact-types is passed, so
the server's page defaults stand; when either is given the whole trigger
has to be restated, because a supplied trigger replaces the defaults
rather than merging with them.

Also adds the CLI tab to the Knowledge Pages API page and a Knowledge Base
section to the CLI reference.
2026-08-03 14:53:57 +02:00

111 lines
3.6 KiB
Python

#!/usr/bin/env python3
"""
Knowledge Pages API examples for Hindsight.
Run: python examples/api/knowledge-pages.py
"""
import os
import time
HINDSIGHT_URL = os.getenv("HINDSIGHT_API_URL", "http://localhost:8888")
BANK_ID = "knowledge-pages-demo-bank"
# =============================================================================
# Setup (not shown in docs)
# =============================================================================
from hindsight_client import Hindsight
client = Hindsight(base_url=HINDSIGHT_URL)
client.create_bank(bank_id=BANK_ID, name="Knowledge Pages Demo")
client.retain(bank_id=BANK_ID, content="The API is deployed to Kubernetes with a rolling update")
client.retain(bank_id=BANK_ID, content="Deploys run from the main branch after CI passes")
client.retain(bank_id=BANK_ID, content="A failed deploy is rolled back by redeploying the previous tag")
time.sleep(2)
# =============================================================================
# Doc Examples
# =============================================================================
# [docs:create-folder]
# Create a folder (omit parent_id, or pass None, to create it at the root)
folder = client.create_knowledge_folder(BANK_ID, name="Operations")
print(f"Folder ID: {folder.id}")
# [/docs:create-folder]
# [docs:create-page]
# Create a page — content is generated in the background
page = client.create_knowledge_page(
BANK_ID,
name="Deploying the API",
source_query="How is the API deployed?",
parent_id=folder.id,
tags=["ops", "type:runbook"],
)
# Poll the operation to know when the first build has finished
print(f"Page ID: {page.page_id}, operation: {page.operation_id}")
# [/docs:create-page]
# Wait for the page's first build
time.sleep(20)
# [docs:get-tree]
# Fetch the whole knowledge base as a nested folder/page tree (no page bodies)
tree = client.get_knowledge_base_tree(BANK_ID)
for root in tree.roots:
print(f"{root.kind}: {root.name}")
for child in root.children:
print(f" {child.kind}: {child.name} (stale: {child.is_stale})")
# [/docs:get-tree]
# [docs:get-page]
# Read a page as a markdown document
document = client.get_knowledge_page(BANK_ID, page.page_id)
print(document.type) # "runbook" — from the type:runbook tag
print(document.body) # the synthesized markdown body
print(document.markdown) # YAML frontmatter + body
# [/docs:get-page]
# [docs:search-pages]
# Hybrid search (full-text + vector) over whole pages
results = client.search_knowledge_base(BANK_ID, q="how do we deploy", limit=5)
for hit in results.results:
print(f"{hit.score:.3f} {hit.name}: {hit.snippet}")
# [/docs:search-pages]
# [docs:update-node]
# Rename a node, move it, and/or update a page's options.
# Changing source_query rebuilds the page against the new question.
client.update_knowledge_node(
BANK_ID,
page.page_id,
name="Deploying the API (v2)",
tags=["ops", "type:runbook", "reviewed"],
)
# [/docs:update-node]
# [docs:export]
# Export the knowledge base as a portable markdown bundle
bundle = client.export_knowledge_base(BANK_ID)
for file in bundle.files:
print(file.path) # index.md, <page-id>.md, <page-id>.log.md
# [/docs:export]
# [docs:delete-node]
# Delete a folder or page — deleting a folder removes its whole subtree
client.delete_knowledge_node(BANK_ID, folder.id)
# [/docs:delete-node]
# =============================================================================
# Cleanup (not shown in docs)
# =============================================================================
client.delete_bank(bank_id=BANK_ID)
print("knowledge-pages.py: All examples passed")