What Gets Logged
Comis generates audit events for a wide range of security-relevant actions. These include agent executions, tool invocations, secret access, message sends, approval decisions, and any action that is denied or times out. Every event is structured as JSON, making it machine-readable from the start. Each audit event captures a set of fields that tell you exactly what happened:
Not every field is present in every event. For example, background tasks may not have a User ID, and read-only actions may not include a Duration.
Common Audit Actions
Here are some of the actions you will see most frequently in your audit logs:
For the complete list of all action classifications (178 actions across 21 categories), see the Action Classifier Reference.
Example Audit Log Entry
A real (sanitized) audit event — one scrubbed line from~/.comis/logs/security-audit.jsonl (the same shape appears as a .audit()-level
line in ~/.comis/logs/daemon.*.log and as a row in the obs_audit_events table):
metadata object never contains the secret values themselves —
only the names of secrets that were accessed and the paths involved. The
msg field is constant ("Audit event") so structured queries key off the
audit boolean and the typed fields above.
Viewing Audit Logs
There are four ways to access your audit events, depending on your needs.Query the durable audit (CLI / RPC / agent tool)
The audit is a durable, queryable store (theobs_audit_events SQLite table).
Query it directly — filter by kind, classification, agent, tenant, outcome, and a
time window — through any of three admin-gated surfaces backed by the same
obs.audit.query RPC:
obs_query tool
({action:"audit", filters:{kind?, classification?, agentId?, tenant?, outcome?, since?, until?, limit?}}) and over JSON-RPC as obs.audit.query. All three
return content-free rows — ids, the closed-enum fields, and a scrubbed refs
blob; never a secret value. This is the best option for “what security-relevant
actions ran, by whom, and how many” — including after a restart.
Web Dashboard
The easiest way to view audit events. Open the Security dashboard and click the Audit Log tab. You can filter by agent, action, classification, and time range. The dashboard displays events in reverse chronological order, so you always see the most recent activity first. Click any event row to expand it and see the full event details including the trace ID, which you can use to correlate the event with other log entries from the same request. This is the best option for quick investigations or spot-checking agent behavior.Structured Log Files
Audit events are written to the dedicated~/.comis/logs/security-audit.jsonl
file — one scrubbed JSON line per event (0600, rotated under
observability.logRotation) — and ALSO appear as .audit()-level (35) lines in
the standard structured log (~/.comis/logs/daemon.*.log). Each is a single JSON
line, easy to parse with standard tools:
comis security audit-log (above) — it reads the same events from the durable
obs_audit_events table.
Log Aggregation
For production deployments, forward Comis logs to your preferred log aggregation service — Datadog, Elasticsearch, Grafana Loki, Splunk, or similar. The structured JSON format makes it straightforward to create dashboards, alerts, and retention policies based on audit events. Common aggregation patterns include:- Alert on denied actions — Get notified when agents are blocked from performing actions
- Track destructive action frequency — Monitor how often agents attempt high-risk operations
- Compliance reporting — Generate periodic reports of all security-relevant activity
Event Aggregation (Sliding-Window Dedup)
When the same event fires many times in quick succession — for example, a user repeatedly triggering jailbreak detection — Comis aggregates these events using a sliding 60-second window per event source. Instead of flooding your logs with hundreds of identical entries, you see a single aggregated event with a count. This keeps your audit log readable without losing information. Events are bucketed by source type —user_input, tool_output, external_content, memory_write — so a flood of jailbreak detections in user input does not suppress a separate flood in memory writes. The first event in a window opens a bucket and arms a setTimeout; subsequent events in the same window increment the count and add their unique patterns (up to 10 per summary). When the timer fires, a single security:injection_detected summary event is emitted with the accumulated count and patterns.
Aggregated summaries include:
- The source type (user_input, tool_output, external_content, memory_write)
- A count of how many times the event occurred in the window
- Up to 10 unique patterns that triggered the detection
- The time window over which events were grouped
unref() so a pending aggregation does not block daemon shutdown, and the aggregator’s flush() method emits all pending summaries immediately on demand. This deduplication is automatic and requires no configuration.
Storage and Retention
Every audit event is persisted to a durable, queryable store and also emitted on the in-memory bus for real-time consumers. The two durable sinks that survive a daemon restart are the obs_audit_events SQLite table (the queryable store of record) and the security-audit.jsonl file (the greppable on-disk trail); the daemon log carries the same event as a structured.audit()-level line but is
not the store of record:
The
obs_audit_events rows and the security-audit.jsonl lines are the
authoritative durable record — they persist across restarts independent of any
external log stack. Comis does not impose a retention policy on the JSONL/log
files beyond the size-based rotation configured under observability.logRotation;
SQLite-row retention follows observability.persistence.retentionDays. The
aggregator’s in-memory state is only the current sliding window; once a summary
fires, the bucket is freed.
Trace Correlation
Every audit event includes a Trace ID that connects it to the full request lifecycle. If an agent execution generates multiple audit events — for example, reading a secret, calling a tool, and sending a message — all of those events share the same Trace ID. This makes it straightforward to reconstruct what happened during a single agent execution, even when reviewing logs from a production system with many agents running simultaneously. When investigating an incident, start with the audit event that caught your attention, note its Trace ID, and filter your logs for that ID to see the complete picture.Log Redaction
Comis automatically scrubs sensitive values from all log output, including audit events. If an API key, password, JWT token, or other credential accidentally appears in a log message, it is replaced with[REDACTED] before being written. This prevents credentials from ending up in log files, log aggregation dashboards, or error reports.
Log redaction works alongside audit logging — audit events record what actions were taken without exposing the sensitive data involved in those actions. For example, an audit event records that an agent accessed a secret named OPENAI_API_KEY, but the actual key value never appears in the log.
Credential Broker Events
The credential broker emits 7 typed events on the daemon event bus. All event payloads are redaction-by-construction — no secret value ever appears in any event field.
The
broker:egress_blocked event deliberately carries targetHostHash (SHA-256 hex) rather than the plaintext hostname — even blocked egress targets are not logged in plaintext (redaction-by-construction).
The secret:accessed event is also emitted by the broker for each per-request SecretManager resolution, separately from the broker:* taxonomy. Fields: secretName, agentId, outcome (success/denied/not_found), timestamp. This lets you audit which secrets an agent touched. The durable audit trail records success reads (a secret was actually accessed) and denied reads (a blocked access — the security signal); a routine not_found read (an optional-key probe that resolved to nothing — no access occurred, and re-emitted every turn) is not persisted, so the trail stays legible instead of being dominated by per-turn probe noise.
Source:
packages/infra/src/credential-broker/broker-events.tsConfiguration
Audit logging is controlled by two settings in your configuration:~/.comis/config.yaml
Audit logging is enabled by default. You generally should not disable it, especially in production. If you need to reduce log volume, consider using log aggregation with filtering rather than turning off audit events entirely.
Related
Security Dashboard
View audit logs in the web UI
Defense in Depth
All security layers that generate audit events
Hardening
Verify audit logging in the hardening checklist
Logging
General logging configuration
