Personal research knowledge base: SQLite, hybrid search, an evidence-bearing graph, doors for people and models
Prax defines 10 tools with complete input schemas and descriptions. Naming is verb-forward (search, get, traverse, link, ask, promote, context, documents). Descriptions are detailed (100-400 chars) and explain WHAT, WHEN, and RETURN. However, parameter descriptions lack constraint details (enums, ranges, formats), output schemas are not formally documented, and error handling is minimal, the server proxies to a door and returns raw errors. No tool annotations (readOnlyHint, destructiveHint) despite clear read/write distinctions. Composition is sound: tools chain well (search→get_chunk→get), and the interface matches user intent (natural entity names, not opaque IDs). Missing: pagination guidance, per-item error reporting, and recovery hints.
The context for answering a question from the library: one numbered passage per document from the hybrid search (best chunk, with chunk and document ids) and what the graph records about those documents. Answer from it and cite passages as [n]; ``append_page`` keeps an answer worth keeping. ``answer=True`` also runs the door host's configured model and returns its answer with resolved citations: it surfs first — searches again, reads on, walks the graph, drops what is beside the point — for ``steps`` steps (the host's default; 0 is one shot, a local model then takes tens of seconds instead of a minute or two) and the result carries the ``trail``. ``doctype`` keeps pdf, web, image, text, note or page documents. ``history`` is the conversation so far as ``[{question, answer}, …]``: a follow-up ("and the second method?") searches in the earlier question's neighbourhood and the model sees the earlier turns.
What places a document (by id) or a page (by slug) in the library, compactly: its title and summary, the entities its edges point at, what it cites and what cites it, the nearest documents, the notes on it, and — for a project page — its members. Where ``search`` finds things, ``context`` says what the library already knows around one; a session on a project starts with ``context(slug="project/<name>")`. Follow an id with ``get`` or ``get_chunk``; a name with ``traverse``.
List documents with optional filtering by domain and tag
Fetch one document by id (ids come from search results). Text is windowed: ``text_len`` and ``truncated`` say whether more remains; call again with a larger ``offset`` to page.
Output schemas not formally documented. Tools return dicts but LLMs cannot see field types, required fields, or nested structure. Downstream tool chaining relies on implicit knowledge.
Parameter constraints missing. 'limit' has no min/max (search accepts 1 - 1000?). 'mode' in search should be enum(hybrid|fts|vec). 'confidence' in link should be enum(EXTRACTED|INFERRED|AMBIGUOUS). Free-form strings invite hallucinated values.
No tool annotations. 'link', 'set_domains', 'promote' are write operations but lack destructiveHint. 'search', 'get', 'traverse', 'ask', 'context', 'documents' are read-only but lack readOnlyHint. Agents cannot infer safety/idempotence.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 59 | 2026-07-28+ | v2 |
Fetch one chunk in full (ids come from search results). Returns its text, kind, heading path, locator (character range and page in the document) and, for tables, ``data`` with header and rows.
Add a graph edge between two entities (created if missing). ``confidence`` is EXTRACTED, INFERRED, or AMBIGUOUS.
Flag a document for the expensive model's pass (a richer extraction with claims and relations between methods) when it turned out to matter: cited in an answer, central to a question, worth a page. The pass itself runs later as a batch; this only queues.
Search the knowledge base. Returns compact snippets + ids. ``hybrid`` (default) fuses BM25 keyword search with vector similarity; ``fts`` or ``vec`` force one side. Each hit names its chunk ``kind`` (text, table, figure, code), section ``heading`` path and ``page``; a figure hit's ``figure`` is the reference of its image (the snippet is what a vision model saw in it). ``kind`` restricts to one kind, e.g. ``kind="table"`` for documents with a table about the query, ``kind="figure"`` for pictures. ``rerank=True`` rescores the top hits with a cross-encoder when one is configured. ``domain`` keeps the documents of one ontology module (``research``, ``studio``; documents without a domain set are in every module); ``doctype`` keeps pdf, web, image, text, note or page documents. Fetch a hit in full with ``get_chunk``.
Which ontology modules a document is read against (its domains, e.g. ["research"], ["family", "research"] for a document that is both, or null for every module). A document extracted afterwards, or in a re-run per domain, uses only those modules' types and relations; a change under an extraction makes it stale (``reread`` true in the answer): the worker's next extract pass reads the document again against the new set and retires the old reading.
Expand the knowledge graph 1-2 hops from a named entity.
Error handling is opaque. _guard() returns {error: str} but does not categorize as retryable/user-fixable/fatal. No recovery hints. 'the door is not reachable' tells agent nothing about next steps.
'ask' tool description mentions 'history' param but does not explain format or how follow-ups are resolved. Dependency on prior search context is implicit, not documented.