Audit Logging
The compliance backbone — every agent action gets a log entry, every significant decision gets a record.
Standards alignment
| Standard |
What we use |
| OCSF |
Event class structure, severity levels |
| OpenTelemetry |
trace_id / span_id for workflow correlation |
| ISO 27001:2022 A.8.15 |
Mandatory fields: who, what, when, where |
Audit event format
Each log entry is one JSON object per line, appended to .compliance/audit.log. Full schema: skills/audit-logging/audit-event.schema.json.
Required fields
{
"event_id": "uuid-v4",
"timestamp": "ISO 8601",
"trace_id": "hex-32",
"event_class": "tool_call | decision | data_access | error",
"activity": "read | write | classify | scan | block | approve",
"severity": "INFO | LOW | MEDIUM | HIGH | CRITICAL",
"outcome": "success | failure | blocked | deferred",
"summary": "Human-readable one-liner"
}
Optional fields
Add only when relevant — keep log entries lean:
| Field |
When to include |
span_id |
Multi-step workflows (hex-16) |
parent_span_id |
Nested operations |
agent_id |
Multi-agent setups |
resource |
File/field/API being accessed — include classification if known |
tool |
Tool name + exit code for tool_call events |
decision |
Required for event_class: "decision" — see ADR below |
metadata |
Anything else worth preserving |
Agent Decision Record (ADR)
An audit event with event_class: "decision" and a decision block. Created when the agent:
- Blocks or allows a RESTRICTED data operation
- Answers a gap analysis question autonomously
- Encounters conflicting information
- Invokes external tools with security implications
Decision block
"decision": {
"action": "block | approve | defer",
"reasoning": "Why this action was taken",
"policy_ref": "GDPR Art. 9 | NIS2 Art. 21(2)(h) | ...",
"human_override": false
}
Storage
- Location:
.compliance/audit.log (project root)
- Format: append-only, one JSON object per line
- Rotation: optional daily files (
audit-YYYY-MM-DD.log)
- Integrity: UUID per event, sequence breaks detectable
- Central collection: Push to cloud storage via the compliance-hub skill
Retention guidance
| Entity type (NIS2) |
Minimum |
Recommended |
| Essential |
18 months |
24 months |
| Important |
6 months |
12 months |
| Voluntary |
3 months |
6 months |
Logging in AI-generated code
When writing code, include structured logging for: auth events, authorization, data access, data modification, external API calls, errors, config changes, batch jobs. Use structured key-value pairs — never string interpolation. Never log secrets, PII, or session tokens.
For the full operations table, correct/wrong code examples per language, what-not-to-log rules, and language-specific logger recommendations, see references/logging-guide.md.
Agent instructions
Follow this process every session:
- Session start — generate a
trace_id (32-char hex). Use it for all events in this session.
- Per step — generate a
span_id (16-char hex) for each discrete operation.
- Before tool execution — log a
tool_call event with the tool name.
- After tool execution — update with outcome and exit code.
- On any decision involving classified data — create an ADR with the decision block.
- Append each event as a single JSON line to
.compliance/audit.log.
- PROACTIVE — when writing code: Whenever you generate, write, or modify source code, you MUST include proper structured audit logging following the rules above. This is not optional. Specifically:
- Add logging imports/setup if the file doesn't have them
- Add structured log statements for every operation listed in the mandatory logging table
- Use the correct structured format for the language (no string interpolation)
- Include correlation IDs (
trace_id, request_id) where the framework supports it
- NEVER log sensitive data — follow the "what MUST NOT be logged" table
- When modifying existing code, add logging to any new or changed code paths
- When reviewing AI-generated code: Check that all operations have structured logging. Flag missing logging as a compliance gap.
Example log entry
{"event_id":"a1b2c3d4-...","timestamp":"2026-03-13T10:15:00Z","trace_id":"abc123...","event_class":"tool_call","activity":"scan","severity":"INFO","outcome":"success","summary":"Scanned src/ for sensitive data patterns","tool":{"name":"data-sensitivity","exit_code":0}}
Example ADR
{"event_id":"e5f6g7h8-...","timestamp":"2026-03-13T10:15:05Z","trace_id":"abc123...","event_class":"decision","activity":"block","severity":"HIGH","outcome":"blocked","summary":"Blocked commit containing BSN","resource":{"type":"file","id":"src/users.py","classification":"RESTRICTED"},"decision":{"action":"block","reasoning":"File contains plaintext BSN (national ID)","policy_ref":"GDPR Art. 87","human_override":false}}
1---2name: audit-logging3description: ACTIVATE on ANY request that involves writing, generating, reviewing, modifying, or outputting source code in any programming language — Python, JavaScript, TypeScript, Go, Java, Rust, C#, SQL, Terraform, or any other. This includes functions, endpoints, scripts, migrations, infrastructure-as-code, config files with logic, and code snippets in responses. Every piece of code the LLM produces must include structured audit logging for security-relevant operations. Also activate when the user asks about audit logs, compliance logging, or traceability. Ensures NIS2 and ISO 27001 compliant logging (structured, no string interpolation, no secrets in logs).4---56# Audit Logging78> The compliance backbone — every agent action gets a log entry, every significant decision gets a record.910## Standards alignment1112| Standard | What we use |13|----------|------------|14| OCSF | Event class structure, severity levels |15| OpenTelemetry | `trace_id` / `span_id` for workflow correlation |16| ISO 27001:2022 A.8.15 | Mandatory fields: who, what, when, where |1718## Audit event format1920Each log entry is one JSON object per line, appended to `.compliance/audit.log`. Full schema: `skills/audit-logging/audit-event.schema.json`.2122### Required fields2324```json25{26 "event_id": "uuid-v4",27 "timestamp": "ISO 8601",28 "trace_id": "hex-32",29 "event_class": "tool_call | decision | data_access | error",30 "activity": "read | write | classify | scan | block | approve",31 "severity": "INFO | LOW | MEDIUM | HIGH | CRITICAL",32 "outcome": "success | failure | blocked | deferred",33 "summary": "Human-readable one-liner"34}35```3637### Optional fields3839Add only when relevant — keep log entries lean:4041| Field | When to include |42|-------|----------------|43| `span_id` | Multi-step workflows (hex-16) |44| `parent_span_id` | Nested operations |45| `agent_id` | Multi-agent setups |46| `resource` | File/field/API being accessed — include `classification` if known |47| `tool` | Tool name + exit code for tool_call events |48| `decision` | **Required** for `event_class: "decision"` — see ADR below |49| `metadata` | Anything else worth preserving |5051## Agent Decision Record (ADR)5253An audit event with `event_class: "decision"` and a `decision` block. Created when the agent:5455- Blocks or allows a RESTRICTED data operation56- Answers a gap analysis question autonomously57- Encounters conflicting information58- Invokes external tools with security implications5960### Decision block6162```json63"decision": {64 "action": "block | approve | defer",65 "reasoning": "Why this action was taken",66 "policy_ref": "GDPR Art. 9 | NIS2 Art. 21(2)(h) | ...",67 "human_override": false68}69```7071## Storage7273- **Location**: `.compliance/audit.log` (project root)74- **Format**: append-only, one JSON object per line75- **Rotation**: optional daily files (`audit-YYYY-MM-DD.log`)76- **Integrity**: UUID per event, sequence breaks detectable77- **Central collection**: Push to cloud storage via the compliance-hub skill7879## Retention guidance8081| Entity type (NIS2) | Minimum | Recommended |82|--------------------|---------|-------------|83| Essential | 18 months | 24 months |84| Important | 6 months | 12 months |85| Voluntary | 3 months | 6 months |8687## Logging in AI-generated code8889When writing code, include structured logging for: auth events, authorization, data access, data modification, external API calls, errors, config changes, batch jobs. Use structured key-value pairs — never string interpolation. Never log secrets, PII, or session tokens.9091For the full operations table, correct/wrong code examples per language, what-not-to-log rules, and language-specific logger recommendations, see [references/logging-guide.md](references/logging-guide.md).9293## Agent instructions9495Follow this process every session:96971. **Session start** — generate a `trace_id` (32-char hex). Use it for all events in this session.982. **Per step** — generate a `span_id` (16-char hex) for each discrete operation.993. **Before tool execution** — log a `tool_call` event with the tool name.1004. **After tool execution** — update with outcome and exit code.1015. **On any decision involving classified data** — create an ADR with the decision block.1026. **Append** each event as a single JSON line to `.compliance/audit.log`.1037. **PROACTIVE — when writing code**: Whenever you generate, write, or modify source code, you MUST include proper structured audit logging following the rules above. This is not optional. Specifically:104 - Add logging imports/setup if the file doesn't have them105 - Add structured log statements for every operation listed in the mandatory logging table106 - Use the correct structured format for the language (no string interpolation)107 - Include correlation IDs (`trace_id`, `request_id`) where the framework supports it108 - NEVER log sensitive data — follow the "what MUST NOT be logged" table109 - When modifying existing code, add logging to any new or changed code paths1108. **When reviewing AI-generated code**: Check that all operations have structured logging. Flag missing logging as a compliance gap.111112### Example log entry113114```json115{"event_id":"a1b2c3d4-...","timestamp":"2026-03-13T10:15:00Z","trace_id":"abc123...","event_class":"tool_call","activity":"scan","severity":"INFO","outcome":"success","summary":"Scanned src/ for sensitive data patterns","tool":{"name":"data-sensitivity","exit_code":0}}116```117118### Example ADR119120```json121{"event_id":"e5f6g7h8-...","timestamp":"2026-03-13T10:15:05Z","trace_id":"abc123...","event_class":"decision","activity":"block","severity":"HIGH","outcome":"blocked","summary":"Blocked commit containing BSN","resource":{"type":"file","id":"src/users.py","classification":"RESTRICTED"},"decision":{"action":"block","reasoning":"File contains plaintext BSN (national ID)","policy_ref":"GDPR Art. 87","human_override":false}}122```