An AI support agent that returns a reason code looks like it has done the hard part. It has not. The code is a label chosen by a language model, and language models are inconsistent about external label definitions: research on label receptivity found that models often fall back on their internal representations rather than the definitions you supplied, so the same situation can produce different labels across runs (Do LLMs Adhere to Label Definitions?). If your router trusts the label string on its own, that variance lands directly on your queues.
The second problem is that a code carries no signal about how sure the model was. A confident "wrong item" and a coin-flip guess between "wrong item" and "damaged on arrival" arrive in your system looking identical. Routing them to the same specialist queue wastes the specialist's time on the coin flip and hides the uncertainty from anyone looking at the queue.
The fix is to make the model emit two fields, not one: the code, and a confidence score you define and calibrate. Constrained decoding can guarantee the code comes from your published list, because grammar-constrained decoding masks out any token that would violate the schema (Structured Output and Constrained Decoding). What it cannot guarantee is that the code is semantically right, or that the confidence attached to it is meaningful. That is why the router reads both.
A useful framing: the code answers "which queue could handle this," and the confidence answers "is it safe to skip triage." You need both answers to assign work.



