Security and Governance¶
RouteKitAI provides built-in security and governance features to control agent behavior, protect sensitive data, and enforce policies. This guide covers all security features and best practices.
Table of Contents¶
- Policy Hooks
- PII Redaction
- Tool Filtering
- Approval Gates
- Sandboxing
- Timeouts and Retries
- Trace Security
- Best Practices
Policy Hooks¶
Policy hooks allow you to intercept and modify agent execution at various points. They are configured at the Runtime level and apply to all agents.
Hook Architecture¶
class PolicyHooks(BaseModel):
pii_redaction: PIIRedactionHook | None = None
tool_filter: ToolFilter | None = None
approval_gate: ApprovalGate | None = None
Hooks are executed in order: 1. PII Redaction (before trace recording) 2. Tool Filtering (before tool execution) 3. Approval Gate (before tool execution)
PII Redaction¶
Automatically redact personally identifiable information (PII) from prompts, tool arguments, and trace logs.
Basic Usage¶
from routekitai.core.hooks import PIIRedactionHook, PolicyHooks
from routekitai.core.runtime import Runtime
# Create PII redaction hook
pii_hook = PIIRedactionHook(
redact_emails=True, # Redact email addresses
redact_phones=True, # Redact phone numbers
replacement="[REDACTED]" # Custom replacement string
)
runtime = Runtime(
policy_hooks=PolicyHooks(pii_redaction=pii_hook)
)
Custom Patterns¶
Add custom regex patterns for domain-specific PII:
pii_hook = PIIRedactionHook(
redact_emails=True,
redact_phones=True,
)
# Add custom patterns
pii_hook.redact_patterns = [
(r"\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b", "[CARD]"), # Credit cards
(r"\b\d{3}-\d{2}-\d{4}\b", "[SSN]"), # Social Security Numbers
(r"\b[A-Z]{2}\d{6}\b", "[PASSPORT]"), # Passport numbers
]
runtime = Runtime(
policy_hooks=PolicyHooks(pii_redaction=pii_hook)
)
Features¶
- Email addresses:
user@example.com→[REDACTED] - Phone numbers:
555-123-4567→[REDACTED] - Custom regex patterns: Match any pattern
- Recursive redaction: Works in nested dictionaries and lists
- Trace integration: Automatically redacts trace logs
What Gets Redacted¶
PII redaction applies to: - User prompts - Tool arguments - Model responses (optional) - Trace event data - Error messages
Tool Filtering¶
Control which tools can be executed at the agent or runtime level.
Agent-Level Filter¶
Restrict tools for a specific agent:
from routekitai.core.hooks import ToolFilter
from routekitai.core.agent import Agent
# Only allow specific tools
agent = Agent(
name="restricted_agent",
model=model,
tools=[tool1, tool2, tool3],
tool_filter=ToolFilter(allowed_tools=["tool1", "tool2"]) # Only tool1 and tool2 allowed
)
Runtime-Level Filter¶
Deny specific tools globally:
from routekitai.core.hooks import PolicyHooks, ToolFilter
from routekitai.core.runtime import Runtime
# Deny specific tools globally
runtime = Runtime(
policy_hooks=PolicyHooks(
tool_filter=ToolFilter(denied_tools=["dangerous_tool", "network_tool"])
)
)
Priority¶
Agent-level filters take precedence over runtime-level filters. If an agent has a filter, it overrides the runtime filter.
Use Cases¶
- Development: Restrict tools during testing
- Production: Deny dangerous tools globally
- Multi-tenant: Different tool sets per tenant
- Compliance: Enforce tool usage policies
Approval Gates¶
Require explicit approval before executing tools with certain permissions.
Basic Setup¶
from routekitai.core.hooks import ApprovalGate, PolicyHooks
from routekitai.core.runtime import Runtime
def approval_callback(tool_name: str, tool_args: dict) -> bool:
"""Return True if tool is approved, False otherwise."""
# Check against approval database, user input, etc.
if tool_name == "network_tool":
return check_approval_database(tool_name, tool_args)
return True # Auto-approve other tools
runtime = Runtime(
policy_hooks=PolicyHooks(
approval_gate=ApprovalGate(
require_approval_for_permissions=["network", "filesystem"],
approval_callback=approval_callback,
)
)
)
Permission-Based Approval¶
Tools can declare permissions:
from routekitai.core.tool import ToolPermission
class NetworkTool(Tool):
permissions = [ToolPermission.NETWORK]
...
The approval gate checks these permissions:
approval_gate = ApprovalGate(
require_approval_for_permissions=["network", "filesystem"],
approval_callback=my_callback,
)
Use Cases¶
- Network access: Block network tools unless explicitly approved
- File system operations: Require human review for file writes
- External API calls: Approve API calls based on cost/risk
- Integration: Connect to external approval systems
Sandboxing¶
Sandboxing provides isolation for tool execution. (Note: Sandboxing is planned for future releases.)
Filesystem Sandbox¶
Control file system access:
from routekitai.sandbox.filesystem import FilesystemSandbox
sandbox = FilesystemSandbox(
allowed_paths=[Path("/safe/directory")],
read_only_paths=[Path("/readonly")],
sandbox_root=Path("/sandbox"),
)
Network Sandbox¶
Control network access:
from routekitai.sandbox.network import NetworkSandbox
sandbox = NetworkSandbox(
allowed_hosts=["api.example.com"],
blocked_hosts=["dangerous-site.com"],
rate_limit={"requests_per_minute": 60},
)
Timeouts and Retries¶
Timeouts¶
Configure timeouts at multiple levels:
# Runtime-level default timeout
runtime = Runtime(timeout=30.0) # 30 seconds default
# Tool-level timeout (takes precedence)
tool = Tool(
name="slow_tool",
timeout=60.0, # 60 seconds for this tool
...
)
Retries¶
Automatic retry with exponential backoff:
runtime = Runtime(
max_retries=3, # Maximum retry attempts
retry_backoff_base=1.0, # Base delay in seconds
retry_backoff_max=60.0, # Maximum delay cap
)
Backoff Formula: delay = min(base * (2^attempt), max)
- Attempt 1: 1.0s delay
- Attempt 2: 2.0s delay
- Attempt 3: 4.0s delay
- Capped at 60.0s maximum
Cancellation¶
Cancel long-running executions gracefully:
import asyncio
from routekitai.core.runtime import Runtime
runtime = Runtime()
runtime.register_agent(agent)
# Create a task that can be cancelled
task = asyncio.create_task(
runtime.run("agent_name", "prompt")
)
# Cancel after 5 seconds
await asyncio.sleep(5)
task.cancel()
try:
result = await task
except asyncio.CancelledError:
print("Execution cancelled")
Trace Security¶
Traces contain sensitive information. Protect them accordingly.
Trace Storage¶
- Local storage: Traces stored in
.routekit/traces/by default - Encryption: Encrypt trace files if they contain sensitive data
- Access control: Restrict file system permissions
- Retention: Implement trace retention policies
Trace Redaction¶
PII redaction automatically applies to traces:
runtime = Runtime(
trace_dir=Path(".routekit/traces"),
policy_hooks=PolicyHooks(
pii_redaction=PIIRedactionHook(redact_emails=True, redact_phones=True)
)
)
Trace Sharing¶
Before sharing traces: 1. Review for sensitive data 2. Redact PII if needed 3. Remove API keys and credentials 4. Anonymize user data
Best Practices¶
1. Always Enable PII Redaction in Production¶
runtime = Runtime(
policy_hooks=PolicyHooks(
pii_redaction=PIIRedactionHook(
redact_emails=True,
redact_phones=True,
)
)
)
2. Use Deny Lists for Dangerous Tools¶
runtime = Runtime(
policy_hooks=PolicyHooks(
tool_filter=ToolFilter(
denied_tools=["delete_file", "format_disk", "shutdown_system"]
)
)
)
3. Implement Approval Gates for High-Risk Permissions¶
def require_approval(tool_name: str, tool_args: dict) -> bool:
# Check approval system
return check_approval_system(tool_name, tool_args)
runtime = Runtime(
policy_hooks=PolicyHooks(
approval_gate=ApprovalGate(
require_approval_for_permissions=["network", "filesystem"],
approval_callback=require_approval,
)
)
)
4. Set Appropriate Timeouts¶
runtime = Runtime(
timeout=30.0, # Prevent runaway executions
)
5. Use Replay for Testing¶
# Replay production traces in test environment
replayed = await runtime.replay(trace_id, "agent_name")
6. Monitor Trace Files¶
- Regularly review trace files for security issues
- Implement trace retention policies
- Encrypt sensitive traces
- Restrict access to trace directories
7. Secure API Keys¶
- Never commit API keys to version control
- Use environment variables or secret management
- Rotate keys regularly
- Use different keys for dev/staging/prod
Complete Example¶
import os
from pathlib import Path
from routekitai.core.agent import Agent
from routekitai.core.hooks import (
ApprovalGate,
PIIRedactionHook,
PolicyHooks,
ToolFilter,
)
from routekitai.core.runtime import Runtime
from routekitai.providers.openai import OpenAIChatModel
# Create model with secure API key handling
model = OpenAIChatModel(
name="gpt-4",
api_key=os.getenv("OPENAI_API_KEY") # Never hardcode!
)
# Create agent with restricted tools
agent = Agent(
name="secure_agent",
model=model,
tools=[safe_tool1, safe_tool2],
tool_filter=ToolFilter(allowed_tools=["safe_tool1", "safe_tool2"]),
)
# Approval callback
def network_approval(tool_name: str, tool_args: dict) -> bool:
# Check approval system
return check_network_approval(tool_name)
# Configure runtime with security hooks
runtime = Runtime(
timeout=30.0,
max_retries=3,
retry_backoff_base=1.0,
retry_backoff_max=60.0,
trace_dir=Path(".routekit/traces"),
policy_hooks=PolicyHooks(
pii_redaction=PIIRedactionHook(
redact_emails=True,
redact_phones=True,
),
tool_filter=ToolFilter(
denied_tools=["dangerous_tool"]
),
approval_gate=ApprovalGate(
require_approval_for_permissions=["network"],
approval_callback=network_approval,
),
),
)
runtime.register_agent(agent)
result = await runtime.run("secure_agent", "User prompt with email@example.com")
Security Checklist¶
- [ ] PII redaction enabled in production
- [ ] Tool deny lists configured
- [ ] Approval gates for high-risk permissions
- [ ] Timeouts set appropriately
- [ ] API keys stored securely
- [ ] Trace files protected
- [ ] Access control implemented
- [ ] Regular security reviews scheduled