Audit Trail
What is the audit trail?
Section titled “What is the audit trail?”Pinchy includes a built-in audit trail that logs every significant action on the platform. Each entry is cryptographically signed with HMAC-SHA256 to detect tampering. The audit log is append-only — PostgreSQL triggers prevent any modification or deletion of existing entries.
The audit trail is designed for compliance and security. It answers the question: “Who did what, and when?”

What gets logged
Section titled “What gets logged”Pinchy logs event types across seven categories:
Tool execution
Section titled “Tool execution”| Event Type | Description |
|---|---|
tool.<toolName> | An agent executed a tool — event type is dynamic per tool (e.g. tool.shell, tool.pinchy_read, tool.fs_read) |
tool.denied | An agent attempted to use a tool that was not in its allow-list |
Each tool execution produces one audit entry — logged when the tool call completes (end phase only). The detail includes the tool name, parameters, and result. Start events are received but not persisted.
Event Status
Section titled “Event Status”Every entry in the audit log — not just tool calls — carries a status that shows whether the action succeeded or failed:
- A green check mark indicates a successful event (a login, an agent update, a tool call that returned cleanly, a config change, etc.).
- A red X indicates a failure (e.g., a failed login, a denied tool, a tool call that errored out, or any other event marked as a failure).
- Legacy entries from before this feature was added show a neutral ”—” with a “Logged before status tracking” tooltip. The schema did not track success/failure at the time. This is normal and not an integrity issue.
You can filter the audit log by status using the Status dropdown above the table. Filtering applies to every event type, not just tool calls:
- All Statuses — show every entry.
- Success only — only successful events. Legacy entries are excluded.
- Failures only — only failed events. This surfaces
auth.failedattempts, denied or errored tool calls, and anything else marked as a failure — useful for spotting recurring problems quickly.
The Event Type filter and Status filter are complementary. Combine them to answer questions like “all failed Auth events in the last 24 hours” or “all failed tool calls for this agent”.
When viewing a failed event’s detail, the error message is shown prominently above the raw event JSON, so you don’t have to dig through the detail blob to find the cause.
The Status column is also included in CSV exports, alongside an Error column with the failure message. Status filtering applies to exports too.
Authentication
Section titled “Authentication”| Event Type | Description |
|---|---|
auth.login | A user successfully logged in |
auth.failed | A login attempt failed (wrong password, unknown email) |
auth.logout | A user logged out |
Agent management
Section titled “Agent management”| Event Type | Description |
|---|---|
agent.created | A new agent was created |
agent.updated | An agent’s settings or permissions were changed |
agent.deleted | An agent was deleted |
User management
Section titled “User management”| Event Type | Description |
|---|---|
user.invited | An admin invited a new user |
user.updated | A user’s profile was changed |
user.role_updated | A user’s role was changed (e.g. member → admin) |
user.groups_updated | A user’s group memberships were changed |
user.deleted | A user account was deleted |
Group management
Section titled “Group management”| Event Type | Description |
|---|---|
group.created | A new group was created |
group.updated | A group’s settings were changed |
group.deleted | A group was deleted |
group.members_updated | Members were added to or removed from a group |
Channel management
Section titled “Channel management”| Event Type | Description |
|---|---|
channel.created | An agent was connected to an external channel (e.g. a Telegram bot token was added) |
channel.deleted | An agent was disconnected from a channel (or all channels of one type were removed) |
Configuration
Section titled “Configuration”| Event Type | Description |
|---|---|
config.changed | A system configuration setting was changed (e.g., provider API key) |
What is NOT logged
Section titled “What is NOT logged”Chat messages are not logged in the audit trail. The audit trail records actions and events, not conversation content. Chat messages are stored separately in the conversation history managed by OpenClaw.
Sensitive data redaction
Section titled “Sensitive data redaction”Tool parameters and results are automatically sanitized before being stored in the audit log. This prevents accidental exposure of secrets such as API keys, passwords, or tokens.
What gets redacted
Section titled “What gets redacted”- Sensitive field names — Any JSON field whose name contains
password,secret,token,apiKey,credential, or similar terms has its value replaced with[REDACTED]. - Known secret patterns — String values matching known formats (OpenAI keys
sk-…, GitHub tokensghp_…, Slack tokensxoxb-…, Bearer tokens, Telegram bot tokens, Meta access tokens, and others) are replaced with[REDACTED]. - Environment file content — When a tool reads a file containing lines like
SECRET_KEY=value, the value portion is redacted while the key name is preserved.
Defense in Depth
Section titled “Defense in Depth”Sanitization runs at two layers:
- Plugin layer — The
pinchy-auditOpenClaw plugin redacts sensitive data before sending it to Pinchy over HTTP. Secrets never leave the agent runtime. - API layer — The tool-use endpoint redacts again before writing to the database. This catches anything the plugin layer might have missed.
The redaction rules are built-in and require no configuration.
How HMAC signing works
Section titled “How HMAC signing works”Each audit log entry is signed with HMAC-SHA256 to ensure integrity:
- When an audit event occurs, Pinchy constructs a payload from the entry’s fields (event type, actor, timestamp, metadata).
- The payload is signed using a server-side HMAC secret.
- The resulting signature is stored alongside the entry in the
hmaccolumn. - The HMAC secret is auto-generated at startup if the
AUDIT_HMAC_SECRETenvironment variable is not set.
If anyone modifies a row directly in the database, the HMAC signature will no longer match — and integrity verification will flag the tampered entry.
How to verify integrity
Section titled “How to verify integrity”Admins can verify the integrity of the audit log in two ways:
Via the admin UI
Section titled “Via the admin UI”- Navigate to the Audit page in the admin area.
- Click the Verify Integrity button.
- Pinchy recomputes HMAC signatures for all entries and reports any mismatches.
Via the API
Section titled “Via the API”Send a GET request to /api/audit/verify. Optional fromId and toId parameters let you verify a specific range of entries.
curl -b session_cookie https://your-pinchy-instance/api/audit/verifyThe response indicates whether all entries are intact:
{ "valid": true, "totalChecked": 142, "invalidIds": []}If tampered entries are found, valid is false and invalidIds contains the IDs of the affected rows.
CSV export for compliance
Section titled “CSV export for compliance”The audit log can be exported as a CSV file for external compliance tools, auditors, or archival:
Via the admin UI
Section titled “Via the admin UI”- Navigate to the Audit page.
- Apply any desired filters (date range, event type, user).
- Click Export CSV.
Via the API
Section titled “Via the API”Send a GET request to /api/audit/export with optional filter parameters (eventType, actorId, from, to).
curl -b session_cookie "https://your-pinchy-instance/api/audit/export?from=2026-01-01&to=2026-02-01" -o audit-log.csvImmutability guarantees
Section titled “Immutability guarantees”The audit trail uses multiple layers to ensure entries cannot be modified:
- PostgreSQL triggers —
BEFORE UPDATEandBEFORE DELETEtriggers on theauditLogtable raise an exception, preventing any modification or deletion at the database level. - HMAC signatures — Even if triggers were somehow bypassed, any modification would invalidate the cryptographic signature.
- Append-only API — The application code only inserts entries. There is no update or delete endpoint for audit entries.
Fire-and-forget pattern
Section titled “Fire-and-forget pattern”Audit logging uses a fire-and-forget pattern: if logging fails (e.g., database connection issue), the main operation still succeeds. This ensures that audit logging never degrades the user experience or blocks critical operations.
The trade-off is that in rare failure scenarios, an action might not be logged. For most enterprise deployments, this is preferable to having audit logging cause outages.
Access control
Section titled “Access control”Only admins can access the audit trail — both the UI page and the API endpoints. Regular users cannot view, verify, or export audit entries.