Skip to content

@InputGuardrail & @OutputGuardrail

@InputGuardrail and @OutputGuardrail ("@agboss/core") define boundary safety checks on @Application, @Workflow, @Agent, and @Router. Unlike @Judge (which retries an agent with feedback), a guardrail blocks execution immediately (GuardFailedError) when a message or reply violates the guardrail.

Both @InputGuardrail and @OutputGuardrail support two execution modes via decidedBy:

  • DecidedBy.Model (default): Evaluates a yes/no prompt against model (such as "typesafe/jev-1.13") and blocks when $P(\text{yes}) \ge \text{threshold}$.
  • DecidedBy.Code: Runs a deterministic check(text: string): Promise<GuardrailVerdict> | GuardrailVerdict method on your GuardrailHandler class with full DI (deps: [...]) at $0.00 LLM cost and 0 tokens (model, prompt, promptUrls, and threshold are forbidden).

Complete @InputGuardrail and @OutputGuardrail example

Section titled “Complete @InputGuardrail and @OutputGuardrail example”

What options do @InputGuardrail and @OutputGuardrail accept?

Section titled “What options do @InputGuardrail and @OutputGuardrail accept?”
Option / Interface Type Required Description
name string Yes Unique kebab-case identifier ending with -guardrail; the class name must end with Guardrail ([name.kind-suffix]).
description string Yes Non-empty summary of the safety rule.
decidedBy DecidedBy.Model | DecidedBy.Code No Execution mode (defaults to DecidedBy.Model).
prompt / promptUrls string / readonly string[] For DecidedBy.Model Yes/no safety question evaluated by the guardrail model ("yes" blocks). Forbidden on DecidedBy.Code.
threshold number For DecidedBy.Model Probability ceiling (0 < threshold <= 1); blocks when $P(\text{yes}) \ge \text{threshold}$. Forbidden on DecidedBy.Code.
model string For DecidedBy.Model* Decision model ("typesafe/jev-1.13") or chat model (*uses defaults.guardrail.model when omitted; never inherits defaults.router.model). Forbidden on DecidedBy.Code.
refusal string Either refusal or implements GuardrailRefusal Fixed refusal text returned when the guardrail blocks ([guardrail.refusal-twice] if both refusal and GuardrailRefusal are provided).
deps readonly Token[] No Constructor dependencies injected into GuardrailHandler and/or GuardrailRefusal.

GuardrailHandler & GuardrailVerdict (DecidedBy.Code)

Section titled “GuardrailHandler & GuardrailVerdict (DecidedBy.Code)”

When decidedBy: DecidedBy.Code is set, the guardrail class must implement GuardrailHandler ([guardrail.missing-handler]):

  • check(text: string): Promise<GuardrailVerdict> | GuardrailVerdict: Receives the PII-masked input or output string and returns GuardrailVerdict.passed() or GuardrailVerdict.blocked().
  • Nominal GuardrailVerdict: Plain { isBlocked: boolean } objects are rejected by TypeScript and at runtime; always construct verdicts via GuardrailVerdict.passed() (isBlocked: false) or GuardrailVerdict.blocked() (isBlocked: true).
  • Fail-closed & $0 cost: If check() throws, the runtime fails closed with GuardFailedError without calling the downstream LLM or leaking internal error strings into result.refusal. Observer events (GuardrailStartEvent / GuardrailEndEvent) fire identically for both modes, with cost: usd(0) on code guardrails.

Hierarchical inheritance (guardrails & excludeGuardrails)

Section titled “Hierarchical inheritance (guardrails & excludeGuardrails)”
  • Additive inheritance: Guardrails declared on @Application({ guardrails }), @Workflow({ guardrails }), and @Agent({ guardrails }) / @Router({ guardrails }) accumulate automatically.
  • Selective opt-out (excludeGuardrails): An individual @Agent or @Router can opt out of an inherited application or workflow guardrail via excludeGuardrails: [PrescriptionRequestGuardrail].