How It Works
Each tool call the agent makes is appended to the audit log before the result returns to the user.Quick Start
1
Enable audit logging
2
Close on shutdown
What’s Logged
Each JSONL line records:timestamp,session_id,agent_nametool_name,tool_input,execution_time_ms- Optional
tool_output(wheninclude_output=True)
after_tool automatically when you call enable_audit_log().
Log Rotation
Audit records keep landing on the live file after an external rotator moves or removes it — no user action, no descriptor leak (PR #4205). Each write compares the inode behind the open handle against the inode on the log path; when they differ (or the path is gone), the stale handle is closed and the path reopened at0o600 before the line is appended.
Secret Redaction
Sensitive values intool_input are replaced with ***REDACTED*** before the JSONL line is written — on by default, no configuration needed.
Key matching is case-insensitive and recurses through nested dicts, lists, and tuples. The built-in denylist (_DEFAULT_SENSITIVE_KEYS in praisonai/security/audit.py):
File permissions. The audit file is created with mode
0o600 (owner read/write only) regardless of umask. This is enforced on the first append even if the file already exists.Configuration
enable_audit_log() and enable_security() accept only log_path and include_output — they do not yet forward redactor or sensitive_keys. To customise redaction, instantiate AuditLogHook directly and register it with add_hook("after_tool", ...) (see below).Customising Redaction
InstantiateAuditLogHook directly for full control over redaction.
Pick the option that fits your situation:
sensitive_keys only affects the built-in redactor. A redactor= callable you supply is used exactly as given — the class does not merge it with the default.
Thread Safety (PR #2062)
- Uses
threading.Lockfor concurrent multi-agent writes - Rotation-safe: each write
stats the log path and reopens when the on-disk inode differs from the open handle (recovers fromlogrotate,mv, orrmmid-run) — added in PR #4205 - Each write calls
fsyncfor crash durability - Call
get_audit_log().close()on shutdown to flush and release the handle
Best Practices
Enable early in production
Enable early in production
Call
enable_audit_log() before creating agents so every tool invocation is captured from the first turn — retrofitting mid-session misses earlier calls.Close on shutdown
Close on shutdown
Call
get_audit_log().close() in your shutdown handler to flush the file handle. Long-running daemons that skip this may lose the last buffered line on crash.Keep output logging selective
Keep output logging selective
Leave
include_output=False unless you need forensic replay. When enabled, tune max_output_chars to avoid bloating the JSONL with large tool payloads. Redaction covers tool_input only — outputs are written verbatim.Verify redaction after enabling
Verify redaction after enabling
Grep your audit file for known-sensitive strings once, especially if your tools use exotic key names not in the default denylist. If you see leaks, extend
sensitive_keys or supply a custom redactor on a directly-instantiated AuditLogHook.Rotate and protect log files
Rotate and protect log files
Store logs outside web-served directories. The file is created
0o600 (owner-only) by default, and the audit path is protected — do not disable Protected Paths on production hosts. External rotators (logrotate, container log drivers, cron mv + HUP) are supported directly — the writer reopens the live file on the next write, so you never need to signal the process (PR #4205).Related
Security Overview
Enable audit log with other security features
Protected Paths
Audit log file is itself protected

