Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.raxe.ai/llms.txt

Use this file to discover all available pages before exploring further.

New to RAXE? Start with the Quickstart and learn how detection works.

Overview

RAXE integrates with Portkey AI Gateway to provide security scanning as a custom webhook guardrail. Portkey is an AI gateway that routes requests to 200+ LLMs with built-in observability, caching, and guardrails. RAXE offers two integration patterns:
PatternUse Case
Webhook GuardrailRAXE as a Portkey custom guardrail (Portkey calls RAXE)
Client WrapperScan locally before/after Portkey calls

Installation

pip install raxe[portkey]

Option 1: Webhook Guardrail

Use RAXE as a custom webhook guardrail that Portkey calls for input/output validation.

Create the Webhook Endpoint

from fastapi import FastAPI, Request
from raxe import Raxe
from raxe import RaxePortkeyWebhook

app = FastAPI()

# Create webhook handler (default: log-only mode)
webhook = RaxePortkeyWebhook(Raxe())

@app.post("/raxe/guardrail")
async def raxe_guardrail(request: Request):
    data = await request.json()
    return webhook.handle_request(data)

Configure Portkey

Add RAXE as a webhook guardrail in your Portkey config:
{
  "beforeRequestHooks": [{
    "id": "raxe-security",
    "type": "guardrail",
    "checks": [{
      "id": "default.webhook",
      "parameters": {
        "webhookURL": "https://your-endpoint/raxe/guardrail",
        "headers": {
          "Authorization": "Bearer YOUR_API_KEY"
        }
      }
    }],
    "deny": true
  }]
}

Blocking Mode

Enable blocking to return verdict: false on threats:
from raxe import (
    RaxePortkeyWebhook,
    PortkeyGuardConfig,
)

config = PortkeyGuardConfig(
    block_on_threats=True,           # Return false verdict on threats
    block_severity_threshold="HIGH", # Block HIGH and CRITICAL
)

webhook = RaxePortkeyWebhook(Raxe(), config=config)

Response Format

RAXE returns Portkey-compatible verdicts:
{
  "verdict": true,
  "data": {
    "reason": "No threats detected",
    "detections": 0,
    "scan_duration_ms": 5.2
  }
}
When threats are detected (with blocking enabled):
{
  "verdict": false,
  "data": {
    "reason": "Threat detected",
    "severity": "high",
    "detections": 1,
    "rule_ids": ["pi-001"],
    "scan_duration_ms": 8.3
  }
}

Option 2: Client Wrapper

Scan requests locally before they go through Portkey:
from portkey_ai import Portkey
from raxe import Raxe
from raxe import RaxePortkeyGuard

# Create guard (default: log-only mode)
guard = RaxePortkeyGuard(Raxe())

# Wrap Portkey client
client = guard.wrap_client(
    Portkey(api_key="PORTKEY_API_KEY", virtual_key="VIRTUAL_KEY")
)

# All calls are automatically scanned
response = client.chat.completions.create(
    messages=[{"role": "user", "content": "Hello, how are you?"}],
    model="gpt-4"
)

Blocking Mode

guard = RaxePortkeyGuard(Raxe(), block_on_threats=True)
client = guard.wrap_client(Portkey(api_key="..."))

# Raises RaxeBlockedError if threat detected
response = client.chat.completions.create(
    messages=[{"role": "user", "content": user_input}],
    model="gpt-4"
)

Direct Scan and Call

For more control, use scan_and_call:
from portkey_ai import Portkey
from raxe import RaxePortkeyGuard

guard = RaxePortkeyGuard(block_on_threats=True)
client = Portkey(api_key="...", virtual_key="...")

# Scan before calling
response = guard.scan_and_call(
    client.chat.completions.create,
    messages=[{"role": "user", "content": user_input}],
    model="gpt-4"
)

Configuration

from raxe import PortkeyGuardConfig

config = PortkeyGuardConfig(
    # Blocking behavior
    block_on_threats=True,           # Return false verdict / raise exception
    block_severity_threshold="HIGH", # "LOW", "MEDIUM", "HIGH", "CRITICAL"

    # What to scan
    scan_inputs=True,   # Scan input messages (beforeRequest)
    scan_outputs=True,  # Scan responses (afterRequest)

    # Response details
    include_scan_details=True,  # Include severity, rule_ids in response

    # Error handling
    fail_open=True,  # Pass on errors (matches Portkey's timeout behavior)
)

Error Handling

from raxe import RaxeBlockedError

try:
    response = client.chat.completions.create(
        messages=[{"role": "user", "content": user_input}],
        model="gpt-4"
    )
except RaxeBlockedError as e:
    print("Request blocked for security reasons")

Statistics

Track scanning statistics:
# Webhook stats
print(webhook.stats)
# {'total_requests': 100, 'threats_detected': 5, 'verdicts_false': 3}

# Guard stats
print(guard.stats)
# {'total_scans': 50, 'threats_detected': 2, 'threats_blocked': 2}

# Reset stats
guard.reset_stats()

Flask Integration

from flask import Flask, request, jsonify
from raxe import RaxePortkeyWebhook

app = Flask(__name__)
webhook = RaxePortkeyWebhook()

@app.route("/raxe/guardrail", methods=["POST"])
def raxe_guardrail():
    data = request.get_json()
    return jsonify(webhook.handle_request(data))

Best Practices

Monitor threats before enabling blocking:
# Default: log-only (always returns true verdict)
webhook = RaxePortkeyWebhook()
Choose blocking threshold based on risk tolerance:
# Strict: Block any threat
config = PortkeyGuardConfig(
    block_on_threats=True,
    block_severity_threshold="LOW"
)

# Balanced: Block HIGH and above
config = PortkeyGuardConfig(
    block_on_threats=True,
    block_severity_threshold="HIGH"
)

# Minimal: Block only CRITICAL
config = PortkeyGuardConfig(
    block_on_threats=True,
    block_severity_threshold="CRITICAL"
)
Portkey webhook requests timeout after 3 seconds. RAXE’s fail_open=True (default) returns a pass verdict if scanning takes too long or errors:
# Default: pass on timeout/error (matches Portkey behavior)
config = PortkeyGuardConfig(fail_open=True)

# Strict: fail on timeout/error
config = PortkeyGuardConfig(fail_open=False)

Combining with Portkey Features

RAXE works alongside Portkey’s other features:
from portkey_ai import Portkey
from raxe import RaxePortkeyGuard

guard = RaxePortkeyGuard(block_on_threats=True)

# Portkey client with retries and fallbacks
client = guard.wrap_client(
    Portkey(
        api_key="PORTKEY_API_KEY",
        virtual_key="OPENAI_VIRTUAL_KEY",
        config={
            "retry": {"attempts": 3},
            "fallback": [{"virtual_key": "ANTHROPIC_VIRTUAL_KEY"}]
        }
    )
)

# RAXE scans, then Portkey handles routing/retries
response = client.chat.completions.create(
    messages=[{"role": "user", "content": "Hello"}],
    model="gpt-4"
)

Supported Versions

PackageVersion
portkey-ai>= 1.0.0
raxe>= 0.3.0

What’s Next

Production Checklist

Deploy RAXE safely to production

Common Patterns

Error handling, logging, and production patterns