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.
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:
Pattern Use Case Webhook Guardrail RAXE as a Portkey custom guardrail (Portkey calls RAXE) Client Wrapper Scan 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)
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)
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()
Use appropriate severity threshold
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"
)
Handle the 3-second timeout
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
Package Version 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