SCOPE (Safety, Compliance, Observability, Permissions, Escalation) is a production-ready governance framework for enterprise AI agents. Built on Google's Agent Development Kit (ADK), it implements a "Defense in Depth" architecture with 5 core pillars:
- Safety Guardrails
- Compliance & Policy-as-Code
- Observability & Auditing
- Permissions & Identity (IAM/ACL)
- Escalation Protocols (Human-in-the-Loop)
SCOPE agent running in the ADK Web UI
SCOPE is designed for mission-critical applications where safety, compliance, and auditability are paramount. Example: A banking customer service agent handling account inquiries, transactions, and fraud reports.
User Input: "What's my account balance?"
β
βββββββββββββββββββββββββββββββββββββββββββ
β Safety Check (before_model_callback) β
β - ML-based safety (disabled for now) β
β - Log user input β
βββββββββββββββββββββββββββββββββββββββββββ
β (if safe)
βββββββββββββββββββββββββββββββββββββββββββ
β LLM Decision Engine β
β - Analyzes user intent β
β - Checks compliance rules β
β - Decides: APPROVE/REJECT/REWRITE/ β
β ESCALATE β
β - Selects tool if needed β
βββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββ
β Decision: APPROVE β
β { β
β "decision": "APPROVE", β
β "action": "get_account_balance", β
β "parameters": {"account_id": "acc1"}, β
β "reasoning": "User wants balance", β
β "confidence": 0.95 β
β } β
βββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββ
β System Executes Decision β
β β
β If APPROVE β Call tool β
β If REJECT β Return refusal message β
β If REWRITE β Rewrite & re-process β
β If ESCALATE β Add to escalation queue β
βββββββββββββββββββββββββββββββββββββββββββ
β (APPROVE path)
βββββββββββββββββββββββββββββββββββββββββββ
β Tool: get_account_balance(account_id) β
β - IAM check (user can access account) β
β - Query database β
β - Log account access (PCI-DSS) β
β - Returns: $1,234.56 β
βββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββ
β LLM Formats Response β
β - Professional tone β
β - Applies compliance rules β
βββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββ
β Logging (after_model_callback) β
β - Log decision: APPROVE β
β - Log tool call: get_account_balance β
β - Log response β
β - Compliance: PCI-DSS audit trail β
βββββββββββββββββββββββββββββββββββββββββββ
β
Response: "Your current balance is $1,234.56"
| Decision | When | Action | Example |
|---|---|---|---|
| APPROVE | Safe, compliant, within capabilities | Call tool or provide info | "What's my balance?" β get_account_balance() |
| REJECT | Violates rules or outside capabilities | Polite refusal + reason | "Can you create an account?" β "Requires in-person verification" |
| REWRITE | Valid intent, unsafe phrasing | Sanitize & re-process | "Hack my account" β "Access my account" |
| ESCALATE | Low confidence or complex | Add to human review queue | "Transfer $100,000" β Escalation ticket |
Key Features:
- π‘οΈ Pre-LLM Safety: Blocks malicious inputs before expensive LLM calls
- π Role-Based Access: USER/STAFF/ADMIN with granular permissions
- π Database Tools: IAM-protected queries to user/account/transaction tables
- π Audit Logging: Every action logged for compliance (PCI-DSS, SOC2)
- π¨ Escalation: Uncertain cases routed to human review
SCOPE uses a layered defense approach with modular, scalable components:
User Input
β
Layer 2a: Fast Safety Checks (ML models, ~50ms)
β (if safe)
Layer 2b: LLM Contextual Safety + Compliance
β (if safe & compliant)
Layer 1: Decision (ALLOW / REFUSE / REWRITE / ESCALATE)
β (if ESCALATE)
Human Review Queue (Role-based access)
- Safety - Fast ML-based + LLM contextual safety checks
- Compliance - Custom business rules and regulatory requirements
- IAM - Role-based access control (USER, STAFF, ADMIN, SYSTEM)
- Escalation - Human-in-the-loop with SQLite queue
- Data - Banking database with IAM-protected operations
- Logging - Audit trail and compliance logging (PCI-DSS, SOC2)
scope/
βββ safety/ # Pillar 1: Text/Image safety tools
β βββ __init__.py
β βββ tools.py # TextSafetyTool, ImageSafetyTool
βββ rules/ # Pillar 2: Compliance rules (YAML)
β βββ __init__.py
β βββ compliance_rules.yaml
βββ iam/ # Pillar 3: Access control
β βββ __init__.py
β βββ roles.py # UserRole, Permission enums
β βββ acl.py # AccessControl, User class
βββ escalation/ # Pillar 4: Human review queue
β βββ __init__.py
β βββ models.py # EscalationTicket model
β βββ queue.py # SQLite-based queue
β βββ data/ # Database storage
βββ data/ # Database layer (for tools)
β βββ models.py # User, Account, Transaction
β βββ database.py # DB queries
βββ logging/ # Audit trail
β βββ audit.py # Transaction logging
β βββ compliance_log.py # Regulatory logs
β βββ view_logs.py # Terminal Log Viewer
βββ config.py # 4-pillar configuration
βββ agent.py # Main ADK agent
βββ callbacks.py # Layer 2 safety callbacks
βββ prompt.py # Agent instructions
βββ observability_tools.py # Traceable tools for ADK
βββ tools.py # Unified imports
- Python 3.10-3.12
- uv package manager
- Google Cloud account with Vertex AI enabled
# Install uv
curl -LsSf https://astral.sh/uv/install.sh | sh
# Authenticate with Google Cloud
gcloud auth login
gcloud auth application-default login
gcloud config set project your-project-id
# Install dependencies
uv syncCreate .env file:
# Google Cloud
GOOGLE_GENAI_USE_VERTEXAI=true
GOOGLE_CLOUD_PROJECT=your-project-id
GOOGLE_CLOUD_LOCATION=us-central1
# Pillar 1: Safety
GOOGLE_SAFETY_ENABLED=true
GOOGLE_SAFETY_MODE=STRICT
GOOGLE_SAFETY_THRESHOLD_HIGH=0.8
GOOGLE_SAFETY_THRESHOLD_MEDIUM=0.4
# Pillar 2: Compliance
GOOGLE_COMPLIANCE_ENABLED=true
GOOGLE_COMPLIANCE_RULES=["Never share full account numbers", "Verify identity before account access"]
# Pillar 3: IAM
GOOGLE_IAM_ENABLED=true
GOOGLE_IAM_DEFAULT_USER_ROLE=USER
# Pillar 4: Escalation
GOOGLE_ESCALATION_ENABLED=true
GOOGLE_ESCALATION_THRESHOLD=0.6
GOOGLE_ESCALATION_STORAGE_TYPE=sqlite# Web UI (recommended)
uv run adk web
# CLI mode
uv run adk run scopeFast, multi-modal safety checks using ML models or LLM.
- Model:
Falconsai/offensive_speech_detection(DistilBERT) - Detection: Offensive language, hate speech, injection attacks
- Latency: ~50ms
- Model:
Marqo/nsfw-image-detection-384(Vision Transformer) - Detection: NSFW content
- Threshold: Block if score > 0.5
# callbacks.py - before_model_callback
def fast_guardrail_callback(context, llm_request):
# Run safety checks BEFORE LLM call
text_result = text_tool.check(user_input)
if not text_result['is_safe']:
# Log and let agent handle with compliance rules
logger.warning(f"Unsafe content: {text_result['risk_category']}")
return None # Agent will apply compliance rules
return None # Continue to LLMBenefits:
- π Fast: Blocks unsafe inputs in ~50ms vs ~2000ms LLM call
- π° Cost-effective: No LLM charges for blocked requests
- π‘οΈ Defense in Depth: Multiple layers of protection
Custom business rules enforced by the LLM agent.
- Define human-readable rules (e.g., "Never share full account numbers")
- Rules are transformed at agent initialization
- Agent consults rules for every decision
- Violations cite specific rule numbers
BANKING_COMPLIANCE_RULES = [
"Never share full account numbers - only last 4 digits",
"Always verify identity before providing account information",
"Log all financial transactions for audit trail",
"Escalate wire transfers over $10,000 to STAFF",
"Never provide investment advice or predictions",
]from scope.compliance.examples import (
HEALTHCARE_RULES, # HIPAA compliance
FINANCIAL_SERVICES_RULES, # PCI-DSS, SOC2
LEGAL_RULES, # Attorney-client privilege
)Role-based access control for the entire system.
| Role | Permissions | Use Case |
|---|---|---|
| USER | Use agent, view own escalations, query own accounts | Banking customers |
| STAFF | + View all escalations (read-only), access customer accounts | Customer service reps |
| ADMIN | + Resolve escalations, modify config, approve transactions | Bank managers |
| SYSTEM | All permissions (internal use) | Automated processes |
from scope.iam import User, UserRole, AccessControl
# Create users
customer = User("user", UserRole.USER, "Alice")
rep = User("staff456", UserRole.STAFF, "Bob")
manager = User("admin789", UserRole.ADMIN, "Charlie")
# Check permissions
customer.has_permission(Permission.VIEW_OWN_ESCALATIONS) # True
rep.has_permission(Permission.VIEW_ALL_ESCALATIONS) # True
manager.has_permission(Permission.RESOLVE_ESCALATIONS) # True
# Access control in tools
@tool
def get_account_balance(user: User, account_id: str):
# Verify user can access this account
AccessControl.check_permission(user, Permission.VIEW_ACCOUNTS)
if user.role == UserRole.USER:
# Users can only see their own accounts
if account_id not in user.account_ids:
raise AccessDeniedException()
# ... query databaseHuman-in-the-loop review queue with SQLite storage.
- Agent confidence < threshold (default: 0.6)
- Edge cases requiring human judgment
- High-value transactions (e.g., >$10,000)
- Fraud reports
from scope.escalation import EscalationQueue, EscalationTicket
from scope.iam import User, UserRole
queue = EscalationQueue()
# Add ticket (agent)
ticket = EscalationTicket(
user_id="user",
input_text="Transfer $50,000 to external account",
agent_reasoning="High-value transfer - requires approval",
confidence=0.55
)
queue.add_ticket(ticket)
# View tickets (role-based)
staff = User("staff1", UserRole.STAFF)
tickets = queue.view_tickets(staff) # Sees all tickets (read-only)
admin = User("admin1", UserRole.ADMIN)
queue.resolve_ticket(admin, ticket.id, "approved", "Verified with customer")Banking database with IAM-protected operations.
from scope.data import User, Account, Transaction, AccountType
# User model
user = User(
user_id="user",
name="Alice Johnson",
email="alice@example.com",
account_ids=["acc001", "acc002"]
)
# Account model
account = Account(
account_id="acc001",
user_id="user",
account_type=AccountType.CHECKING,
balance=1234.56,
currency="USD"
)
# Transaction model
transaction = Transaction(
transaction_id="txn001",
account_id="acc001",
transaction_type=TransactionType.DEPOSIT,
amount=500.00,
description="Paycheck deposit"
)from scope.data import Database
from scope.iam import User, UserRole
db = Database()
# Create user and account
db.create_user(user)
db.create_account(account)
# Get account (IAM-protected)
iam_user = User("user", UserRole.USER)
account = db.get_account(iam_user, "acc001") # β
Allowed (own account)
# Staff can view all accounts
staff = User("staff1", UserRole.STAFF)
account = db.get_account(staff, "acc001") # β
Allowed (staff privilege)
# Get transaction history
transactions = db.get_account_transactions(iam_user, "acc001", days=30)Database Location:
- Development:
scope/data/storage/banking.db(SQLite) - Production: Migrate to PostgreSQL/MySQL
Comprehensive audit logging and compliance-specific logging.
from scope.logging import get_audit_logger, AuditEventType
audit = get_audit_logger()
# Log user query
audit.log_user_query(
user_id="user",
query="What's my balance?",
response_action="ALLOW"
)
# Log account access
audit.log_account_access(
user_id="user",
account_id="acc001",
operation="view_balance"
)
# Log tool call
audit.log_tool_call(
user_id="user",
tool_name="get_account_balance",
parameters={"account_id": "acc001"},
result="$1,234.56"
)
# Log safety block
audit.log_safety_block(
user_id="user",
input_text="Offensive content",
risk_category="Offensive"
)from scope.logging import get_compliance_logger
compliance = get_compliance_logger()
# PCI-DSS: Log data access (Requirement 10.2)
compliance.log_pci_data_access(
user_id="user",
data_type="account",
account_id="acc001",
operation="read"
)
# PCI-DSS: Log authentication (Requirement 10.2.4)
compliance.log_pci_authentication(
user_id="user",
success=True,
method="oauth2",
ip_address="192.168.1.1"
)
# SOC2: Log access control decision (CC6.1)
compliance.log_soc2_access_control(
user_id="user",
resource="account_balance",
permission="VIEW_ACCOUNTS",
granted=True
)
# SOC2: Log incident (CC7.3)
compliance.log_soc2_incident(
user_id="user",
incident_type="unauthorized_access_attempt",
severity="medium",
description="Failed login attempt detected"
)Log Locations:
- Audit logs:
scope/logging/audit_logs/audit_YYYY-MM-DD.jsonl - PCI-DSS logs:
scope/logging/compliance_logs/pci_dss_YYYY-MM-DD.jsonl - SOC2 logs:
scope/logging/compliance_logs/soc2_YYYY-MM-DD.jsonl
Log Format: Structured JSON (one event per line)
{
"timestamp": "2025-11-28T12:00:00",
"event_type": "account_access",
"user_id": "user",
"action": "account_view",
"success": true,
"details": {"account_id": "acc001", "operation": "view_balance"}
}# Test all features
uv run pytest -v
# Test individual pillars
uv run pytest scope/safety/tests/ -v
uv run pytest scope/compliance/tests/ -v
uv run pytest scope/iam/tests/ -v
uv run pytest scope/escalation/tests/ -vTest Coverage:
- β Configuration loading (6 modules)
- β Compliance rule transformation
- β Escalation queue with SQLite
- β Role-based access control
- β Permission enforcement
- β Database operations with IAM
- β Audit and compliance logging
The agent can take 4 actions based on safety + compliance analysis:
| Action | When | Output |
|---|---|---|
| ALLOW | Safe & compliant | Pass to generator |
| REFUSE | Violates policy/rules | Polite refusal + reason |
| REWRITE | Unsafe but valid intent | Sanitized version |
| ESCALATE | Low confidence | Queue for human review |
{
"action": "ALLOW|REFUSE|REWRITE|ESCALATE",
"reasoning": "Brief explanation",
"violated_rule": "Rule #2",
"confidence": 0.75,
"rewritten_content": "..."
}ADK provides built-in tracing for complete observability:
uv run adk web
# Navigate to: http://127.0.0.1:8000
# Click any conversation β "Trace" tabYou'll see:
- π Every callback execution (before/after)
- π οΈ Every tool call with parameters and results
- π¬ Every LLM request and response
- β±οΈ Timing for each step
- β Errors and exceptions
- π Token usage and costs
# All actions are automatically logged
2025-11-28 12:00:00 - INFO - [SCOPE Layer 2] Checking input: What's my balance?
2025-11-28 12:00:00 - INFO - [SCOPE Layer 2] Passed.
2025-11-28 12:00:01 - INFO - [Tool] get_account_balance(user_id=user)
2025-11-28 12:00:01 - INFO - [Audit] User user queried balance: $1,234.56For real-time debugging without the web UI, use the terminal-based log viewer:
# View recent logs (interactive mode)
uv run python scope/logging/view_logs.py
# View specific event types
uv run python scope/logging/view_logs.py --event transaction_query
# Follow mode (tail logs)
uv run python scope/logging/view_logs.py --follow
from scope.config import Config
config = Config(
COMPLIANCE_RULES=[
"Never share internal metrics",
"Redirect pricing questions to sales team",
"Do not commit to feature timelines"
]
)config = Config(
IAM_ENABLED=True,
IAM_DEFAULT_USER_ROLE="USER",
IAM_REQUIRE_AUTHENTICATION=True,
IAM_SESSION_TIMEOUT_MINUTES=30
)config = Config(
ESCALATION_ENABLED=True,
ESCALATION_THRESHOLD=0.7, # Higher = fewer escalations
ESCALATION_STORAGE_TYPE="sqlite",
ESCALATION_AUTO_NOTIFY_ADMINS=True
)- google-adk - Agent Development Kit
- google-cloud-aiplatform - Vertex AI integration
- transformers - ML model pipelines
- torch - Deep learning runtime
- pydantic-settings - Configuration management
- pillow - Image processing
- numpy<2 - NumPy 1.x compatibility
- SQLite - Escalation queue storage (built-in)
- β Explicit profanity blocked by ML model (no LLM call)
- β Nuanced harmful requests caught by LLM reasoning
- β Compliance rules enforced with rule citations
- β Role-based access control working
- β Escalation queue with SQLite persistence
- β Multi-modal support (text + images)
- β Complete audit trail for all actions
example_config.py- Industry-specific configuration templatesTESTING.md- Comprehensive testing guidescope/*/tests/- Unit tests for each moduletests/test_agent_integration.py- Integration tests
For production banking applications:
- Database: Migrate from SQLite to PostgreSQL/MySQL
- Authentication: Integrate OAuth2/SAML for user identity
- Monitoring: Add OpenTelemetry, Prometheus, Grafana
- Compliance: Enable PCI-DSS, SOC2 audit logging
- Scaling: Deploy with Kubernetes, load balancing
- Backup: Automated backups for escalation queue and audit logs
This is a reference implementation of the SCOPE framework. Contributions welcome!
Apache-2.0