A shadow test is an experiment, not a second API call. Before you write any harness code, write down the hypothesis: are you testing lower cost per resolved ticket, stricter JSON schema adherence, better handling of long documents, or a specific set of edge cases that the current model gets wrong? Yotta Labs' workflow makes the point that a vague "test the new model" is impossible to evaluate, and that you should decide upfront how you will judge the candidate.
Then capture the baseline. That means recording, for the current production model, the model identifier, the prompt template, system instructions, retrieval settings, temperature, output schema, timeout behavior and retry logic. If any of those change mid-test, the comparison stops being interpretable. This is the same discipline as regression testing for evolving LLM APIs: Ma, Yang and Kästner show that an API update changed which prompt was better by 8.7 percentage points of accuracy on a toxicity task, so prompt and model are a single unit of comparison, not two.
A useful baseline record looks like this:
{
"request_id": "req_8f21c",
"prompt_version": "support-v14",
"baseline_model": "current-production",
"candidate_model": "candidate-a",
"input": {"messages": [...], "retrieval_context": [...]},
"baseline": {"output": "...", "latency_ms": 1830, "input_tokens": 1240, "output_tokens": 310},
"candidate": {"output": "...", "latency_ms": 2410, "input_tokens": 1240, "output_tokens": 288}
}
Keep the schema stable for the whole run. If you add fields halfway through, you will be unable to compute a single pass rate across the full sample.



