Phase 19 · Lesson 85 of 85

Capstone 87 — End-to-End Safety Gate

Pre-gen, during-gen, post-gen. Three checkpoints, one verdict, an audit trail per request.

Lesson 85 of 85Build~90 minPython

Before this: Phase 18 safety lessons, Phase 19 Track A lessons 25 to 29

On this page

Problem

Lessons 82-86 in this track each shipped a single piece: a taxonomy, an input detector, an evaluation framework, an output classifier, a rules engine. A real safety gate has to compose the runtime pieces (the lesson 83 detector, the lesson 85 classifier, and the lesson 86 rules engine), run them at the right moment in the request lifecycle, decide what action to take when they disagree, and produce a trace a reviewer can read on Monday morning. The composition is the lesson.

The gate sits at three checkpoints. Pre-gen runs before the model is called: the detector from lesson 83 looks at the prompt and either passes it, blocks it outright (high-confidence attack), or attaches a flag for downstream layers to weigh. During-gen runs as the model emits tokens: a streaming filter buffers chunks and terminates the stream early if a forbidden phrase appears (prefix-injection survives this if the gate only looks post-hoc). Post-gen runs after the model finishes: the classifier router from lesson 85 and the rules engine from lesson 86 inspect the full output, the gate aggregates their verdicts with the pre-gen signal, and the gate applies a final action.

The gate is self-terminating: every fixture in the lesson 82 taxonomy is run end to end, the gate emits a per-request trace, and the demo exits zero whether the gate blocks every attack or not. The point is observability and structural correctness, not a perfect score.

Concept

Three checkpoints, one decision tree.

Diagram (opens full size)

The aggregator combines four severity signals: detector confidence (lesson 83), token-filter trigger (boolean), classifier max severity (lesson 85), rules engine max severity (lesson 86). The aggregation function is a deterministic table.

Signal state Action
detector confidence >= 0.85 on a non-benign category block before generation
any high severity block
any medium severity (detector confidence 0.5 to 0.85, or early stream termination) redact
any low severity (detector confidence below 0.5 on a non-benign category) warn
detector says benign and no other signal allow

Block returns a refusal. Redact ships the classifier-redacted text and applies the rules-engine fixer. Warn ships the original with a soft notice. Allow ships the original. Each request emits a RequestTrace with request_id, prompt, pre_gen (detector verdict), during_gen (token-filter trigger), post_gen (classifier action + rules report), final_action, final_output, and latency_ms.

The during-gen filter is a streaming abstraction. The mock LLM yields chunks (4 tokens each by default). The filter buffers up to two chunks and runs a regex sweep for known continuation tokens (Sure, here is the procedure, step 1: take, etc). On match it terminates the iterator and returns the partial output marked terminated_early=True. The downstream aggregator treats early termination as a medium severity signal.

The mock LLM has two behaviors keyed off the prompt: it refuses recognizable attacks (returns I cannot ...) and answers benign prompts (returns a generic helpful string). For a small subset of attacks (notably encoding tricks not caught by the input pipeline) it produces a partial harmful continuation that the during-gen filter is supposed to catch. This is intentional. The gate's value is in the layered defense; the demo shows the layers interact correctly.

safety-checkpoints

Build It

code/safety_gate.py defines the SafetyGate class. It imports the detector, classifier router, and rules engine from the prior lessons via relative file paths. code/mock_llm_stream.py defines a streaming mock LLM with three scripted personas (clean, attacker-honest, attacker-lazy). code/main.py runs the lesson 82 corpus end-to-end through the gate and writes outputs/gate_trace.json.

The demo runs all 50 taxonomy fixtures plus 10 benign prompts. The trace summary reports: blocks, redacts, warns, allows, early terminations, per-category outcome breakdown, and average latency. The numbers are not the point; the per-request trace is the point.

Use It

python3 main.py. The demo loads everything, runs end-to-end, prints the summary table, and writes the trace artifact. Exit code is zero. The demo is self-terminating in the literal sense: each request runs to completion or early termination and the gate moves to the next.

Ship It

outputs/skill-end-to-end-safety-gate.md documents the request lifecycle, the aggregation table, and the trace format. The gate's primary deliverable is the trace format and the composition logic, both of which a team can lift into their own backend.

Exercises

  1. Add a fifth checkpoint: a policy-check that runs against the original system prompt before pre-gen. It must reject prompts targeting a known internal tool name.
  2. Replace the deterministic aggregator with a weighted score: each signal contributes a 0-1 confidence and the gate trips at a threshold. Sweep the threshold and report the precision-recall trade-off on the lesson 82 corpus.
  3. Add an async streaming variant where during-gen runs in a thread; verify the latency impact stays within a 50ms budget.

Key Terms

Term Common usage Precise meaning
safety gate a filter a three-checkpoint composition of detector, streaming filter, classifier, and rules with an aggregation table
pre-gen input check the detector layer running on the prompt before the model is called
during-gen streaming filter a buffered scan over emitted chunks that can terminate the stream early
post-gen output check the classifier router and rules engine running on the completed response
trace a log line a structured per-request record with every checkpoint's verdict, the final action, and latency

Further Reading

The five preceding lessons in this track. The gate composes them; it does not add new safety primitives.

Check yourself

Quick quiz

  1. Where do the three checkpoints sit in the request lifecycle?

    1. All three run before the model is called
    2. Pre-gen runs on the prompt before the model, during-gen filters the stream, post-gen runs on the completed output
    3. Only post-gen runs; pre-gen and during-gen are aliases
    4. All three run after the model finishes
    Show the answer

    B. Pre-gen runs on the prompt before the model, during-gen filters the stream, post-gen runs on the completed output

  2. What is the goal of during-gen filtering?

    1. To increase token throughput
    2. To buffer chunks and terminate the stream early when a known harmful continuation appears, before the user sees it
    3. To replace the prompt with a refusal
    4. To translate the output to another language
    Show the answer

    B. To buffer chunks and terminate the stream early when a known harmful continuation appears, before the user sees it

  3. How does the aggregator decide the final action?

    1. By looking only at the rules engine
    2. By taking the maximum severity across detector, token-filter, classifier, and rules signals and mapping it to block, redact, warn, or allow
    3. By averaging the confidences of every signal
    4. By calling the model a second time
    Show the answer

    B. By taking the maximum severity across detector, token-filter, classifier, and rules signals and mapping it to block, redact, warn, or allow

  4. Why does the gate emit a structured RequestTrace per request?

    1. To slow the system down
    2. To replace logging
    3. To give a reviewer a per-checkpoint audit trail so a regression in any layer can be traced to the right module
    4. To replicate the trace into the prompt
    Show the answer

    C. To give a reviewer a per-checkpoint audit trail so a regression in any layer can be traced to the right module

  5. What happens when pre-gen confidence exceeds the block threshold?

    1. The model is still called for completeness
    2. The gate raises an exception
    3. The gate returns the policy refusal and skips during-gen and post-gen entirely
    4. The gate lowers the threshold and retries
    Show the answer

    C. The gate returns the policy refusal and skips during-gen and post-gen entirely

  6. Why does the demo intentionally let some encoding-trick prompts reach during-gen?

    1. Because encoding tricks are not real attacks
    2. Because the input pipeline does not always normalize them in time; the during-gen filter is the defense in depth that catches the leaked continuation
    3. Because the rules engine handles encoding
    4. Because the model refuses them anyway
    Show the answer

    B. Because the input pipeline does not always normalize them in time; the during-gen filter is the defense in depth that catches the leaked continuation

Questions people ask

What is an AI safety gate?

It is a layer that checks each request at several points: the input before the model runs, the output as it streams, and the final reply. It combines the results into one decision to allow, block or change the response, and logs it.

Why keep an audit log for AI responses?

A log of each request, the checks run and the decision helps teams investigate complaints, prove what happened, tune rules and spot attacks. It should avoid storing private data it does not need.

You reached the end of the courseBack to the coursePrevious: Capstone 86 — Constitutional Rules Engine

Lessons from AI Engineering from Scratch by Rohit Ghumare and contributors, MIT license. Notes for owners by Lozo. License

Next step

Rather have it built for you?

Reading is optional. Tell me what's stuck and I'll build it into the business you already run.

  • A real conversation, not a pitch
  • You keep your accounts
  • Nothing sends without your yes