Skip to course content
Free LLMOps course

LLMOps for Reliable AI Applications

Unit 10.00: Defining what must pass to ship

A gate names a metric, a bar, a comparison and a severity. Anything less is a suggestion.

Eight gates, seven of them blockers

Each row is machine-checkable, which is what lets it run in CI rather than in a meeting.

The code lists the full gate set.

GATES = [
    ("approval violations",   "count", 0,     "==", "blocker"),
    ("format failure rate",   "rate",  0.01,  "<=", "blocker"),
    ("correctness (40 cases)", "rate", 0.90,  ">=", "blocker"),
    ("grounding rate",        "rate",  0.95,  ">=", "blocker"),
    ("refusal accuracy",      "rate",  0.95,  ">=", "blocker"),
    ("p95 latency",           "ms",    2000,  "<=", "blocker"),
    ("cost per request",      "usd",   0.005, "<=", "warning"),
    ("newly broken cases",    "count", 0,     "==", "blocker"),
]
print(f"{'gate':26} {'kind':6} {'bar':>8} {'op':>3}  severity")
for name, kind, bar, op, severity in GATES:
    print(f"{name:26} {kind:6} {bar:>8} {op:>3}  {severity}")

blockers = sum(1 for *_, s in GATES if s == "blocker")
print(f"\n{blockers} blockers, {len(GATES) - blockers} warning")
print("every gate names a metric, a bar, a comparison and a severity")

# "Newly broken cases == 0" is the gate that catches the change that improves
# the average and breaks a case that used to work.

"Newly broken cases == 0" is the gate that catches what averages hide: a change that improves the overall score while breaking a case that used to work. Without it, every gate can pass on a release that made things worse for some users.

Cost is a warning rather than a blocker, which is a deliberate choice. A release that improves quality and costs slightly more should be a conversation, not an automatic block - and marking it as a warning is how you say that in the config rather than in someone's head.

The mistake this prevents

The mistake is setting every gate as a blocker because everything matters. A gate set with no warnings gets overridden routinely, and once overriding is routine the blockers stop meaning anything either.

Takeaway

Every gate needs a metric, bar, comparison and severity. Include newly-broken-cases at zero, and use warnings deliberately so blockers keep their force.