AI Agent Mining for Snowflake
This page describes how to configure the AI Agent Mining for Snowflake solution, powered by QPR ProcessAnalyzer. The solution uses Snowflake dynamic tables to transform the AI observability data that AI agents produce in Snowflake into a format suitable for QPR ProcessAnalyzer. These dynamic tables refresh automatically on the defined schedule, keeping the agent mining model up to date. The solution also provides ready-made, easy-to-use dashboards for analyzing AI agent behavior from a variety of perspectives, including performance, latency, and cost.
Installation overview
Configure the solution in the following order:
- Install the QPR ProcessAnalyzer Native App, or use QPR ProcessAnalyzer connected to a Snowflake account.
- Create the dynamic tables to the Snowflake account, transforming the AI observability data to the QPR ProcessAnalyzer model (instructions below). Ask the dynamic tables creation script from your QPR representative.
- Give the Native App (or the Snowflake user in case of a connected app) permissions to read the dynamic tables (Native App access to data).
- Import a project into QPR ProcessAnalyzer, containing the datatables, models and dashboards for the AI observability solution (Import project). Ask the project file from your QPR representative.
- Configure the imported project to use the Snowflake database and schema where the dynamic tables are located (Project Properties dialog). Select the project and click Properties. In the dialog, select the Data location tab, and define the Snowflake database name and Snowflake schema name. Click Save.
Dynamic tables allow to specify the target lag how often the tables are updated from the source AI observability data. The provided script uses a one-day target lag. Adjust target lag according to the requirements of the implemented solution. The more often the dynamic tables are refreshed, the more recent data is available in the solution, but the Snowflake warehouse costs are also higher.
The solution contains QPR ProcessAnalyzer datatables that have the same names as the Snowflake dynamic tables. The following datatables (and dynamic tables) are used:
- AI_OBSERVABILITY_BASE_EVENTS: parsed event-level observability data.
- AI_OBSERVABILITY_TRACE_EVENTS: events having a trace identifier.
- AI_OBSERVABILITY_TRACE_CASES: one aggregated row for each trace, representing one agent invocation.
- AI_OBSERVABILITY_THREAD_EVENTS: events belonging to a conversation thread.
- AI_OBSERVABILITY_THREAD_CASES: one aggregated row for each conversation thread.
Required Snowflake resources
Create or select the following Snowflake resources:
- A database and schema where the dynamic tables are located.
- A warehouse used to refresh the dynamic tables.
- A role that owns and refreshes the dynamic tables (referred later as <observability_role>)
The role creating the tables needs appropriate access to the target database, target schema, and warehouse. It also needs permission to create dynamic tables in the target schema. The role must retain the required privileges for the source used by the selected alternative and for AI_CLASSIFY.
Choose data access option
Two alternatives are available for reading the Snowflake AI observability data:
- Direct event-table access reads all account-level telemetry from the SNOWFLAKE.LOCAL.AI_OBSERVABILITY_EVENTS view.
- Scoped function access reads events for one specified Snowflake Cortex Agent, External Agent, or Cortex Search service using the SNOWFLAKE.LOCAL.GET_AI_OBSERVABILITY_EVENTS function.
Use direct event-table access when the solution needs account-wide observability analysis, such as analysing Snowflake CoWork activity or multiple agents without maintaining a list of objects. This approach bypasses object-level scoping and is intended for limited administrative scenarios. The source table includes telemetry such as conversation threads, traces, spans, inputs and outputs, feedback, evaluation runs, and eligible Cortex Search request logs.
Use scoped function access when the solution is intended to monitor a particular Cortex Agent, External Agent, or Cortex Search service. The function returns only events for the that agent without giving access to any other data. This is Snowflake's recommended access pattern for routine monitoring. This is preferable where account-wide raw-table access is not appropriate.
Alternative 1: Direct access to AI_OBSERVABILITY_EVENTS
For the direct access option, the following permissions need to be granted:
- SNOWFLAKE.AI_OBSERVABILITY_READER grants read access to the raw AI observability event table.
- READ UNREDACTED AI OBSERVABILITY EVENTS TABLE permits access to unredacted conversation content, tool inputs and outputs, and feedback text; without it, metadata such as tool names, token usage, latency, model name, and error severity remains available.
- The SNOWFLAKE.CORTEX_USER database role is required because AI_OBSERVABILITY_TRACE_CASES calls AI_CLASSIFY.
Example of granting the permissions:
USE ROLE ACCOUNTADMIN;
GRANT APPLICATION ROLE SNOWFLAKE.AI_OBSERVABILITY_READER TO ROLE <observability_role>;
GRANT READ UNREDACTED AI OBSERVABILITY EVENTS TABLE ON ACCOUNT TO ROLE <observability_role>;
GRANT DATABASE ROLE SNOWFLAKE.CORTEX_USER TO ROLE <observability_role>;
When the permissions have been set, run the dynamic tables creation script in the Snowflake Workspace using the <observability_role> role (so that the role becomes the owner of the dynamic tables). The script has parameter values <your_database>, <your_schema>, <observability_role>, and <your_warehouse> - replace these values before execution. Ask the creation script from your QPR representative.
Alternative 2: Scoped access using GET_AI_OBSERVABILITY_EVENTS
Required permissions
In the scoped access option, the role creating and refreshin the dynamic tables needs to have access to the parent database and schema of the monitored agent, plus the following object-specific privilege:
- For a Cortex Agent, grant MONITOR, or use a role that has OWNERSHIP on the Cortex Agent.
- For a Cortex Search service, grant MONITOR, or use a role that has OWNERSHIP on the service. Request logging must be enabled.
- For an External Agent, grant USAGE on the External Agent.
- Grant SNOWFLAKE.CORTEX_USER where required by the monitored feature. It is required for an External Agent call to this function.
- Grant READ UNREDACTED AI OBSERVABILITY EVENTS TABLE on the account when the dynamic tables must retain unredacted content.
- Grant SNOWFLAKE.CORTEX_USER for the supplied trace-cases table because it uses AI_CLASSIFY.
Example of giving the permissions:
USE ROLE ACCOUNTADMIN;
GRANT USAGE ON DATABASE <agent_database> TO ROLE <observability_role>;
GRANT USAGE ON SCHEMA <agent_database>.<agent_schema> TO ROLE <observability_role>;
GRANT MONITOR ON CORTEX AGENT <agent_database>.<agent_schema>.<agent_name> TO ROLE <observability_role>;
GRANT READ UNREDACTED AI OBSERVABILITY EVENTS TABLE ON ACCOUNT TO ROLE <observability_role>;
GRANT DATABASE ROLE SNOWFLAKE.CORTEX_USER TO ROLE <observability_role>;
Reading single agent data
In the dynamic tables creation script, replace the direct reading of the AI_OBSERVABILITY_BASE_EVENTS table with the GET_AI_OBSERVABILITY_EVENTS function call as described below. Ask the creation script from your QPR representative.
Replace:
FROM SNOWFLAKE.LOCAL.AI_OBSERVABILITY_EVENTS e
with:
FROM TABLE(SNOWFLAKE.LOCAL.GET_AI_OBSERVABILITY_EVENTS(
'<agent_database>',
'<agent_schema>',
'<agent_name>',
'<agent_type>'
)) e
For example:
FROM TABLE(SNOWFLAKE.LOCAL.GET_AI_OBSERVABILITY_EVENTS(
'MY_DATABASE',
'MY_SCHEMA',
'MY_AGENT',
'CORTEX AGENT'
)) e
Reading multiple agents data
If the solution must analyse several agents, create a source query with one function call per agent and combine results with UNION ALL. Identify the source object in an additional literal column if the object identity is needed in reporting.
Example:
WITH source_events AS (
SELECT 'AGENT_A' AS AGENT_NAME, e.*
FROM TABLE(SNOWFLAKE.LOCAL.GET_AI_OBSERVABILITY_EVENTS(
'MY_DATABASE', 'MY_SCHEMA', 'AGENT_A', 'CORTEX AGENT'
)) e
UNION ALL
SELECT 'AGENT_B' AS AGENT_NAME, e.*
FROM TABLE(SNOWFLAKE.LOCAL.GET_AI_OBSERVABILITY_EVENTS(
'MY_DATABASE', 'MY_SCHEMA', 'AGENT_B', 'CORTEX AGENT'
)) e
)
SELECT *
FROM source_events;