Skip to content

Cheat sheet — AI-Assisted Detection & Triage

Companion to Module 07 — AI-Assisted Detection & Triage · CC BY 4.0 — print it, pin it, share it.

Last reviewed: 2026-07

Using a model to triage alerts is only defensible if you've measured it against ground truth. This sheet is the scoring machinery: a labelled corpus, a confusion matrix, and a threshold gate.

The classification call (force a graded schema)

from anthropic import Anthropic
client = Anthropic()

def triage(alert):
    m = client.messages.create(
        model="claude-haiku-4-5-20251001",       # cheap + fast is right for high-volume triage
        max_tokens=256,
        tools=[{"name": "verdict", "description": "Triage verdict for one alert",
                "input_schema": {"type": "object", "properties": {
                    "label": {"type": "string", "enum": ["true_positive", "false_positive"]},
                    "confidence": {"type": "number"}},
                    "required": ["label", "confidence"]}}],
        tool_choice={"type": "tool", "name": "verdict"},
        messages=[{"role": "user", "content": alert}],
    )
    return next(b.input for b in m.content if b.type == "tool_use")

Confusion matrix + metrics (the scorecard)

                 predicted +    predicted -
   actual +          TP             FN         ← FN = missed real attack (the costly one)
   actual -          FP             TN         ← FP = analyst fatigue
precision = TP / (TP + FP)     # of alerts it flagged, how many were real
recall    = TP / (TP + FN)     # of real attacks, how many it caught  ← usually the one that matters
f1        = 2*precision*recall / (precision + recall)

Gate at a threshold

# only auto-close when the model is BOTH confident AND the class is cheap-to-be-wrong
if v["label"] == "false_positive" and v["confidence"] >= 0.95:
    auto_close(alert)          # everything else → human queue
else:
    escalate(alert)

Re-eval cadence

Alerts drift; models change. Re-run the scorecard on a fresh labelled sample on a schedule (and in CI on any prompt/model change) — a threshold that was safe last quarter may not be now.

Gotchas worth remembering

  • Recall is usually the metric that matters — a false negative is a missed breach. Tune the threshold to your cost asymmetry: auto-closing a real attack is far worse than queuing a false alarm.
  • Never let the model auto-action the costly direction. Auto-closing "false positives" at high confidence is defensible; auto-escalating or auto-blocking on a model call is not — gate it.
  • A score without a labelled set is theater. You cannot claim precision/recall without ground truth; building and maintaining the labelled corpus IS the work.
  • Confidence is not calibrated by default. A model's "0.95" isn't a real probability — validate that your threshold actually holds on held-out data, don't assume the number means what it says.
  • Class imbalance hides failure. If 99% of alerts are false positives, "always say FP" scores 99% accuracy and misses every attack — that's why you read the confusion matrix, not accuracy.

Comments

Sign in with GitHub to comment. Choose the type: Feedback (errors or suggestions on this page) · Hints (help for fellow learners — no spoilers) · General (anything else).