org.llm4s.agent.guardrails

Members list

Type members

Classlikes

class CompositeGuardrail[A](guardrails: Seq[Guardrail[A]], mode: ValidationMode) extends Guardrail[A]

Combines multiple guardrails with configurable validation mode.

Combines multiple guardrails with configurable validation mode.

Supports three modes:

  • All: All guardrails must pass (strictest)
  • Any: At least one guardrail must pass (OR logic)
  • First: First result wins (performance optimization)

Type parameters

A

The type of value to validate

Value parameters

guardrails

The guardrails to combine

mode

How to combine validation results

Attributes

Companion
object
Supertypes
trait Guardrail[A]
class Object
trait Matchable
class Any

Attributes

Companion
class
Supertypes
class Object
trait Matchable
class Any
Self type
trait Guardrail[A]

Base trait for all guardrails.

Base trait for all guardrails.

A guardrail is a pure function that validates a value of type A. Guardrails are used to validate inputs before agent processing and outputs before returning results to users.

Type parameters

A

The type of value to validate

Attributes

Supertypes
class Object
trait Matchable
class Any
Known subtypes
sealed trait GuardrailAction

Actions to take when a guardrail detects a violation.

Actions to take when a guardrail detects a violation.

Guardrails can be configured to respond to violations in different ways depending on the use case and severity of the detected issue.

Example usage:

// Block on prompt injection (security critical)
val injectionGuard = PromptInjectionDetector(onFail = GuardrailAction.Block)

// Fix PII by masking (privacy preserving)
val piiGuard = PIIDetector(onFail = GuardrailAction.Fix)

// Warn on low-severity issues (monitoring)
val lengthGuard = LengthCheck(1, 10000, onFail = GuardrailAction.Warn)

Attributes

Companion
object
Supertypes
class Object
trait Matchable
class Any
Known subtypes
object Block
object Fix
object Warn

Attributes

Companion
trait
Supertypes
trait Sum
trait Mirror
class Object
trait Matchable
class Any
Self type
sealed trait GuardrailResult[+A]

Result of a guardrail check with action handling.

Result of a guardrail check with action handling.

Extends the basic Result type with information about what action was taken and any warnings that were logged.

Attributes

Companion
object
Supertypes
class Object
trait Matchable
class Any
Known subtypes
class Blocked
class Fixed[A]
class Passed[A]
class Warned[A]

Attributes

Companion
trait
Supertypes
trait Sum
trait Mirror
class Object
trait Matchable
class Any
Self type
trait InputGuardrail extends Guardrail[String]

Validates user input before agent processing.

Validates user input before agent processing.

Input guardrails run BEFORE the LLM is called, validating:

  • User queries
  • System prompts
  • Tool arguments

Attributes

Companion
object
Supertypes
trait Guardrail[String]
class Object
trait Matchable
class Any
Known subtypes

Attributes

Companion
trait
Supertypes
class Object
trait Matchable
class Any
Self type

Base trait for LLM-based guardrails (the LLM-as-Judge pattern).

Base trait for LLM-based guardrails (the LLM-as-Judge pattern).

A judge guardrail asks a language model to rate the content against natural-language criteria and passes the content when the rating reaches a threshold. It suits subjective qualities (tone, factual support, safety in context) that deterministic rules cannot express. For plain word, pattern or length checks prefer the rule-based guardrails (ProfanityFilter, RegexValidator, PIIDetector, LengthCheck): they are free, instant and repeatable.

Side: output only. LLMGuardrail extends OutputGuardrail and not InputGuardrail, so it belongs in the output list of a GuardrailMiddleware, where it judges the agent's final answer.

What one validation does: exactly one synchronous llmClient.complete call, made on the calling thread even when the content is empty. The request holds two messages:

  • a fixed system message that asks for a bare number between 0 and 1;
  • a user message made of evaluationPrompt and the content between triple quotes.

Cost, latency and privacy: every validation adds one llmClient.complete call to the run. With a plain provider client that is one round trip and its token cost; a wrapping client changes the count - CachingLLMClient first embeds the system and user messages (an embedding request that sends the judged content to its embedding provider, hit or miss) and on a cache hit skips only the completion request, and ReliableClient can retry a failed request or reject the call with its circuit breaker open. Either way these guardrails do not belong on latency-sensitive paths. The content being judged is sent to whichever provider llmClient talks to, including any embedding provider a caching wrapper uses. A cheaper or separate model can serve as judge, which also avoids a model grading its own answer.

Scoring: a reply is a score only when the whole reply is one plain decimal number from 0 to 1, optionally labelled Score:, and the content passes when the score reaches threshold (a score equal to the threshold passes). Any other reply is refused as unreadable and fails the guardrail; a number is never clamped into range, because a clamped value would read as 1.0 for the usual mistakes (a 0 to 100 answer, a fraction, a percentage) and approve the content. The rules, in full:

  • Accepted: 0.9, .5, 0, 1, 1.0, with surrounding whitespace or a trailing newline, with markdown emphasis, quotes, brackets or code-fence backticks before or after the number (**0.9**, "0.9", ```0.9```), and with a Score: label in any case before it (Score: 0.9, score:0.9, **Score:** 0.9). The wrapping characters before and after the number are read independently and need not match or balance, so ((0.9 and 0.9 * are accepted too; they carry no meaning either way.
  • Refused, as unreadable: everything else. That includes a number outside 0 to 1 (85, 1.5); a sign, glued or apart (-0.5, - 1, negative 1, +0.5); a percentage, fraction, exponent or any scale, as a sign or in words (85%, 1 %, 1 percent, 1 per ten thousand, 100 bps, 8/10, 0.7 out of 1, 1e-3); a decimal comma (0,9); a trailing full stop (0.85.); any other label or sentence (Rating: 0.9, The score is 0.9, 0.9, because ...); more than one number; and a reply with no number. The grammar lists what is accepted rather than what is refused, so a scale or sign written in a form no one anticipated is refused too.
  • The edges of the grammar: the label is strict, so emphasis may wrap Score: as a whole (**Score:** 0.9) but not split it (**Score**: 0.9 is refused); a code fence is accepted only bare, so a fence with a language tag (text after the opening backticks, on the line before 0.7) is refused, the tag being a word the grammar does not admit; and the number is at most 64 characters, so a reply of thousands of digits is refused before it is parsed.
  • The score is compared at the precision the judge wrote it, and the threshold as the decimal it is written as: 1.0000000000000001 is out of range, and 0.79999999999999999 does not reach a threshold of 0.8, though both would round to the bound as a Double.
  • The judge is not asked to be lenient: the fixed system message asks for only a number between 0 and 1. Before this rule the reply was reduced to its digits and dots and clamped, so 85, 85%, 8/10, 1e-3 and 0,9 all read as 1.0 and passed any threshold up to 1.0, and 0.7 out of 1 read as 0.71.

Failures are always Left; an error never lets content through:

  • A threshold outside 0.0 to 1.0, or NaN: a org.llm4s.error.ValidationError on field threshold, before any judge call: LLM judge threshold must be between 0.0 and 1.0, got <value> for <name>.
  • Below the threshold: a ValidationError on field output whose message names this guardrail, the score and the threshold to two decimals: LLM judge score (0.40) below threshold (0.70) for <name>. It does not say why the judge scored the content low. Because of the rounding, a score of 0.69999 against a threshold of 0.7 reads 0.70 below 0.70.
  • An unreadable reply: a ValidationError on field llm_response that quotes the reply.
  • A failing llmClient.complete (network, rate limit, authentication): the client's own error, returned unchanged.

Inside an agent run a failing guardrail blocks the run: GuardrailMiddleware reports the name of the first failing guardrail together with the failure messages.

Limits: validate is not pure here, unlike the contract of Guardrail: it performs a network call, and the same content can score differently between calls (the default temperature of 0.0 reduces this but does not remove it). The content is inserted into the prompt as is, without escaping, so text inside it that addresses the judge can sway the score: treat the result as a probabilistic filter, not a security boundary. threshold must be between 0.0 and 1.0: any other value, or NaN, makes validate fail before the judge is called (see threshold). A threshold of 0.0 is accepted and passes every reply that parses as a score.

@note The default completionOptions cap the judge's reply at 10 tokens. Override them if your judge model needs more room than a bare number.

@example

class MyCustomLLMGuardrail(client: LLMClient) extends LLMGuardrail {
 val llmClient = client
 val evaluationPrompt = "Rate if this response is helpful (0-1)"
 override val threshold = 0.7
 val name = "HelpfulnessGuardrail"
}

Attributes

Companion
object
Supertypes
trait Guardrail[String]
class Object
trait Matchable
class Any
Known subtypes
object LLMGuardrail

Attributes

Companion
trait
Supertypes
class Object
trait Matchable
class Any
Self type
trait OutputGuardrail extends Guardrail[String]

Validates agent output before returning to user.

Validates agent output before returning to user.

Output guardrails run AFTER the LLM responds, validating:

  • Assistant messages
  • Tool results
  • Final responses

Attributes

Companion
object
Supertypes
trait Guardrail[String]
class Object
trait Matchable
class Any
Known subtypes

Attributes

Companion
trait
Supertypes
class Object
trait Matchable
class Any
Self type
sealed trait ValidationMode

Mode for combining multiple guardrails.

Mode for combining multiple guardrails.

Determines how validation results are combined when multiple guardrails are applied to the same value.

Attributes

Companion
object
Supertypes
class Object
trait Matchable
class Any
Known subtypes
object All
object Any
object First

Attributes

Companion
trait
Supertypes
trait Sum
trait Mirror
class Object
trait Matchable
class Any
Self type