Search

↑↓ to move↵ to openesc to closetop 6 documentation results

Book a demoTry TokenTriage

In development · Explore the product preview. Join the launch list or book a walkthrough.

Browse docs

What a new dashboard shows you

Before any traffic arrives, every screen has something to say. What an empty instance renders, measured on a real binary rather than the demo.

ExplanationLast updated

On this page

You have turned the dashboard on and pointed nothing at the proxy yet. Most products give you a blank grid here. This one has something to say on every screen, and what it says is designed to be checkable: it tells you what it looked at, how many rows that was, and what it therefore cannot claim.

That matters more than it sounds, because the failure it avoids is specific. A dashboard that paints sample data on an empty install teaches you to distrust every figure you see later. The screens below are captures from a genuinely empty ledger on a binary running from a config file, not from the demo, so what you see here is what you will see.

The Overview on an empty ledger

localhost:9090/ui/Empty ledger
The Overview surface on an empty instance. A banner reads: no data in the ledger yet, TokenTriage is waiting for your first request, with a Send your first request button. Spend to date and projected period-end both read UNPRICED rather than a dollar figure. Savings vs baseline reads: no verdict yet. Every panel carries a 0 rows chip, the charts say no series evaluated 0 rows, and the anomalies panel reports no anomalies detected with the parameters it used.The Overview surface on an empty instance. A banner reads: no data in the ledger yet, TokenTriage is waiting for your first request, with a Send your first request button. Spend to date and projected period-end both read UNPRICED rather than a dollar figure. Savings vs baseline reads: no verdict yet. Every panel carries a 0 rows chip, the charts say no series evaluated 0 rows, and the anomalies panel reports no anomalies detected with the parameters it used.
The Overview of a config-file instance with zero rows in its ledger. Nothing here is sample data: the ledger it read is empty.

Read it from the top. The banner states the situation in a sentence and offers the one action that changes it. The trust-ladder rail on the left shows three rungs with none of them claimed. Then the panels, and this is where the interesting decisions are.

Spend to date reads UNPRICED, not $0.00. Those are different claims. Zero dollars would assert that requests were priced and cost nothing. UNPRICED says no priced row exists to total. The same rule governs a populated instance where some models are missing from the price table, so you learn it here and it holds everywhere. Where a cost number comes from is the rule; this is the rule with no rows in it.

Savings vs baseline says there is no verdict yet, and names what would produce one: a graded shadow comparison. It does not show zero savings, because nothing has been measured.

Each panel carries its row count. 0 rows beside a chart, evaluated 0 rows inside it. On a populated instance the same chips carry the estimated and unpriced counts, so the count is not an empty-state affordance. It is the disclosure that is always there.

The anomaly panel publishes its parameters even with nothing to report. It names the detection method, the fields it is watching and the fields it is not, and the window it evaluated. “Nothing was found” and “nothing was examined” are different answers, and the panel distinguishes them.

The Live surface is the on-ramp

localhost:9090/ui/liveEmpty ledger
The Live surface on an empty instance, headed: waiting for your first request. A tabbed snippet picker offers env, wrap, curl, openai-python, openai-node, anthropic-python, and migration snippets from LiteLLM, Portkey, Helicone and OpenAI. The selected snippet sets the Anthropic base URL to this instance's proxy address. Below, a trust-ladder checklist shows ledger verified as satisfied and shadow running, verdict green and routing available as not yet met, each naming the endpoint it reads.The Live surface on an empty instance, headed: waiting for your first request. A tabbed snippet picker offers env, wrap, curl, openai-python, openai-node, anthropic-python, and migration snippets from LiteLLM, Portkey, Helicone and OpenAI. The selected snippet sets the Anthropic base URL to this instance's proxy address. Below, a trust-ladder checklist shows ledger verified as satisfied and shadow running, verdict green and routing available as not yet met, each naming the endpoint it reads.
The Live surface before the first request, on the same empty instance. The snippet carries this instance's own proxy address.

This is where a new instance points you, and it is the most useful screen on an empty dashboard. It carries a snippet picker with your instance’s own address already in it, in the shape your client uses, including the migration forms if you are coming from another gateway. Copy one, send a request, and the row appears on this screen as it is costed.

Under it sits the trust-ladder checklist, and each item names the endpoint it was computed from. “Ledger verified” is satisfied because the read model is reading your decision log. “Verdict green” is not, and it says why in the product’s own words: no graded rows under the current policy yet. That is the same gate Routing owns, rendered as a checklist rather than a refusal.

Get started’s first live request is the tutorial for that first call. This page is what the screen looks like while you make it.

What the other surfaces say with nothing to show

Each surface writes its own empty state, and they fall into three kinds. Telling them apart is the useful skill, because only one of the three is a problem.

Nothing has happened yet. The subsystem is on, it read your ledger, and there was nothing in it. Requests reports No rows match — evaluated 0 rows in scope. Pricing reports No unpriced rows — every logged row has a price, which is true of zero rows. Anomalies reports its scan with a population of zero.

The subsystem is off. The surface says so and names the setting. Cache says no cache is configured on this instance, so there is no hit rate or saving to show. Cost breakdown: Cost-optimization analytics is not enabled on this instance, so there is no breakdown to show — not an empty one. Set analytics.enabled: true (with analytics.rollups.enabled and dashboard.index.enabled) and restart. Governance and Calibration do the same. These surfaces are usually absent from your sidebar entirely; you reach this state by typing the URL.

Nothing could be read. Rarer, and the one worth acting on. The Realized surface makes the distinction explicitly: the applied-recommendation list could not be read from this instance, so no measurements are shown — this is a failed read, NOT a report that nothing has been applied. A failed read is not an empty result, and a surface that conflated them would be telling you a comfortable lie.

The empty state of every surface, as measured

Captured by walking each route on a run --config instance over a zero-row ledger.

Surface What it says
Overview banner offering the first request; UNPRICED spend; no savings verdict
Requests No rows match — evaluated 0 rows in scope
Traces No trace selected — open a request's trace from the Requests feed
Cost UNPRICED total; Excludes 0 unpriced rows from all totals; 0 rows are estimated
Reconcile No invoice has been imported on this instance yet, naming the accepted formats
Realized a failed read, distinguished from nothing having been applied
Providers one card per upstream, health unknown, no reference where no key env var is set
Pricing the active snapshot with its model count; 0 rows unpriced
Saved views three empty panels, each with its create form
Live the snippet picker and the trust-ladder checklist
Routing the ladder at Ledger; every quality source CANNOT_MEASURE, 0 / 8 labeled
Policy one blank rule, the emitted YAML, and the validate-diff-apply controls
Honesty Promote gate not satisfied, with the reason and the reproducing command
Calibration No calibration directory is wired on this engine
Anomalies the scan with its parameters and a population of zero
Budgets No budgets defined. Create one below
Fleet Single-node fleet — fleet not configured — showing the local instance only
Settings the running config, its generation number, and any config warnings

The Honesty surface also embeds a captured reference sample of eval output, labelled as one, so you can see the shape of a verdict before you can produce a verdict of your own.

Panels that are not yours

Four panels currently render a fixed example instead of your instance’s data, and two of them carry no watermark. This is a defect, it is filed, and until it is fixed you need to know which panels to disregard.

Where What it shows Marked as sample?
Cost, divergence panel at the bottom a cohort comparison over 812 rows, naming tenants acme and globex yes, DEMO DATA
Alerts, burn-alert backtest a replay over 128 records with rules that are not yours yes, DEMO DATA
Fleet, coverage of the last merged read Partial coverage — 2 of 3 replicas answered, listing tt-0, tt-1, tt-2 no
Governance · limits, preview and tenant panels a key vk_team_ml_01 under org:acme with dollar figures no

The rest of the dashboard does not behave this way, and it used to. Every per-surface data loader once fell back to the same sample corpus whenever a fetch failed, which meant one declined request could repaint a live instance with fabricated dollars. That was found, filed, and closed: the fallback is now compiled out of production builds, and a failed load degrades to an empty panel that discloses its own incompleteness. The four panels above sit outside that fix because they take their sample as a default value rather than as a fallback after a failed fetch.

How to check that what you see is yours

Two checks, both quick.

Look for the watermark and the mode chip. A demo instance labels itself in the header and puts a diagonal DEMO DATA watermark across every spend tile. If your header does not say demo and a panel does, that panel is one of the four above.

Ask the instance directly. The capabilities endpoint reports what the server thinks it is, and it needs no authentication:

$ curl -s http://127.0.0.1:9090/tt/api/v1/capabilities
{"api_version":2,"engine":{"version":"dev","mode":"ledger","pricing_snapshot":"litellm@2026-07-14#179affb"},"features":{"index":true,"stream":true,"control_plane":true,"replay":false,"budgets":{"defined":0,"enforce_granted":false},"alerts":false,"anomaly":true,...

That is the first 300 characters of a much longer document, from the same empty instance the captures came from. Two fields answer the question: demo is false further down, and a query returns a row count you can compare against:

$ curl -s -X POST http://127.0.0.1:9090/tt/api/v1/query \
    -H 'content-type: application/json' -d '{"metrics":["requests"]}'
{"provenance":{"pricing_snapshots":[],"rows":0,"estimated_rows":0,"unpriced_rows":0,"demo_rows":0,"truncated":false,"source":"scan","indexed_through":{"file":"","offset":0,"ts":""},"window":{"since":"","until":""}}}

rows: 0 with demo_rows: 0 and truncated: false is a successful read of an empty ledger. truncated: true would mean the read did not complete, which is the third case above.

What this page does not cover

It covers what an empty instance renders, not how to fill it. Your first live request is the tutorial that produces the first row, and the trust ladder explains the three rungs the checklist is tracking.