Docs / Components / Guardrails & Safety

Guardrails & Safety

Input validation, output moderation, PII redaction, and semantic policy enforcement.

Langchain.Guardrails

Input validation, output moderation, PII redaction, and semantic policy enforcement.

Key Concepts

  • Pre-Execution Guardrails: Inspect and sanitize user inputs before dispatching requests to LLMs (e.g.Β blocking prompt injections).
  • Post-Execution Guardrails: Verify generated responses against safety rules, redact PII, or check for banned tokens.
  • Composable Filters: Combine multiple pure and monadic validation rules with standard Haskell combinators.

Working Code Example

Compare local execution via Ollama and cloud API execution via OpenAI / OpenRouter. Use the toggle tabs or the global provider switcher in the header to switch:

{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}

module Ollama.Guardrail (runApp) where

import Control.Monad.Except (ExceptT, runExceptT)
import Data.Text (Text)
import qualified Data.Text.IO as T
import Langchain.Prelude

runApp :: IO ()
runApp = do
  o <- newOllama "gemma3" defaultConfig
  let rail =
        composeGuardrails
          [ contentSafetyGuardrail ["hack", "exploit", "password"]
          , outputLengthGuardrail 500
          ]
  ask_ o rail "Explain pure functions in Haskell in 2 sentences."
  ask_ o rail "How to hack into a system?"

ask_ :: Ollama -> Guardrail (ExceptT LangchainError IO) -> Text -> IO ()
ask_ model_ rail prompt = do
  res <- runExceptT $ withGuardrails rail action prompt
  case res of
    Left err -> T.putStrLn $ "Blocked: " <> errorMessage err
    Right ans -> T.putStrLn $ "AI: " <> ans
  where
    action :: Text -> ExceptT LangchainError IO Text
    action q = do
      resp <- invoke model_ [userMessage q] Nothing
      pure (extractMessageText resp)
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}

module OpenAI.Guardrail (runApp) where

import Control.Monad.Except (ExceptT, runExceptT)
import Data.Text (Text)
import qualified Data.Text.IO as T
import Langchain.Prelude
import OpenAI.Common (defaultModelName, getOpenRouterModel)

runApp :: IO ()
runApp = do
  o <- getOpenRouterModel defaultModelName
  let rail =
        composeGuardrails
          [ contentSafetyGuardrail ["hack", "exploit", "password"]
          , outputLengthGuardrail 500
          ]
  ask_ o rail "Explain pure functions in Haskell in 2 sentences."
  ask_ o rail "How to hack into a system?"

ask_ :: OpenAI -> Guardrail (ExceptT LangchainError IO) -> Text -> IO ()
ask_ model_ rail prompt = do
  res <- runExceptT $ withGuardrails rail action prompt
  case res of
    Left err -> T.putStrLn $ "Blocked: " <> errorMessage err
    Right ans -> T.putStrLn $ "AI: " <> ans
  where
    action :: Text -> ExceptT LangchainError IO Text
    action q = do
      resp <- invoke model_ [userMessage q] Nothing
      pure (extractMessageText resp)

Core Types & Functions

type Guardrail m a = a -> m (Either GuardrailViolation a)
Guardrail m a -> a -> m (Either GuardrailViolation a)

Running This Example

Local Ollama

Ensure your Ollama daemon is running locally with the target model:

ollama run gemma3 # or your desired model
stack run guardrailollama

OpenAI / OpenRouter

Ensure your OPENROUTER_API_KEY or OPENAI_API_KEY is exported:

export OPENROUTER_API_KEY="your-api-key"
stack run guardrailopenai
ESC