Worked example
Anatomy of an experiment
One prompt, 4 variants, 24 days, 12,048 judged events — and every decision in the order it was actually made. This is what running a prompt change as an experiment looks like from the inside.
This is our sample experiment, not a customer. LLMJury is in open beta and we are not going to invent a case study. Everything below is the read-only sample experiment that ships in every account — the same one behind the interactive demo and the screenshots on the home page. The numbers are illustrative; the procedure, the statistics, and the product behaviour are exactly what you get.
Start from a decision, not a hunch
The assistant that answers questions during checkout runs on one prompt, and the team disagreed about it. Half thought it was too long; someone had read that bulleted answers convert better; someone else wanted it friendlier. Three opinions, no evidence, and a decision that gets made either way.
The useful reframe is that a prompt change is a release. The question is not “which of these reads better?” — it is “which of these should the next 12,048 customers get?”, and that is a question with an answer.
Write the variants you would actually ship
4 arms: the prompt in production as the control, and one rewrite per argument. Not a grid of every phrasing — every extra arm splits the traffic, so an arm nobody would ship is a week of sample spent on nothing.
- control (detailed)control25% of traffic
You are a helpful checkout assistant. Answer thoroughly, covering shipping, returns, and payment options where relevant…
- concise25% of traffic
You are a checkout assistant. Answer in at most three sentences. Lead with the answer, then one line of context…
- bulleted25% of traffic
You are a checkout assistant. Answer as a short bulleted list, one fact per bullet, most important first…
- warm25% of traffic
You are a friendly checkout assistant. Acknowledge the concern before answering, and close by offering further help…
All four run the same model (claude-haiku-4-5) at the same settings, so the only thing that differs between arms is the words. If the model varied too, a difference could not be attributed to either.
Declare the metrics before the data arrives
4 metrics, each with its direction and its role fixed in advance. That ordering is the whole point: a metric chosen after the numbers are in is not a measurement, it is a story. One is primary — the thing the experiment is about — and the rest are guardrails that must not get worse.
| Metric | Role | Better is | Where it comes from |
|---|---|---|---|
| Answer quality | primary | higher | the judge, on a sample of answers |
| Conversion | secondary | higher | your application, one track call |
| Cost per answer | secondary | lower | the SDK wrapper, automatically |
| Response time | secondary | lower | the SDK wrapper, automatically |
Exactly one of these needs code from you. Quality is judged, cost and response time are intercepted by the wrapper, and conversion is the one only your application knows about.
Work out how much traffic the effect needs
The control scores 3.41 on answer quality. A rewrite worth shipping should move that by something like a fifth of a point — smaller than that and it is not worth the churn of changing a production prompt. At four arms and that effect size, the arithmetic lands around three thousand exposures per arm.
This step is the one teams skip, and skipping it is how an experiment ends in “it looks better but it is not significant yet” three weeks running. Required sample scales with the square of the effect you are chasing, so halving the effect you want to detect quadruples the wait. Deciding that before you start is what makes the end date real — the sample-size post has the tables.
Wire it up
Two lines on the request path. Assignment is a local hash, so nothing here adds latency or depends on us being reachable — and the in-code default is what your users get if we are not.
from llmjury import Client
client = Client(experiments=["checkout-assistant-prompt"])
llm = client.wrap(anthropic_client, "checkout-assistant-prompt")
# The assigned arm's prompt. Your current prompt is the fallback, so the first
# deploy of this line changes nothing about what anyone sees.
p = client.get_prompt("checkout-assistant-prompt", user_id,
default=CHECKOUT_PROMPT)
answer = llm.messages.create(
model="claude-haiku-4-5",
system=p.prompt,
messages=[{"role": "user", "content": question}],
)
# The one metric only your application can measure.
client.track("business_event", {
"experiment_id": "checkout-assistant-prompt", "user_id": user_id,
"variant": p.variant, "business_metric": "conversion", "value": 1,
})The same thing in TypeScript and Java is on the quickstart.
Wait, and do not peek
24 days, from 2026-06-09. By day three the concise arm was ahead on quality and it would have been very easy to call it — and that is exactly the mistake. Checking repeatedly and stopping the first time a number crosses 0.05 inflates the false-positive rate well past the 5% the number claims to describe. The result you get that way is the one you went looking for.
The permissible early stop is the opposite one: a guardrail moving badly enough that you would abandon the change regardless of what the primary metric does. Nothing did. When can you call it? is the longer version.
Check the split before reading the result
Configured at 25/25/25/25, observed at 3,012 / 3,012 / 3,012 / 3,012. The chi-squared sample-ratio-mismatch check returns p = 0.62, comfortably clear of the 0.001 gate, so the analysis runs.
Had it failed, LLMJury would have halted and told you, rather than showing a verdict built on a broken split. That is not a formality: a mismatch usually means assignment is broken or one arm is losing users before they are counted, and no amount of correct statistics downstream repairs it. See SRM.
Read the verdict
“concise” wins — better answers, cheaper, and it converts. 3 of 4 metrics moved significantly across 12,048 judged events. Every p-value below is corrected across all 12 comparisons in the experiment (4 metrics × 3 rewrites), because asking twelve questions and reporting the best answer is how a coincidence gets published.
| Metric | Change | 95% CI | p (FDR) | Verdict |
|---|---|---|---|---|
| Answer quality | +9.3%+0.317 | [0.261, 0.373] | < 0.001 | wins |
| Conversion | +5.2%+3.2 pp | [0.74, 5.66] pp | 0.030 | wins |
| Cost per answer | −12.4%−0.00051 USD | [−0.00067, −0.00035] USD | < 0.001 | wins |
| Response time | −2.8%−52 ms | [−97, −6] ms | 0.067 | no change |
The distribution says the same thing in a way an average cannot: 61% of concise’s judged answers scored 4 or 5, against 49% of the control’s. That is a real shift in the shape, not a mean dragged by a handful of outliers.
Look at what did not work
Two results here are more instructive than the win.
Response time did not survive correction. Concise is −52 ms faster with a raw p of 0.025 — significant, if you look at that metric alone. After correcting across all 12 comparisons it is 0.067, and the honest reading is “probably faster, not shown”. That is the difference between the number you would have reported and the number that is true, and it is the reason the roll-up says 3 of 4 rather than all four.
“warm” converted better without answering better. It moved conversion by +6.7% (0.005) while answer quality sat at +0.44% and did not clear significance at all. A single-metric experiment would have shipped it as a win, or as a failure, depending entirely on which metric someone happened to pick — which is the argument for declaring the whole set in step 3.
Ship it, and keep the record
Promote concise to control. No deploy: the prompt lives in LLMJury, so the change is a version pointer moving, and moving it back is the same click. The experiment keeps the version each arm ran, the configuration, the verdict, and who approved it — so the next time someone asks “why does the assistant answer like that?”, the answer is a link rather than a memory.
The warm result stays open as its own question: it converts, and nobody knows why, which is a better experiment than the one just finished.
Click through this one
Every number above is on the interactive demo, where you can open each metric, read every rewrite against the control, and see the score distribution — no sign-up.