Official Python SDK for Sensoit - AI Prompt Security & Management
Project description
Sensoit Python SDK
Official Python SDK for Sensoit - AI Prompt Security & Management Platform.
Sensoit provides enterprise-grade guardrails for AI applications, including PII detection, toxicity filtering, keyword blocking, and custom policy enforcement.
Installation
pip install sensoit-sdk
# With framework integrations
pip install sensoit-sdk[fastapi]
pip install sensoit-sdk[flask]
pip install sensoit-sdk[django]
pip install sensoit-sdk[all] # All frameworks
Quick Start
Async Usage
from sensoit import Sensoit
async def main():
async with Sensoit(api_key="gf_live_xxx") as gf:
result = await gf.run(
"customer-support",
input="I need help with my order #12345",
variables={"customer_name": "John"},
session_id="session_abc",
)
if result.blocked:
print(f"Blocked: {result.violations}")
else:
print(f"Response: {result.output}")
import asyncio
asyncio.run(main())
Sync Usage
from sensoit import Sensoit
gf = Sensoit(api_key="gf_live_xxx")
result = gf.run_sync(
"customer-support",
input="I need help with my order #12345",
variables={"customer_name": "John"},
)
print(f"Response: {result.output}")
print(f"Tokens: {result.tokens_used}")
print(f"Cost: ${result.cost_usd}")
Configuration
gf = Sensoit(
# Required: Your API key
api_key="gf_live_xxx",
# Optional: API base URL (default: https://api.sensoit.io)
base_url="https://api.sensoit.io",
# Optional: Request timeout in seconds (default: 30.0)
timeout=30.0,
# Optional: Max retry attempts (default: 3)
max_retries=3,
# Optional: Enable debug logging (default: False)
debug=True,
# Optional: Enable caching (default: True)
cache_enabled=True,
# Optional: Cache TTL in seconds (default: 60)
cache_ttl_seconds=60,
)
| Option | Type | Default | Description |
|---|---|---|---|
api_key |
str |
required | Your Sensoit API key |
base_url |
str |
https://api.sensoit.io |
API base URL |
timeout |
float |
30.0 |
Request timeout in seconds |
max_retries |
int |
3 |
Max retry attempts |
debug |
bool |
False |
Enable debug logging |
cache_enabled |
bool |
True |
Enable prompt caching |
cache_ttl_seconds |
int |
60 |
Cache TTL in seconds |
Core Methods
run() / run_sync()
Run a prompt through Sensoit with guardrail protection.
# Async
result = await gf.run(
"support-assistant",
input="I need help with my order",
variables={"customer_name": "John"},
session_id="session_123",
force_refresh=False,
dry_run=False,
timeout=60.0,
metadata={"source": "web"},
)
# Sync
result = gf.run_sync("support-assistant", input="Hello")
Return Type: RunResult
@dataclass
class RunResult:
output: str # Generated response
allowed: bool # Request passed guardrails
blocked: bool # Request was blocked
escalated: bool # Request needs human review
violations: list # Policy violations
tokens_used: int # Total tokens (in + out)
tokens_in: int # Input tokens
tokens_out: int # Output tokens
latency_ms: int # Total latency
cost_usd: float # Estimated cost
prompt_version: int # Prompt version used
model: str # LLM model used
provider: str # LLM provider
cached: bool # Served from cache
request_id: str # Unique request ID
run_batch() / run_batch_sync()
Run multiple prompts in parallel.
# Async
batch_result = await gf.run_batch([
{"prompt": "translator", "options": {"input": "Hello", "variables": {"lang": "es"}}},
{"prompt": "translator", "options": {"input": "Goodbye", "variables": {"lang": "fr"}}},
])
# Sync
batch_result = gf.run_batch_sync([...])
print(f"Total: {batch_result.summary.total}")
print(f"Allowed: {batch_result.summary.allowed}")
print(f"Blocked: {batch_result.summary.blocked}")
for result in batch_result.results:
print(f"{result.prompt}: {result.output}")
invalidate_cache()
Clear cached prompt data.
# Clear cache for specific prompt
gf.invalidate_cache("support-assistant")
# Clear all cache
gf.invalidate_cache()
FastAPI Integration
from fastapi import FastAPI, Request
from sensoit import Sensoit
from sensoit.middleware import SensoitMiddleware
app = FastAPI()
gf = Sensoit(api_key="gf_live_xxx")
# Add middleware to protect routes
app.add_middleware(
SensoitMiddleware,
client=gf,
prompt="support-bot",
protected_paths=["/api/chat", "/api/ask"],
blocked_response={"error": "Cannot help with that request"},
blocked_status_code=200,
)
@app.post("/api/chat")
async def chat(request: Request):
# Access Sensoit result
result = request.scope.get("sensoit")
return {"reply": result.output if result else "No response"}
Flask Integration
from flask import Flask, request, jsonify
from sensoit import Sensoit
from sensoit.middleware import flask_protect
app = Flask(__name__)
gf = Sensoit(api_key="gf_live_xxx")
@app.route("/chat", methods=["POST"])
@flask_protect(gf, prompt="support-bot")
def chat():
# Access Sensoit result
result = request.sensoit
return jsonify({"reply": result.output})
# With custom options
@app.route("/ask", methods=["POST"])
@flask_protect(
gf,
prompt="qa-bot",
extract_input=lambda: request.json.get("question"),
extract_variables=lambda: {"user_id": request.json.get("user_id")},
blocked_response={"error": "Question not allowed"},
)
def ask():
return jsonify({"answer": request.sensoit.output})
Django Integration
# settings.py
MIDDLEWARE = [
# ... other middleware
'sensoit.middleware.DjangoSensoitMiddleware',
]
SENSOIT = {
'API_KEY': 'gf_live_xxx',
'PROMPT': 'support-bot',
'PROTECTED_PATHS': ['/api/chat/', '/api/ask/'],
'BASE_URL': 'https://api.sensoit.io', # Optional
}
# views.py
from django.http import JsonResponse
def chat(request):
# Access Sensoit result
result = getattr(request, "sensoit", None)
if result:
return JsonResponse({"reply": result.output})
return JsonResponse({"error": "No response"})
Error Handling
from sensoit import (
Sensoit,
BlockedError,
EscalatedError,
RateLimitError,
AuthError,
TimeoutError,
ValidationError,
is_retryable_error,
)
gf = Sensoit(api_key="gf_live_xxx")
try:
result = await gf.run("my-prompt", input="Hello")
print(result.output)
except BlockedError as e:
print(f"Blocked by: {[v['policyName'] for v in e.violations]}")
print(f"Has critical: {e.has_critical_violation()}")
except EscalatedError as e:
print(f"Escalated: {e.reason}")
except RateLimitError as e:
print(f"Rate limited, retry after: {e.retry_after_seconds}s")
except AuthError as e:
print(f"Auth error: {e.message}")
except TimeoutError as e:
print(f"Timed out after: {e.timeout_seconds}s")
except ValidationError as e:
print(f"Validation errors: {e.field_errors}")
Error Classes
| Error | Code | Status | Description |
|---|---|---|---|
BlockedError |
BLOCKED |
200 | Response blocked by guardrails |
EscalatedError |
ESCALATED |
200 | Response needs human review |
RateLimitError |
RATE_LIMIT |
429 | Rate limit exceeded |
AuthError |
AUTH_ERROR |
401 | Invalid API key |
TimeoutError |
TIMEOUT |
- | Request timed out |
ValidationError |
VALIDATION_ERROR |
400 | Invalid input |
PromptNotFoundError |
PROMPT_NOT_FOUND |
404 | Prompt doesn't exist |
NetworkError |
NETWORK_ERROR |
- | Network failure |
SensoitAPIError |
API_ERROR |
varies | General API error |
Event Callbacks
gf = Sensoit(api_key="gf_live_xxx")
# Register event handlers
@gf.on_blocked
def handle_blocked(prompt_name, violations, request_id):
print(f"Blocked: {prompt_name}")
for v in violations:
print(f" - {v['policyName']}: {v['detail']}")
@gf.on_escalated
def handle_escalated(prompt_name, request_id, reason):
print(f"Escalated: {prompt_name} - {reason}")
@gf.on_error
def handle_error(prompt_name, error, request_id):
print(f"Error in {prompt_name}: {error}")
@gf.on_complete
def handle_complete(prompt_name, result):
print(f"Completed: {prompt_name}")
print(f" Tokens: {result.tokens_used}")
print(f" Cost: ${result.cost_usd}")
@gf.on_retry
def handle_retry(prompt_name, attempt, max_attempts):
print(f"Retry {attempt}/{max_attempts} for {prompt_name}")
Type Hints
All types are exported for type checking:
from sensoit import (
# Configuration
SensoitConfig,
CacheConfig,
# Run operations
RunOptions,
RunResult,
# Batch operations
BatchRunInput,
BatchRunResult,
BatchRunItemResult,
BatchRunSummary,
# Guardrails
GuardrailViolation,
GuardrailViolationType,
ViolationSeverity,
ViolationAction,
)
Caching
The SDK includes built-in caching for prompt responses:
gf = Sensoit(
api_key="gf_live_xxx",
cache_enabled=True,
cache_ttl_seconds=60,
)
# First call - makes API request
result1 = await gf.run("prompt", input="Hello")
print(result1.cached) # False
# Second call - served from cache
result2 = await gf.run("prompt", input="Hello")
print(result2.cached) # True
# Force fresh request
result3 = await gf.run("prompt", input="Hello", force_refresh=True)
print(result3.cached) # False
# Invalidate cache
gf.invalidate_cache("prompt")
Health Check
# Async
health = await gf.health()
# Sync
health = gf.health_sync()
print(health)
# {'status': 'ok', 'service': 'sensoit', 'timestamp': '...'}
Context Manager
# Async
async with Sensoit(api_key="gf_live_xxx") as gf:
result = await gf.run("prompt", input="Hello")
# Sync
with Sensoit(api_key="gf_live_xxx") as gf:
result = gf.run_sync("prompt", input="Hello")
Environment Variables
export SENSOIT_API_KEY=gf_live_xxx
export SENSOIT_BASE_URL=https://api.sensoit.io
import os
from sensoit import Sensoit
gf = Sensoit(
api_key=os.environ["SENSOIT_API_KEY"],
base_url=os.environ.get("SENSOIT_BASE_URL", "https://api.sensoit.io"),
)
Requirements
- Python 3.9 or higher
- httpx >= 0.26.0
- pydantic >= 2.0.0
- tenacity >= 8.0.0
License
MIT
Support
- Documentation: https://docs.sensoit.io
- Issues: https://github.com/sensoit/sensoit-sdk/issues
- Email: support@sensoit.io
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sensoit-1.2.0.tar.gz.
File metadata
- Download URL: sensoit-1.2.0.tar.gz
- Upload date:
- Size: 40.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.8.19
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cf4fa1f67dd9fb25c1d9edd0286d243520bc559435b71afab06ffbc332c52a3a
|
|
| MD5 |
7e178be86f0327dad19ecdf94734811e
|
|
| BLAKE2b-256 |
17a53055472cf15284adb8a380b07432bc9979fd184760aab50ff414b7b8b020
|
File details
Details for the file sensoit-1.2.0-py3-none-any.whl.
File metadata
- Download URL: sensoit-1.2.0-py3-none-any.whl
- Upload date:
- Size: 41.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.8.19
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
37899d6278e8ca6515ffb8ce84e5c9ff275ae8e1faca4387b8586198b4250c3e
|
|
| MD5 |
2b18cbcc000f240a62bf8391b05d89ad
|
|
| BLAKE2b-256 |
319181b67460b62732e7a1dee9e39d86447458b8eee3b64a300e854e6be4c76e
|