Interface GuardrailConfig

Configuration for guardrail evaluation behavior.

Controls when and how often guardrails evaluate content. Use these settings to balance safety requirements against performance and cost constraints.

Example

// Real-time PII redaction with rate limiting
const config: GuardrailConfig = {
evaluateStreamingChunks: true,
maxStreamingEvaluations: 50
};

// Cost-efficient final-only evaluation (default)
const config: GuardrailConfig = {
evaluateStreamingChunks: false
};
interface GuardrailConfig {
    evaluateStreamingChunks?: boolean;
    evaluateToolCalls?: boolean;
    maxStreamingEvaluations?: number;
    canSanitize?: boolean;
    timeoutMs?: number;
    failClosed?: boolean;
    streamingMode?: "per-chunk" | "sentence-buffered";
}

Properties

evaluateStreamingChunks?: boolean

Enable real-time evaluation of streaming chunks.

When true, also evaluates each TEXT_DELTA chunk during streaming. When false (default), evaluates only the output stream's chunks that carry isFinal: true (the FINAL_RESPONSE, an ERROR the turn yields), which every guardrail evaluates either way.

Performance Impact:

  • Streaming: Adds 1-500ms latency per TEXT_DELTA chunk
  • Final-only: Adds 1-500ms latency once per response

Cost Impact:

  • Streaming: May trigger LLM calls per chunk (expensive)
  • Final-only: Single evaluation per response (cost-efficient)

Use Cases:

  • Streaming (true): Real-time PII redaction, immediate blocking
  • Final-only (false): Policy checks needing full context, cost-sensitive

Default

false
evaluateToolCalls?: boolean

Evaluate the tool calls a turn requests.

When true, evaluateOutput also receives each TOOL_CALL_REQUEST chunk of a guarded output stream, as the stream carries it: chunk.toolCalls lists each call's id, name and parsed arguments. The verdict applies as it does to text:

  • BLOCK ends the stream with the guard's verdict (the error chunk, or the final response holding replacementText) in place of the chunk, so the stream never hands the host an actionable call (executionMode: 'external') to execute. AgentOS drops the pause the runtime saved for that call when the turn stopped for it: getPendingExternalToolRequest() no longer returns it, the conversation answers the call with a refused tool result, and the stream cannot be continued with a result for it. A block on a chunk that holds no actionable call (the chunk of calls the runtime runs itself, or a streamed delta) ends the stream while the turn goes on inside the runtime; when the turn then stops for calls the host runs, AgentOS drops that pause the same way once the turn ends, and until then the pause is neither offered nor resumed nor continued.
  • SANITIZE cannot rewrite a tool call; it is applied as a BLOCK that keeps the guard's reason and reason code.
  • FLAG and ALLOW pass the chunk on with the evaluation in its metadata.guardrail.output.

AgentOS also asks the guard about each call the runtime executes itself (executionMode: 'internal') before the call runs, as a TOOL_CALL_REQUEST chunk holding that one call, with the sources the turn retrieved in ragSources. A BLOCK (or a SANITIZE) refuses the call: the tool does not run, and the model receives a refused tool result (code AUTH_PERMISSION_DENIED), as it does for a permission refusal. When a model step asks for several such calls, each is judged before any of them runs, and the calls that pass alone are judged once more together, as the stream's chunk for the step holds them; a block there refuses each of them. The guard also judges the stream's chunk for the step, where a block ends the stream.

When false (default), the guard never receives a tool-call chunk. The flag is opt-in because a guard written for text may read any chunk it is given as text.

Default

false
maxStreamingEvaluations?: number

Maximum streaming evaluations per guarded stream (the turn's stream and each continuation stream after a tool result count on their own).

Rate-limits streaming evaluations to control cost and performance. Only applies when evaluateStreamingChunks is true. After reaching the limit, remaining chunks pass through unevaluated.

The output dispatcher counts evaluations per stream by the guardrail object's id property. Streaming sanitizers (canSanitize: true) that have no id share one count; give each of them an id.

Default

undefined (no limit)
canSanitize?: boolean

Whether this guardrail may return SANITIZE actions that modify content.

When true, this guardrail runs in Phase 1 (sequential) of the parallel dispatcher — it sees and can modify text produced by prior sanitizers. Each sanitizer receives the cumulative sanitized text from all preceding sanitizers in registration order.

When false or omitted, this guardrail runs in Phase 2 (parallel) on the already-sanitized text from Phase 1. It may return BLOCK, FLAG, or ALLOW. If a Phase 2 guardrail returns SANITIZE, the action is downgraded to FLAG with a warning logged, because concurrent sanitization would produce non-deterministic results.

Default

false
timeoutMs?: number

Maximum time in milliseconds to wait for this guardrail's evaluation.

If exceeded, the evaluation is abandoned (fail-open), a warning is logged, and the guardrail contributes nothing to the result. Prevents a slow guardrail (e.g., LLM-based) from blocking the entire pipeline.

Safety note: Do NOT set timeoutMs on safety-critical guardrails (e.g., CSAM detection, compliance-mandatory filters) because fail-open on timeout means content passes unchecked. Only use on guardrails where a missed evaluation is acceptable.

Default

undefined (no timeout — wait indefinitely)
failClosed?: boolean

Error/timeout posture for this guardrail.

When false (default), a guardrail that throws or times out is skipped (fail-open) and contributes nothing to the result — so unsafe content can pass if the guard errors. When true, a throw or timeout instead yields a synthetic BLOCK (fail-closed) so an erroring safety-critical guardrail never silently lets content through.

Default

false (fail-open — preserves prior behavior)
streamingMode?: "per-chunk" | "sentence-buffered"

Streaming evaluation mode, a declaration for the guardrail's own use.

The output dispatcher does not read this field: when evaluateStreamingChunks is true it passes each TEXT_DELTA to the guardrail on its own, whatever the value.

  • 'per-chunk' — the guardrail evaluates each TEXT_DELTA as it arrives.
  • 'sentence-buffered' — the guardrail buffers the deltas itself and evaluates whole sentences, for example with SentenceBoundaryBuffer, which also returns the previous sentence as overlap context.

Default

'per-chunk'