how to audit queries an agent ran
Builds an audit trail of every query an agent ran by tagging queries with a session id and pulling warehouse query history into an append-only audit table nightly. Use when compliance asks what the agent touched, when debugging a bad agent-driven change, or when you need the agent's database activity joined to its action log. Do not use for real-time monitoring, for auditing human users, or as a substitute for preventing bad queries in the first place.
TL;DR
Tag every agent query with a unique session id in a query tag or comment, then pull the warehouse query history filtered by that tag into an append-only audit table every night. If you cannot list everything the agent ran last Tuesday, you do not have an audit trail, you have vibes. It works because the warehouse history is ground truth: the agent's own logs can be lost or misleading, but the database remembers every statement it executed.
how to audit queries an agent ranUse this when
- Compliance or security asks what the agent touched
- You are debugging a bad change the agent made
- You need the agent's database activity joined to its action log
- Multiple agents share a warehouse and you need per-agent attribution
Not for
- Real-time monitoring, history views lag by minutes to hours
- Auditing human users, who need their own attribution scheme
- Preventing bad queries, which needs gates before execution
Steps
- Inject a session tag into every query the agent issues:
-- Snowflake: set once per agent session
ALTER SESSION SET QUERY_TAG = 'agent_id=agent-7 session=2026-10-04-001';
-- Postgres: embed in a comment the history views preserve
/* agent_id=agent-7 session=2026-10-04-001 */ SELECT * FROM reporting.orders LIMIT 100;Expected output: the tag travels with the query into the warehouse history, becoming the join key between what the agent did and what the database ran.
- Pull the tagged queries from the history views nightly:
-- Snowflake: all queries from agent sessions in the last day
SELECT query_id, user_name, query_text, query_tag,
total_elapsed_time, bytes_scanned, start_time
FROM snowflake.account_usage.query_history
WHERE query_tag LIKE 'agent_id=%'
AND start_time > DATEADD(day, -1, CURRENT_TIMESTAMP());Expected output: one row per executed query with text, timing, and bytes scanned, filtered to agent traffic only.
- Land the results in an append-only audit table:
INSERT INTO ops.agent_query_audit
(query_id, agent_id, session_id, query_text, elapsed_ms, bytes_scanned, started_at)
SELECT query_id, ... FROM snowflake.account_usage.query_history
WHERE query_tag LIKE 'agent_id=%'
AND NOT EXISTS (SELECT 1 FROM ops.agent_query_audit a WHERE a.query_id = query_history.query_id);Expected output: the audit table grows by exactly the new queries each night, with the NOT EXISTS guard making the load idempotent.
- Join the audit trail to the agent's own action log:
SELECT a.started_at, a.query_text, l.action, l.reasoning_summary
FROM ops.agent_query_audit a
LEFT JOIN ops.agent_action_log l
ON l.session_id = a.session_id AND l.tool_call_id = a.query_id;Expected output: each query next to the agent's stated reason for running it, so reviewers can check whether the action matched the intent.
- Lock down the audit table and set retention:
REVOKE ALL ON ops.agent_query_audit FROM PUBLIC;
GRANT SELECT ON ops.agent_query_audit TO ROLE security_auditor;Expected output: only the auditor role can read the trail. Keep history at least as long as your compliance window requires, and note that warehouse history views themselves expire, which is why the nightly copy matters.
Variant phrasings
log all queries from AI agent
The tag-then-pull pattern is the whole technique. Without the tag you are grepping query text, which is fragile and incomplete.
database query audit trail for agents
The trail has two halves: the warehouse half (what ran) and the agent half (why). Either half alone is insufficient for a real audit.
track what queries an LLM ran
Track at the session level, not just the agent level, so one compromised or confused session does not taint the history of every other session.
Why it happens
Agents act through tools, and tool calls are easy to lose: logs rotate, sessions get discarded, and the agent's summary of what it did is a story, not evidence. The warehouse, meanwhile, records every statement with timing and data volume as a side effect of executing it. Tagging gives you the join key, the nightly pull gives you permanence beyond the history view's retention, and the append-only table gives you tamper resistance. Auditing works when the evidence is collected independently of the thing being audited.
Edge cases
- Some drivers and ORMs strip SQL comments, which kills the Postgres comment technique; prefer native query tags or labels where the warehouse supports them.
- Warehouse history views have limited retention, often 7 to 365 days depending on edition; the nightly copy is what makes the trail long-lived.
- A superuser or compromised credential can run untagged queries; the audit proves what tagged sessions did, it does not prove nothing else happened.
- Query text may contain PII in literals; restrict audit table access and consider redacting literals for long-term storage.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst8LIs8SDaHi7_W3wbxNPFA
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.