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

Explain a routing decision

Find the rule and inputs behind one routing decision, then diagnose why it behaved differently from what you expected.

How-to guideLast updated

On this page

Use policy explain when a request matches an unexpected rule or takes an unexpected route. The command shows the policy revision, the result, and the inputs used to reach it. You do not have to read the config and guess what happened.

The command reads an existing decision from the log. It does not send a request, change the policy, or affect traffic.

What you need

Gather these three things before you run the command.

You need Where to find it
one completed request any request already written to the decision ledger
its request id the x-tt-request-id response header; trace a request by id shows the other lookup paths
read access to the log the default is ~/.tokentriage/decisions.jsonl

You do not need the dashboard, a provider connection, or routing enforcement. policy explain works on a copied log and on rows recorded in ledger, shadow, or route mode.

Explain the request

Replace tt_simple below with your request id. The default log path is used when you omit --log.

$ tokentriage policy explain --req-id tt_simple
req_id:     tt_simple
policy_rev: 184bdaf
decision:   rule=simple-to-cheap tier=— upstream=—
path:       root → rules[simple-to-cheap]
trace:
  • rules[simple-to-cheap]       matched
      read signal.complexity = 0.21
      read $simple_cut = 0.35

This request matched simple-to-cheap because its complexity value, 0.21, was below the configured cutoff, 0.35. This example was recorded in ledger mode, so the policy match was recorded but no routing tier was applied. That is why tier and upstream are dashes.

If your log lives somewhere else, add its path:

$ tokentriage policy explain --req-id tt_simple --log ./decisions.jsonl

Read the result in four steps

Reading the fields in this order usually finds the surprise quickly.

  1. Confirm policy_rev. This short fingerprint identifies the policy that decided the row. If it does not match the config you are inspecting, you are looking at two different policy versions. tokentriage policy migrate --config ./tokentriage.yaml prints the config revision in its first comment.
  2. Read decision. This is the result: the rule, tier, upstream, and any model rewrite. A ledger row may show a rule with no tier because ledger mode observes without applying a routing target.
  3. Follow path. It lists the policy nodes that were visited, in order. The final entry is the node that produced the result.
  4. Inspect trace and read. trace says what each visited node did. Its read lines show the values that were present when a condition evaluated them.

The complete output for selectors, traffic splits, and cascades is in Routing explanation fields.

Diagnose a rule that did not match

A condition stops evaluating as soon as its result is known. For example, once the first part of an and expression is false, later parts are not read. Fewer read lines than conditions can therefore be expected.

A rule shown as skipped with why=when=false was evaluated and did not match. A rule missing from path and trace was not reached. Use How a routing decision is made to check the evaluation order.

Fix common problems

Start from the symptom in the output, then take the corresponding next step.

Symptom Likely cause What to do
request id is not found wrong log, incomplete request, or a damaged log line confirm the log path and request id; use Trace a request by id to locate the row
tier=— on a matched rule the row was recorded in ledger mode use the rule and reads to debug the policy; use shadow when you also need the proposed tier
(no explanation block …) an older or non-policy router wrote the row inspect the raw ledger row; newer policy-language decisions include an explanation
an expected rule is missing an earlier node ended the walk follow path from left to right and check the decision order
an expected read line is missing an earlier condition settled the result, or the value was absent check the preceding reads, then verify the signal, header, or state source
policy_rev is unfamiliar the request used a different config revision print the revision of the config you are inspecting and compare it with the row

explain skips a torn JSON line without printing a warning. If the request id and path are correct but the row is still not found, run report, eval, or calibrate against the log; those commands count damaged lines on standard error.

Use the same explanation elsewhere

The CLI renders the explanation stored on the decision row. The dashboard record drawer and GET /tt/api/v1/requests/{req_id} read that stored block too, although each surface presents it differently. There is no separate explain endpoint.

Use Preview a routing policy change when the next question is not why one request behaved that way, but how a draft would affect a whole log.