← the shad0w blog

Adding a category without breaking production

A trained shortcut and a changing list of options are a dangerous mix. The rule shad0w follows, and what happens when you add, remove or rename an option.

Product adds a new intent, transfer, to the list your LLM chooses from. The LLM uses it from the first request. shad0w learns from your LLM's answers, so a shad0w trained last week on the old list cannot: it has never seen a transfer, so it picks its closest old label, sometimes with high confidence.

Before 0.3.1 we tested exactly this. More than half of the new option's messages went out with a wrong old label, marked certified. Every message about a removed option went out with the deleted label. The certificate was right about the world it was computed in. The world changed.

The rule#

From 0.3.1 on, shad0w compares the options you offer now with the options shad0w learned, on every load, and in the proxy on every request:

shad0w only answers with options it learned, from a list you still offer, under the certificate it was given.

adddefer everythingshad0w never learned it
removenever serve itthe rest keep serving
renameapplies at oncesame decisions, new name
retrainnew certificateserving resumes
intent = shad0w.decision("intent", options=["refund", "card_lost", "balance"], llm=...,
                         rename={"lost_card": "card_lost"})

Why not keep serving?#

You can: on_new_option = "serve". It is not the default because shad0w cannot tell you which of its answers were really about the new option, and those come back confident and wrong. A day of extra LLM calls costs money. Silent wrong answers cost trust.

The JavaScript package and the proxy follow the same rules. Changing your options covers merging, splitting and checking where you stand.

Upgrade: pip install -U shad0wllm · npm i shad0wllm@latest. The protection is on by default.
Try it on your own traffic.One line in front of the LLM you already call, or zero code with the proxy. pip install "shad0wllm[compile]"Start in 5 minutes →