Audit logging records every intercepted HTTP and HTTPS transaction along with security events: PII detections, injection blocks, transformation applications, and network policy violations. Logs are streamed from the security proxy to the host orchestrator in real time and retrievable via the SDK.
Enable audit logging
from declaw import Sandbox, SecurityPolicy, AuditConfig
sbx = Sandbox.create(
security=SecurityPolicy(
audit=AuditConfig(enabled=True),
)
)
The shorthand audit=True is equivalent:
sbx = Sandbox.create(
security=SecurityPolicy(audit=True)
)
AuditConfig model
| Field | Type | Default | Description |
|---|
enabled | bool | False | Activate audit logging |
What gets logged
Every audit entry captures:
| Field | Type | Description |
|---|
timestamp | datetime | When the event occurred |
sandbox_id | str | Sandbox that produced the event |
event_type | str | Type of event (see below) |
direction | str | "outbound" or "inbound" |
destination | str | Target hostname or IP |
method | str | None | HTTP method (GET, POST, etc.) |
status_code | int | None | HTTP response status code |
pii_detections | list | PII types detected, counts, and actions |
injection_detected | bool | Whether an injection attempt was found |
transformation_applied | bool | Whether transformation rules matched |
blocked | bool | Whether the request/response was blocked |
policy_stage | str | Which pipeline stage logged the event |
Event types
| Event type | When it occurs |
|---|
request_allowed | A request passed all policy checks and was forwarded |
request_blocked | A request was blocked by network policy, PII, or injection defense |
pii_detected | PII was found (regardless of action taken) |
injection_detected | A prompt injection pattern was found |
transformation_applied | A transformation rule matched and replaced content |
domain_blocked | A domain was blocked by the network policy |
ip_blocked | An IP/CIDR was blocked by iptables |
Retrieve audit logs
entries = sbx.get_audit_log()
for entry in entries:
print(entry.timestamp, entry.event_type, entry.destination)
if entry.pii_detections:
for det in entry.pii_detections:
print(f" PII: {det.type} (count={det.count}, action={det.action})")
const entries = await sbx.getAuditLog();
for (const entry of entries) {
console.log(entry.timestamp, entry.eventType, entry.destination);
}
Audit with other security features
Audit logging captures events from all pipeline stages. Enable it alongside other features to get a full picture:
policy = SecurityPolicy(
pii=PIIConfig(
enabled=True,
types=["ssn", "credit_card", "email"],
action="redact",
),
injection_defense=InjectionDefenseConfig(
enabled=True,
action="block",
),
network=NetworkPolicy(
allow_out=["*.openai.com"],
deny_out=[ALL_TRAFFIC],
),
audit=AuditConfig(enabled=True),
)
With this policy, audit entries are created for:
- Every domain-blocked connection (e.g., a request to
google.com)
- Every PII detection (SSN found in outbound request body)
- Every injection detection (pattern found in inbound response)
- Every request that was blocked
- Every request that passed through successfully
Example audit entry
{
"timestamp": "2024-01-15T10:30:45.123Z",
"sandbox_id": "sbx-abc123",
"event_type": "pii_detected",
"direction": "outbound",
"destination": "api.openai.com",
"method": "POST",
"status_code": 200,
"pii_detections": [
{ "type": "ssn", "count": 1, "action": "redact" },
{ "type": "email", "count": 2, "action": "redact" }
],
"injection_detected": false,
"transformation_applied": false,
"blocked": false,
"policy_stage": "pii_scanner"
}
Blocked request audit entry
{
"timestamp": "2024-01-15T10:31:00.456Z",
"sandbox_id": "sbx-abc123",
"event_type": "domain_blocked",
"direction": "outbound",
"destination": "evil.com",
"method": "POST",
"blocked": true,
"policy_stage": "domain_filter"
}
Streaming audit events
Audit entries are streamed in real time from the security proxy to the host orchestrator via the envd gRPC channel. This means you can process events while the sandbox is still running.
Audit logs are stored in memory on the orchestrator and are not persisted to a database by default. Retrieve them with get_audit_log() before calling kill() or the logs will be lost. For persistent audit trails, integrate with an observability stack (Grafana, ClickHouse, etc.).
Log-only mode for visibility
Use audit logging alone (without blocking) to understand what traffic your agents generate before applying stricter policies:
# Phase 1: observe without blocking
policy = SecurityPolicy(
pii=PIIConfig(enabled=True, types=["ssn", "credit_card", "email"], action="log_only"),
injection_defense=InjectionDefenseConfig(enabled=True, action="log"),
audit=True,
)
# After reviewing logs, tighten to blocking
policy = SecurityPolicy(
pii=PIIConfig(enabled=True, types=["ssn", "credit_card", "email"], action="redact"),
injection_defense=InjectionDefenseConfig(enabled=True, action="block"),
audit=True,
)