Skip to main content

Logs

WASP emits structured JSON logs via structlog with consistent event= naming. There are four log surfaces:

SurfaceWherePurpose
Container logsdocker compose logs <service>Stdout/stderr of each service
Structured logs/data/logs/ (volume agent-logs)JSON event stream
AuditLogPostgres audit_log tablePer-action audit trail
Decision TraceRedis (TTL ~24h) → /tracesPer-response forensic record

Container logs

docker compose logs agent-core --tail=200
docker compose logs -f agent-core # follow
docker compose logs --since=1h agent-core # last hour

Pipe to grep to filter by event:

docker compose logs agent-core --since=1h | grep behavioral.queue_cap_trimmed
docker compose logs agent-core --tail=500 | grep model_manager.overflow_recovered

Structured logs (/data/logs/)

The agent-logs volume mounts /data/logs/ inside agent-core. Files there are JSON-line format. Each line has at least:

{
"timestamp": "2026-04-30T15:00:00Z",
"level": "INFO",
"event": "policy.intent_gate.blocked",
"skill": "gmail",
"reason": "no_explicit_intent",
"chat_id": "..."
}

Common event names:

EventWhen
policy.intent_gate.blockedIntent gate dropped a side-effect skill
policy.action_announcer.strippedAction announcer removed an unverified claim
policy.response_guard.appliedResponse guard fired (schedule honesty / grounding / sanitizer)
behavioral.queue_cap_trimmedBehavioral queue evicted items at the 50-cap
behavioral.rule_conflict_detectedNew rule contradicts an existing one
model_manager.overflow_recoveredCompaction overflow successfully recovered
self_improve.soft_gate_analysisSelf-improve patch passed/blocked by soft gate
goal_orchestrator.replan_stormGoal hit replan storm threshold
cpi.highCPI exceeded 80; background jobs paused
boot.model_unreachableBoot model liveness ping failed
auto_detect.multi_url_exemptMulti-URL aggregator exemption applied

AuditLog

Postgres table; recorded for every CONTROLLED, RESTRICTED, and PRIVILEGED skill call. Query directly:

SELECT timestamp, action, input_summary, output_summary, error
FROM audit_log
WHERE chat_id = '<your-chat-id>'
ORDER BY timestamp DESC
LIMIT 50;

Or use the dashboard /audit page (keyset pagination, filterable by chat_id and date).

Action types recorded:

ActionTriggered by
skill.shellEvery shell skill call (with redacted command)
skill.self_improveEvery read/propose/apply/patch/install
skill.gmailEvery Gmail send/read/delete
skill.task_managerEvery task create/delete/trigger
skill.agent_managerEvery sub-agent CRUD
skill.python_execEvery python_exec invocation
skill.http_requestEvery http_request invocation
agent.resetEvery Panic Reset
goal.created / goal.completed / goal.failedGoal lifecycle

All input/output summaries pass through redact() to strip API keys, tokens, and key=value passwords. Shell commands additionally pass through _redact_command() before logging.

Decision Trace

Every response — fast-path, Decision Layer route, or full LLM loop — emits a DecisionTrace:

DecisionTrace(
request_id, path, chat_id, user_text_hash,
request_tier, # simple | normal | complex
detected_language, detected_intent,
allowed_skills, blocked_skills,
guard_actions, # which guards fired and why
notes, start_ts, end_ts, latency_ms,
)

Stored in Redis with TTL ~24h. Surfaced at /traces.

Each trace tells the full story: which fast-paths matched, which skills the LLM tried, which were blocked and why, which guards modified the response, total latency.

Reading a trace

When you see a surprising response, open /traces and find the request. Look at:

FieldWhat it tells you
pathtelegram or dashboard
request_tierSimple / normal / complex (drives the request budget)
detected_languageShould match user's language
detected_intentDid the classifier read the request correctly?
allowed_skillsWhat the LLM tried to call
blocked_skillsWhat the policy layer dropped, with reason
guard_actionsList of (guard_name, action, reason) tuples
notesAny free-form annotation from the pipeline
latency_msTotal response time

If you see intent_gate.blocked for gmail, the user message did not match the email-send regex. If you see enforce_schedule_honesty.applied, the user requested a clock time and a disclaimer was appended. If you see factual_grounding.applied, a fabricated verdict was replaced with an honest fallback.

Log retention

LayerRetentionHow
Container logsDocker daemon (host config)Configure --log-opt max-size=...
Structured logs (/data/logs/)Operator-managedAdd log rotation cron
AuditLogAUDIT_RETENTION_DAYS (default 30)AuditRetentionJob runs daily, bounded batch deletes
Decision Trace~24h TTLRedis automatic
Memory snapshotsOperator-managedBackup cron (see Scaling)

See also