The Chat assistant¶
The second view in whygraph serve is a chat assistant that answers questions about
your repo by calling WhyGraph's own tools. Ask "why does the rationale cache key on qualified name
instead of node id?" or "who has touched the scan crawler in the last year?" and it goes and looks
- reading rationale cards, walking evidence, querying the graph, running aggregate SQL, and drawing
charts from the results.
Every tool it calls is the same in-process function the MCP server or the Explorer already calls. There is no second implementation and no MCP roundtrip, so the assistant cannot drift from what your editor sees.
It costs money and it writes to your database
Unlike the Explorer, the assistant is not read-only. Every turn calls an LLM under your [chat]
provider, and every message, tool call, and session is stored in the WhyGraph database. It is
still loopback-only with no auth (see Localhost only).
Getting started¶
Run the server and switch to Chat in the header:
Pick a provider and model in the composer, type a question, and send. The first thing to know is that answers are grounded: when the assistant makes a claim it shows the tool calls behind it, and you can expand any of them to see what came back.
Symbols in an answer are links. The assistant writes them as whygraph://symbol/<qualified_name>,
and clicking one jumps to that symbol in the Explorer - graph recentered, detail panel open.
Providers¶
Chat needs streaming tool calls, which not every adapter supports. Four of WhyGraph's six LLM providers can drive it:
| Provider | Chat | Env var |
|---|---|---|
anthropic |
Yes | ANTHROPIC_API_KEY |
openai |
Yes | OPENAI_API_KEY |
deepseek |
Yes | DEEPSEEK_API_KEY |
openrouter |
Yes | OPENROUTER_API_KEY |
ollama |
No | - |
claude-cli |
No | - |
ollama is excluded because local models' tool-calling reliability varies too much to depend on;
claude-cli disables tools outright. Both still work for [analyze] and [rationale]. See
LLM providers.
Providers you haven't configured still appear in the picker, greyed out, labelled with the env var they need - so a missing key looks like a missing key rather than a missing feature.
The model list may fall back
The picker asks your provider for its live model list. If your API key is scoped narrowly it can
work for chat but return 401 on the models endpoint - in that case WhyGraph shows a short
built-in list instead. That is normal operation, not an error.
Choosing a default¶
whygraph init doesn't ask about chat - you pick a provider and model per session in the composer.
[chat] provider and model in whygraph.toml set the defaults for new sessions, and nothing
more: each session records the pair it was started with, so changing your config never rewrites an
existing conversation's history or re-answers it with a different model.
[chat]
provider = "anthropic"
# model = "claude-opus-4-7" # default: the provider's own [llm.*] model
If OpenRouter is your provider, pin a tool-capable model rather than leaving openrouter/auto -
automatic routing can land on a model that does not support tool calling.
Sessions¶
The left pane is your session list. Sessions are stored in the WhyGraph database alongside the evidence, so they survive restarts and are per-repo, not global.
- A new session is auto-titled from your first message.
- Sessions are deep-linkable at
/chat/<id>- copy the URL to come back to a conversation. - Rename and delete are in the session list.
What it can look at¶
Seventeen tools across five sources. You never call these directly; they are listed so you know what the assistant can and cannot reach.
-
Code structure (CodeGraph)
search_symbols,get_symbol,get_area_outline -
Evidence and rationale (WhyGraph)
get_rationale,get_evidence,get_area_history,find_changes,get_commit,get_pr,get_issue,get_repo_overview,list_recent_activity -
Statistics (aggregate SQL)
run_project_statsover commit history,run_graph_statsover the CodeGraph index -
Charts
render_chart -
Source tree
read_file,list_dir
Statistics are aggregate-only¶
The two *_stats tools let the assistant write its own SQL, which is why they are fenced hard. Every
query runs through a SQLite authorizer that permits read-only aggregates and nothing else, over an
explicit table allowlist. Results cap at 200 rows with a 5-second deadline.
The allowlist deliberately excludes chat_* (the assistant's own transcripts) and rationale_cache -
the assistant cannot query its own conversations, and coverage is reported through the proper tools
rather than by reading the cache table.
Reading files¶
read_file returns at most 400 lines or 100 KB per call, list_dir at most 200 entries, and
both refuse anything under .git/, .whygraph/, or .codegraph/, plus whygraph.toml itself - your
live config holds real API keys. WhyGraph's own storage is reachable only through the knowledge tools,
which present it in a curated shape instead of as raw database rows.
Charts¶
Ask for a chart and the assistant draws one from a statistics result - "chart commits per month for the last two years", "break down changes by author as a stacked bar".
Five kinds are available: line, bar, bar_h, bar_stacked, and bar_h_stacked. Stacked charts
carry at most six series.
Charts are drawn from data the assistant has already fetched, never from numbers it wrote itself.
A statistics tool mints an opaque reference for its result set, and render_chart can only point at
one of those references - so a chart is always a view onto real rows. References expire at the end of
the turn, and none is minted at all for an errored, truncated, or trivially short (fewer than two
rows) result, which is why the assistant will sometimes tell you there is nothing worth plotting.
Every chart ships with a Table toggle showing the underlying rows, and a PNG export.
Bounds on a turn¶
Tuned under [chat] in whygraph.toml:
| Key | Default | What it bounds |
|---|---|---|
max_tool_rounds |
8 |
Tool rounds per user turn. On the last round the assistant is called once more without tools, so a turn always ends in prose rather than mid-investigation. |
max_rationale_generations |
2 |
Uncached rationale cards one turn may generate. 0 makes the assistant cache-only. |
context_token_budget |
60000 |
Conversation history sent to the model. |
Two behaviours worth knowing:
- A failing tool never ends a turn. Errors come back to the model as results, so it can correct course and try something else. Individual results are truncated at 30 000 characters with an explicit marker.
- Rationale generated inside chat uses your
[rationale]provider, not the chat session's. That keeps the cache key identical to what the Explorer and the MCP tools produce, so a card generated from a conversation is the same card your editor gets.
When history outgrows context_token_budget, WhyGraph first elides stale tool results, then drops
whole turns from the top - never splitting a tool call from its result.
Limits¶
- One repo per server, the one you ran
whygraph servein. - No auth and no multi-user support; it is a local dev tool.
- The assistant cannot edit your code. It reads, queries, and charts.