> ## Documentation Index
> Fetch the complete documentation index at: https://docs.abv.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Guardrails Patterns

> Content validation, safety checks, and custom rules

<Info>
  Guardrails validate inputs and outputs to ensure safety, quality, and compliance. All guardrail calls are automatically traced.
</Info>

## Available Guardrails

| Guardrail         | Description                                          |
| ----------------- | ---------------------------------------------------- |
| `toxic_language`  | Detects harmful, offensive, or inappropriate content |
| `biased_language` | Identifies biased or discriminatory language         |
| `valid_json`      | Validates JSON format and optional schema            |
| `contains_string` | Checks for required or forbidden strings             |

***

## Toxic Language Detection

<Tabs>
  <Tab title="Python" icon="python">
    ```python theme={null}
    from abvdev import ABV

    abv = ABV(api_key="sk-abv-...")

    result = abv.guardrails.validate_toxic_language(
        text="You're doing a great job!",
        config={"sensitivity": "high"}  # high, medium, low
    )

    if result.status == "PASS":
        print("Content is safe")
    else:
        print(f"Blocked: {result.reason} (confidence: {result.confidence})")
    ```
  </Tab>

  <Tab title="JavaScript" icon="js">
    ```typescript theme={null}
    const abv = new ABVClient({ apiKey: "sk-abv-..." });

    const result = await abv.guardrails.validators.toxicLanguage.validate(
      "You're doing a great job!",
      { sensitivity: "HIGH" }
    );

    if (result.status === "PASS") {
      console.log("Content is safe");
    } else {
      console.log(`Blocked: ${result.reason} (confidence: ${result.confidence})`);
    }
    ```
  </Tab>
</Tabs>

***

## Biased Language Detection

<Tabs>
  <Tab title="Python" icon="python">
    ```python theme={null}
    result = abv.guardrails.validate_biased_language(
        text="The engineer fixed the issue quickly.",
        config={"categories": ["gender", "race", "age"]}
    )

    if result.status == "FAIL":
        print(f"Bias detected: {result.reason}")
    ```
  </Tab>

  <Tab title="JavaScript" icon="js">
    ```typescript theme={null}
    const result = await abv.guardrails.validators.biasedLanguage.validate(
      "The engineer fixed the issue quickly.",
      { categories: ["gender", "race", "age"] }
    );

    if (result.status === "FAIL") {
      console.log(`Bias detected: ${result.reason}`);
    }
    ```
  </Tab>
</Tabs>

***

## JSON Validation

Validate that output is valid JSON, optionally against a schema.

<Tabs>
  <Tab title="Python" icon="python">
    ```python theme={null}
    # Basic JSON validation
    result = abv.guardrails.validate_json(
        data='{"name": "Alice", "age": 30}'
    )

    # With JSON schema
    schema = {
        "type": "object",
        "properties": {
            "name": {"type": "string"},
            "age": {"type": "integer", "minimum": 0}
        },
        "required": ["name", "age"]
    }

    result = abv.guardrails.validate_json(
        data='{"name": "Alice", "age": 30}',
        config={"schema": schema, "strictMode": True}
    )

    if result.status == "PASS":
        print("Valid JSON matching schema")
    ```
  </Tab>

  <Tab title="JavaScript" icon="js">
    ```typescript theme={null}
    // Basic JSON validation
    const result = await abv.guardrails.validators.validJson.validate(
      '{"name": "Alice", "age": 30}'
    );

    // With JSON schema
    const schema = {
      type: "object",
      properties: {
        name: { type: "string" },
        age: { type: "integer", minimum: 0 },
      },
      required: ["name", "age"],
    };

    const resultWithSchema = await abv.guardrails.validators.validJson.validate(
      '{"name": "Alice", "age": 30}',
      { schema, strictMode: true }
    );

    if (resultWithSchema.status === "PASS") {
      console.log("Valid JSON matching schema");
    }
    ```
  </Tab>
</Tabs>

***

## Contains String Validation

Check for required or forbidden strings.

<Tabs>
  <Tab title="Python" icon="python">
    ```python theme={null}
    # Must contain disclaimer
    result = abv.guardrails.validate_contains_string(
        text="This is financial advice. Disclaimer: Not professional advice.",
        config={
            "strings": ["disclaimer", "not professional advice"],
            "matchMode": "any",  # any, all
            "caseSensitive": False
        }
    )

    # Must NOT contain forbidden content
    result = abv.guardrails.validate_contains_string(
        text="Here's the safe response",
        config={
            "strings": ["password", "secret", "api_key"],
            "matchMode": "none",  # Fail if ANY string is found
            "caseSensitive": False
        }
    )
    ```
  </Tab>

  <Tab title="JavaScript" icon="js">
    ```typescript theme={null}
    // Must contain disclaimer
    const result = await abv.guardrails.validators.containsString.validate(
      "This is financial advice. Disclaimer: Not professional advice.",
      {
        strings: ["disclaimer", "not professional advice"],
        matchMode: "any",
        caseSensitive: false,
      }
    );

    // Must NOT contain forbidden content
    const forbiddenResult =
      await abv.guardrails.validators.containsString.validate(
        "Here's the safe response",
        {
          strings: ["password", "secret", "api_key"],
          matchMode: "none",
          caseSensitive: false,
        }
      );
    ```
  </Tab>
</Tabs>

***

## Input Validation Before LLM

Validate user input before sending to the LLM.

<Tabs>
  <Tab title="Python" icon="python">
    ```python theme={null}
    from abvdev import ABV, observe

    abv = ABV(api_key="sk-abv-...")

    @observe()
    def safe_chat(user_message: str) -> str:
        # Validate input
        validation = abv.guardrails.validate_toxic_language(
            text=user_message,
            config={"sensitivity": "medium"}
        )

        if validation.status == "FAIL":
            return "I can't respond to that message. Please rephrase."

        # Safe to proceed
        response = abv.gateway.complete_chat(
            provider="openai",
            model="gpt-4o-mini",
            messages=[{"role": "user", "content": user_message}]
        )

        return response.choices[0].message.content

    result = safe_chat("Tell me about machine learning")
    ```
  </Tab>

  <Tab title="JavaScript" icon="js">
    ```typescript theme={null}
    import { observe } from "@abvdev/tracing";

    const safeChat = observe(
      async (userMessage: string) => {
        // Validate input
        const validation =
          await abv.guardrails.validators.toxicLanguage.validate(userMessage, {
            sensitivity: "MEDIUM",
          });

        if (validation.status === "FAIL") {
          return "I can't respond to that message. Please rephrase.";
        }

        // Safe to proceed
        const response = await abv.gateway.chat.completions.create({
          provider: "openai",
          model: "gpt-4o-mini",
          messages: [{ role: "user", content: userMessage }],
        });

        return response.choices[0].message.content;
      },
      { name: "safe-chat" }
    );

    const result = await safeChat("Tell me about machine learning");
    ```
  </Tab>
</Tabs>

***

## Output Validation After LLM

Validate LLM output before returning to user.

<Tabs>
  <Tab title="Python" icon="python">
    ```python theme={null}
    @observe()
    def validated_generation(prompt: str) -> str:
        response = abv.gateway.complete_chat(
            provider="openai",
            model="gpt-4o-mini",
            messages=[{"role": "user", "content": prompt}]
        )
        output = response.choices[0].message.content

        # Validate output for toxic content
        toxic_check = abv.guardrails.validate_toxic_language(
            text=output,
            config={"sensitivity": "high"}
        )

        # Validate output doesn't leak sensitive patterns
        leak_check = abv.guardrails.validate_contains_string(
            text=output,
            config={
                "strings": ["internal:", "confidential:", "secret:"],
                "matchMode": "none"
            }
        )

        if toxic_check.status == "FAIL" or leak_check.status == "FAIL":
            return "I apologize, but I cannot provide that response."

        return output
    ```
  </Tab>

  <Tab title="JavaScript" icon="js">
    ```typescript theme={null}
    const validatedGeneration = observe(
      async (prompt: string) => {
        const response = await abv.gateway.chat.completions.create({
          provider: "openai",
          model: "gpt-4o-mini",
          messages: [{ role: "user", content: prompt }],
        });
        const output = response.choices[0].message.content;

        // Validate output
        const [toxicCheck, leakCheck] = await Promise.all([
          abv.guardrails.validators.toxicLanguage.validate(output, {
            sensitivity: "HIGH",
          }),
          abv.guardrails.validators.containsString.validate(output, {
            strings: ["internal:", "confidential:", "secret:"],
            matchMode: "none",
          }),
        ]);

        if (toxicCheck.status === "FAIL" || leakCheck.status === "FAIL") {
          return "I apologize, but I cannot provide that response.";
        }

        return output;
      },
      { name: "validated-generation" }
    );
    ```
  </Tab>
</Tabs>

***

## Multi-Guard Pipeline

Chain multiple guardrails for comprehensive validation.

<Tabs>
  <Tab title="Python" icon="python">
    ```python theme={null}
    from abvdev import ABV, observe
    from dataclasses import dataclass
    from typing import List

    abv = ABV(api_key="sk-abv-...")

    @dataclass
    class GuardResult:
        passed: bool
        failures: List[str]

    def run_guards(text: str) -> GuardResult:
        failures = []

        # Run all guards
        guards = [
            ("toxic", abv.guardrails.validate_toxic_language(text, {"sensitivity": "medium"})),
            ("bias", abv.guardrails.validate_biased_language(text, {})),
            ("forbidden", abv.guardrails.validate_contains_string(text, {
                "strings": ["password", "api_key"],
                "matchMode": "none"
            })),
        ]

        for name, result in guards:
            if result.status == "FAIL":
                failures.append(f"{name}: {result.reason}")

        return GuardResult(passed=len(failures) == 0, failures=failures)

    @observe()
    def guarded_chat(message: str) -> str:
        # Input guards
        input_result = run_guards(message)
        if not input_result.passed:
            return f"Input blocked: {input_result.failures}"

        # Generate
        response = abv.gateway.complete_chat(
            provider="openai",
            model="gpt-4o-mini",
            messages=[{"role": "user", "content": message}]
        )
        output = response.choices[0].message.content

        # Output guards
        output_result = run_guards(output)
        if not output_result.passed:
            return "Response blocked by safety filters."

        return output
    ```
  </Tab>

  <Tab title="JavaScript" icon="js">
    ```typescript theme={null}
    import { observe } from "@abvdev/tracing";

    interface GuardResult {
      passed: boolean;
      failures: string[];
    }

    async function runGuards(text: string): Promise<GuardResult> {
      const failures: string[] = [];

      const results = await Promise.all([
        abv.guardrails.validators.toxicLanguage
          .validate(text, { sensitivity: "MEDIUM" })
          .then((r) => ({ name: "toxic", result: r })),
        abv.guardrails.validators.biasedLanguage
          .validate(text, {})
          .then((r) => ({ name: "bias", result: r })),
        abv.guardrails.validators.containsString
          .validate(text, { strings: ["password", "api_key"], matchMode: "none" })
          .then((r) => ({ name: "forbidden", result: r })),
      ]);

      for (const { name, result } of results) {
        if (result.status === "FAIL") {
          failures.push(`${name}: ${result.reason}`);
        }
      }

      return { passed: failures.length === 0, failures };
    }

    const guardedChat = observe(
      async (message: string) => {
        // Input guards
        const inputResult = await runGuards(message);
        if (!inputResult.passed) {
          return `Input blocked: ${inputResult.failures.join(", ")}`;
        }

        // Generate
        const response = await abv.gateway.chat.completions.create({
          provider: "openai",
          model: "gpt-4o-mini",
          messages: [{ role: "user", content: message }],
        });
        const output = response.choices[0].message.content;

        // Output guards
        const outputResult = await runGuards(output);
        if (!outputResult.passed) {
          return "Response blocked by safety filters.";
        }

        return output;
      },
      { name: "guarded-chat" }
    );
    ```
  </Tab>
</Tabs>

***

## Structured Output Validation

Ensure LLM output matches expected structure.

<Tabs>
  <Tab title="Python" icon="python">
    ```python theme={null}
    @observe()
    def get_structured_data(query: str) -> dict:
        schema = {
            "type": "object",
            "properties": {
                "answer": {"type": "string"},
                "confidence": {"type": "number", "minimum": 0, "maximum": 1},
                "sources": {"type": "array", "items": {"type": "string"}}
            },
            "required": ["answer", "confidence"]
        }

        response = abv.gateway.complete_chat(
            provider="openai",
            model="gpt-4o-mini",
            messages=[
                {"role": "system", "content": "Respond in JSON with answer, confidence, and sources."},
                {"role": "user", "content": query}
            ]
        )
        output = response.choices[0].message.content

        # Validate structure
        result = abv.guardrails.validate_json(
            data=output,
            config={"schema": schema, "strictMode": True}
        )

        if result.status == "FAIL":
            raise ValueError(f"Invalid output structure: {result.reason}")

        import json
        return json.loads(output)
    ```
  </Tab>

  <Tab title="JavaScript" icon="js">
    ```typescript theme={null}
    const getStructuredData = observe(
      async (query: string) => {
        const schema = {
          type: "object",
          properties: {
            answer: { type: "string" },
            confidence: { type: "number", minimum: 0, maximum: 1 },
            sources: { type: "array", items: { type: "string" } },
          },
          required: ["answer", "confidence"],
        };

        const response = await abv.gateway.chat.completions.create({
          provider: "openai",
          model: "gpt-4o-mini",
          messages: [
            {
              role: "system",
              content:
                "Respond in JSON with answer, confidence, and sources.",
            },
            { role: "user", content: query },
          ],
        });
        const output = response.choices[0].message.content;

        // Validate structure
        const result = await abv.guardrails.validators.validJson.validate(
          output,
          { schema, strictMode: true }
        );

        if (result.status === "FAIL") {
          throw new Error(`Invalid output structure: ${result.reason}`);
        }

        return JSON.parse(output);
      },
      { name: "get-structured-data" }
    );
    ```
  </Tab>
</Tabs>

<CardGroup cols={2}>
  <Card title="Evaluation Patterns" icon="arrow-right" href="/developer/cookbook/evaluation-patterns">
    Next: Scoring and datasets
  </Card>

  <Card title="Guardrails Guide" icon="book" href="/developer/guardrails/overview">
    Reference: Full guardrails documentation
  </Card>
</CardGroup>
