What events are automatically written to activity_log, the schema (actor, action, entity_type, entity_id, before/after snapshots, metadata), querying by time range, and CSV export.
Paperclip's complete audit trail — what is logged automatically, how to query it for compliance, and how to export it for external reporting.
| Event | Table | Key fields |
|---|---|---|
| Every heartbeat run | heartbeat_runs |
status, cost, timing |
| Every LLM call | cost_events |
model, tokens, cost, agent |
| Every issue state change | issues |
status, result, timestamps |
| Every approval | approvals |
trigger, decision, reviewer, note |
| Every agent status change | agents (+ history table) |
old/new status, changed_at |
The issues table already contains the full story:
SELECT
id,
title,
status,
attempt_count,
created_at,
claimed_at,
resolved_at,
EXTRACT(epoch FROM (resolved_at - created_at)) / 60 AS minutes_to_resolve,
LEFT(result, 100) AS result_preview
FROM issues
WHERE company_id = 'your-company-id'
ORDER BY created_at DESC;
Paperclip records changes to agent configuration in a separate audit table:
-- If your schema has an agent_audit table:
SELECT
aa.changed_at,
aa.changed_field,
aa.old_value,
aa.new_value,
aa.changed_by -- 'heartbeat', 'api', or a user email
FROM agent_audit aa
WHERE aa.agent_id = 'your-agent-id'
ORDER BY aa.changed_at DESC;
For SOC2/ISO27001 evidence packages, export a full activity log:
COPY (
SELECT
'issue' AS record_type,
i.id::text AS record_id,
i.title AS description,
i.status,
a.name AS actor,
i.created_at AS occurred_at,
i.resolved_at AS completed_at
FROM issues i
LEFT JOIN agents a ON a.id = i.assigned_agent_id
WHERE i.company_id = 'your-company-id'
UNION ALL
SELECT
'approval',
ap.id::text,
ap.trigger,
ap.status,
COALESCE(ap.human_reviewer_email, req.name),
ap.created_at,
ap.decided_at
FROM approvals ap
LEFT JOIN agents req ON req.id = ap.requesting_agent_id
WHERE ap.company_id = 'your-company-id'
UNION ALL
SELECT
'cost_event',
ce.id::text,
ce.model || ': ' || ce.input_tokens || '+' || ce.output_tokens || ' tokens',
'recorded',
a.name,
ce.created_at,
NULL
FROM cost_events ce
JOIN agents a ON a.id = ce.agent_id
WHERE ce.company_id = 'your-company-id'
AND ce.created_at >= '2024-01-01'
ORDER BY occurred_at
) TO '/tmp/audit_export.csv' CSV HEADER;
Paperclip never automatically deletes audit records. Implement your own retention policy:
-- Archive records older than 1 year to a cold storage table
INSERT INTO issues_archive SELECT * FROM issues
WHERE created_at < now() - interval '1 year'
AND company_id = 'your-company-id';
DELETE FROM issues
WHERE created_at < now() - interval '1 year'
AND company_id = 'your-company-id';