Skip to main content
Sengol has three ways to act on a response at runtime. Pick by what you want to happen when a check fails. All three run deterministic evaluators only, synchronously, on the hot path. LLM judges belong in EvalSuite and the CI gate.

sengol.instrument()

  • Runs pre_evaluators on the prompt (default [PIIEvaluator()]). A CRITICAL failure blocks the call before it reaches the model.
  • Runs post_evaluators on the response (default none). Any failure blocks.
  • Raises BlockedError; read exc.failure_mode.
  • Runs observe_evaluators (default none) after post_evaluators on every call that gets a response. They must be DeterministicEvaluator instances with a declared version. Their scores go on the call’s record, never block, and never change overall_passed.
  • deployment_environment (or SENGOL_DEPLOYMENT_ENVIRONMENT) labels every record the process signs. It must match [a-z0-9_-]{1,40}.
  • Streams are buffered in full before the post-check runs.
  • If the appliance cannot accept the record, the call is refused with EVIDENCE_UNWRITABLE (on_evidence_failure="refuse", the default).
A full, runnable example is in the AI developer journey.

GuardrailRuntime

Wrap any function that takes a prompt and returns a response. The policy’s on_failure mode decides what the caller receives:
guard.py
retry does not withhold. When every retry fails, it returns the last failing response. Use block or fallback when the user must never see a failing answer. on_failure has no default, so you always choose.
Notes:
  • response="" is required on the input; the runtime fills it from your function.
  • Pre-evaluators score the input exactly as given. PIIEvaluator reads the response field, so put it in post_evaluators to check the agent’s answer.
  • A pre-evaluator failure under retry is treated as block.
  • Each call writes one record. Its last score, from GuardrailRuntime, names the outcome: GUARDRAIL_BLOCKED, FALLBACK_USED, RETRY_EXHAUSTED, or none when the response passed.

InlineEvaluator

Scores only. It never changes the response:
inline.py
InlineEvaluator refuses LLM evaluators. Its audit write is fire-and-forget on a running event loop; with no loop, as in this script, it is skipped. Use EvalSuite or GuardrailRuntime when every verdict must be recorded.