Chat (kb chat) — design and roadmap
This doc is the source of truth for how chat relates to kb query today and how we expect it
to grow. Update it when behavior changes.
Today: one dumb orchestrator, one “tool”
Chat is intentionally minimal:
- Resolve the turn — conversational mode may rewrite follow-ups into a standalone retrieval
query (
src/cli/chat-conversation.ts). - Graph expansion — same helpers as CLI query (
expandQueryWithGraph, relation block for the LLM prompt). - Run retrieval exactly like
kb query— both callrunQueryTruthRetrieval()insrc/cli/query-truth-retrieval.ts:runIntentLoop(samequery_truthenvelope the CLI builds after graph expansion and only optional--sessionrewrite — default CLI query uses the literal topic string, like chat) → router →read_facts(fact FTS + deepFactsQueryResearchOrchestratorwhen discovery is deep). No workspace markdown fallback.DefaultIntentRouterdefaultsquery_truthtodiscoveryDepth: 'deep'when--discoveryis omitted, so chat and CLI get the same research-style retrieval; chat passesdiscoveryDepth: 'deep'explicitly plus the chat retrieval limit. - Conversational answer — evidence from step 3 is passed to the chat system prompt + LLM
(
src/cli/chat-cli.ts,src/prompts/chat-system.md). - Orchestration output —
printReadDocumentsOrchestrationFooter()prints the same minimal wire rows askb queryhuman mode:retrieval>,matches>, then a singlesources>line with all hit titles (ids as fallback). With--debug/chat --debug, it instead prints one full provenancesource>line per document (same shape as legacy query output).summary>,status>, andconfidence>are only included when the user passed--verboseonkb chat(CLI) orchat --verbosein the TUI shell before the session starts; there is no mid-session toggle. Router fields likeexplanation/provenancestay onIntentResultfor JSON and telemetry but are not duplicated in the human footer by default.
query-session.json: only when kb query --session (not chat).
So today’s “orchestrator” is trivial: always call runQueryTruthRetrieval() (not a second
router shortcut), then the LLM, then the shared footer. Subprocess kb query is not spawned;
in-process reuse keeps config, base, and telemetry aligned.
Why not shell out to kb query?
Calling the CLI in a loop would duplicate process startup, env, base resolution, and error surfaces. The orchestrator module is the same contract as query without a fork/exec boundary.
Near future: richer chat orchestrator
The next step is a small turn router in front of the loop:
- Classify (rules + optional lightweight LLM): QUERY vs SUBMIT vs INVALIDATE vs DOCS vs GRAPH …
- QUERY → keep calling
runQueryTruthRetrieval()(viaexecuteChatQueryTruthRetrieval()’s thin envelope builder). - Other intents → dispatch to the same handlers the CLI already uses, then summarize for chat.
Principles:
- One owner per turn — pick an intent once, run it, render with shared printers.
- Reuse CLI intent paths — avoid a second implementation of query/submit/invalidate for chat.
- Orchestration lines stay wire-format —
key> valuerows only fromPrinter/ shared formatters so TUI and piped CLI stay consistent (src/ui/orchestration-meta.ts).
Historical note
Older revisions called read_documents directly from chat with hand-built inputs; that drifted
from kb query (different limits, router explanation / confidence not shown in the default human
footer, different augment order). The orchestrator + footer alignment fixes that; use --verbose
when you want those extra human rows to match an explicit kb query --verbose session.
See also
src/cli/query-truth-retrieval.ts— sharedrunQueryTruthRetrieval()for CLIkb queryand chatsrc/cli/chat-query-orchestrator.ts— builds chatquery_truthenvelope, delegates to shared retrievalsrc/cli/intent-cli.ts—printReadDocumentsOrchestrationFooter, augment helperssrc/intents/router.ts—query_truth→read_factsroutingsrc/core/TUI.md— TUI command surfacesrc/core/AGENT_LOOP.md— full intent loop (retries, escalation); chat may adopt more of this later for QUERY turns