Audit Logs
The audit_log table records every significant skill execution. With 259,547+ entries in production, it provides a comprehensive audit trail for debugging, security review, and usage analysis.
Schema
CREATE TABLE audit_log (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
skill_name VARCHAR(255) NOT NULL,
input_summary TEXT, -- Arguments (secrets redacted)
output_summary TEXT, -- Result (secrets redacted)
capability_level VARCHAR(20), -- safe, monitored, controlled, restricted, privileged
risk_level VARCHAR(20), -- low, medium, high (RESTRICTED+ only)
duration_ms INTEGER, -- Execution time in milliseconds
chat_id VARCHAR(255), -- Who triggered it
success BOOLEAN, -- Whether execution succeeded
created_at TIMESTAMPTZ DEFAULT NOW()
);
What Gets Logged
| Capability Level | Logged? | Notes |
|---|---|---|
| SAFE | No | calculate, datetime — no side effects |
| MONITORED | No | web_search, fetch_url — read-only |
| CONTROLLED | Yes | gmail, reminders, task_manager |
| RESTRICTED | Yes | shell, python_exec, http_request |
| PRIVILEGED | Yes | broker commands |
Secret Redaction
All input and output summaries are passed through redact() before writing:
from src.utils.redaction import redact
audit_entry.input_summary = redact(json.dumps(call.arguments))
audit_entry.output_summary = redact(result.output or "")
Redacted Patterns
| Pattern | Example |
|---|---|
| OpenAI keys | sk-[a-zA-Z0-9]{20,} |
| Anthropic keys | sk-ant-[a-zA-Z0-9-]{20,} |
| Google keys | AIza[a-zA-Z0-9-_]{35} |
| xAI keys | xai-[a-zA-Z0-9]{20,} |
| HuggingFace tokens | hf_[a-zA-Z0-9]{20,} |
| AWS access keys | AKIA[A-Z0-9]{16} |
| Stripe live keys | sk_live_[a-zA-Z0-9]{24} |
| Slack tokens | xox[bpoa]-[a-zA-Z0-9-]+ |
| SendGrid keys | SG\.[a-zA-Z0-9]{22}\.[a-zA-Z0-9]{43} |
| Bearer tokens | Bearer [a-zA-Z0-9+/=]{20,} |
| Password patterns | password[=:]\S+ |
Matched patterns are replaced with [REDACTED].
Common Queries
Recent Activity
docker exec agent-postgres psql -U agent -d agent -c "
SELECT skill_name, capability_level, duration_ms, success, created_at
FROM audit_log
ORDER BY created_at DESC
LIMIT 20;
"
Skill Usage Statistics (Last 24h)
docker exec agent-postgres psql -U agent -d agent -c "
SELECT
skill_name,
COUNT(*) as total_calls,
SUM(CASE WHEN success THEN 1 ELSE 0 END) as successes,
ROUND(AVG(duration_ms)) as avg_ms,
ROUND(100.0 * SUM(CASE WHEN success THEN 1 ELSE 0 END) / COUNT(*), 1) as success_rate
FROM audit_log
WHERE created_at > NOW() - INTERVAL '24 hours'
GROUP BY skill_name
ORDER BY total_calls DESC;
"
Error Analysis
docker exec agent-postgres psql -U agent -d agent -c "
SELECT skill_name, output_summary, created_at
FROM audit_log
WHERE success = false
AND created_at > NOW() - INTERVAL '7 days'
ORDER BY created_at DESC
LIMIT 30;
"
High-Risk Skill Calls
docker exec agent-postgres psql -U agent -d agent -c "
SELECT skill_name, input_summary, output_summary, created_at
FROM audit_log
WHERE capability_level IN ('restricted', 'privileged')
ORDER BY created_at DESC
LIMIT 20;
"
Per-User Activity
docker exec agent-postgres psql -U agent -d agent -c "
SELECT chat_id, COUNT(*) as calls, MAX(created_at) as last_active
FROM audit_log
WHERE created_at > NOW() - INTERVAL '7 days'
GROUP BY chat_id
ORDER BY calls DESC;
"
Audit Log Size
The audit log grows at approximately 1 MB per day under normal usage. At 259,547 entries:
- Size: ~50 MB
- Index on
created_atrecommended for large tables
Cleanup
# Delete entries older than 90 days
docker exec agent-postgres psql -U agent -d agent -c "
DELETE FROM audit_log
WHERE created_at < NOW() - INTERVAL '90 days';
"
# Vacuum to reclaim space
docker exec agent-postgres psql -U agent -d agent -c "VACUUM audit_log;"
Real-time Audit Streaming
To watch audit events in real-time:
# Poll every 5 seconds
watch -n5 'docker exec agent-postgres psql -U agent -d agent -c "
SELECT skill_name, capability_level, success, created_at
FROM audit_log
ORDER BY created_at DESC
LIMIT 5;
"'