Before You StartParadime
- Your Paradime API endpoint, API key, and API secret — generate these under Workspace Settings → API. Make sure to enable
DinoAI agent APIcapabilities. Requires Admin access.
- Your Paradime workspace must have an active Snowflake connection with sufficient permissions to read query history metadata. The agent calls
get_snowflake_query_performance_statsto retrieve performance stats for the Snowflake queries that each dbt™ model produced.
- A Bolt schedule name — the script reads query IDs directly from the latest run’s
run_results.jsonartifact, which maps each dbt™ model to the Snowflake query it produced viaadapter_response.query_id - One or more Snowflake query IDs supplied directly via CLI flag or environment variable, if you already know which models are expensive
- Slack — the agent posts the PR link and a cost summary to
#finopsviapost_slack_message
What You’ll Build
By the end of this guide you’ll have:- A Poetry project wired to the Paradime SDK
- A
run_snowflake_query_optimizer.pytrigger script that reads dbt™ model results from Bolt artifacts (or accepts Snowflake query IDs directly), filters to the top costly models by execution time, and hands the full context to the agent - A
snowflake-query-optimizerDinoAI agent YAML that diagnoses Snowflake-specific anti-patterns, rewrites dbt™ model SQL and config, opens a PR, and notifies Slack
What the Agent Does
Once triggered, the agent works through five phases without stopping:main, and never guesses — if a business decision is required it leaves a TODO comment in the SQL and calls it out in the PR description.
Anti-Patterns the Agent Detects and Fixes
Architecture Overview
How It Works
run_snowflake_query_optimizer.py loads configuration from environment variables, optionally reads the latest Bolt run’s run_results.json artifact to extract the Snowflake query ID produced by each dbt™ model from adapter_response.query_id, filters to the top-N slowest models above a configurable execution time threshold (default: 30 seconds), then triggers a single snowflake-query-optimizer DinoAI agent session with the full model context pre-embedded in the opening message. The script polls every 20 seconds until the agent completes or times out (default: 60 minutes), then prints the full optimisation report to stdout. An optional follow-up drill-down on a single model can be sent within the same session.
Unlike the BigQuery version which filters by bytes processed, the Snowflake version filters by execution time in seconds — this is the most reliable proxy for credit consumption available in
run_results.json without needing to call the Snowflake query history API upfront.1
Set Up the Poetry Project
Create the following Install dependencies by running:
pyproject.toml at the same directory level as your dbt_project.yml. This is required so the agent can locate and rewrite dbt™ model files correctly during the optimisation pass.pyproject.toml
The only two third-party dependencies are
requests (for downloading Bolt artifacts) and paradime-io (the Paradime SDK). All other imports — argparse, os, sys, textwrap, time — are part of the Python standard library.2
Create the Agent YAML
Create the following file in your repository at
.dinoai/agents/snowflake-query-optimizer.yml. This defines the agent’s role, five-phase goal, Snowflake-specific anti-pattern knowledge, guardrails, and Slack output channel..dinoai/agents/snowflake-query-optimizer.yml
tools.mode: allowlist restricts the agent to only the tools listed. This is important for a write-capable agent — it prevents accidental access to tools outside the intended optimisation workflow.The Slack channel is set to
#finops by default. Update slack.channel before committing if your team routes cost alerts to a different channel.3
Create the Trigger Script
Create
scripts/run_snowflake_query_optimizer.py. This script reads dbt™ model results from Bolt artifacts (or accepts Snowflake query IDs directly via CLI), extracts adapter_response.query_id from each result, filters to the top costly models by execution time, builds a structured opening message with all pre-fetched metadata, triggers the snowflake-query-optimizer agent, and polls until completion.In Snowflake’s
run_results.json, the query ID is found at adapter_response.query_id — for example "01c4683c-0003-4ff0-0002-731a00bda6ea". This is different from BigQuery where the job ID is at adapter_response.job_id. The script reads this field specifically when parsing Bolt artifacts.scripts/run:snowflake:query:optimizer.py
The script accepts
--schedule-name or --query-ids but not both — they are mutually exclusive. When --schedule-name is used, the script reads run_results.json from the latest Bolt run and extracts adapter_response.query_id from each dbt™ model result. Models where query_id is absent (e.g. tests or snapshots) are automatically excluded.When no models are found above the execution time threshold, or none have a captured
query_id, the script exits cleanly with code 0 — safe to run on a schedule without generating noise.4
Set Your Environment Variables
Store your secrets in Paradime before scheduling. Go to Workspace Settings → Environment Variables and add the following:
Your Paradime API endpoint, key, and secret are available under Workspace Settings → API. Make sure the key has
DinoAI agent API capabilities enabled.5
Run the Optimizer Manually
Option A — Automatically detect costly dbt™ models from a Bolt schedule:Option B — Supply Snowflake query IDs directly (when you already know which models are slow):Option C — Include a follow-up drill-down on a specific dbt™ model:You should see output like:The agent then posts its full optimisation plan and PR link to stdout, and a credit reduction summary to
#finops on Slack.Schedule with Bolt
Run the optimizer automatically on a recurring cadence so costly dbt™ models are caught and fixed without any manual intervention. The schedule reads the latest Bolt run’srun_results.json, identifies the top offending models by execution time, and triggers the agent to fix and PR them.
Add Environment Variables to Paradime
Go to Workspace Settings → Environment Variables and confirm the variables from the previous step are saved. Bolt schedules read from the same environment variable store, so no additional setup is needed.Create the Bolt Schedule
Go to Bolt → Schedules and click New Schedule. Name it something likeSnowflake Query Cost Optimizer and add the following two commands in order:
Replace
your_dbt_production_schedule with the exact name of the Bolt schedule that runs your dbt™ models in production. The script reads that schedule’s run_results.json artifact, which contains a record per dbt™ model including the Snowflake query ID captured at adapter_response.query_id.poetry install runs first on every execution so that any dependency updates committed to pyproject.toml are picked up automatically — no manual intervention needed after a dependency bump.Choose a Schedule Frequency
The right cadence depends on how frequently your production dbt™ models run and how quickly Snowflake credit costs accumulate. The table below covers the most common options:For most teams, weekdays at 8 AM (
0 8 * * 1-5) is a sensible default — it runs after overnight production dbt™ models have completed, so the latest run_results.json artifacts and Snowflake query history are always available. The script exits cleanly with code 0 when no dbt™ models exceed the execution time threshold, so there is no cost or noise on quiet days.File Structure
Your repository should look like this after completing the setup:pyproject.toml must sit at the same directory level as dbt_project.yml. The agent uses run_terminal_command, read_file, and write_file to navigate and rewrite your dbt™ project files, so the working directory at session start must be the repo root.Related Docs
- Programmable Agents — Quick Start — getting started with DinoAI agents
- Programmable Agents — YAML Configuration — full reference for agent config options
- Programmable Agents — Tools Reference — all available tools including
get_snowflake_query_performance_statsandpost_slack_message - Bolt — Schedules — creating and managing Bolt schedules
- Paradime SDK — Artifacts — accessing run artifacts including
run_results.json - Slack Integration — connecting Slack to Paradime
- Paradime API & Credentials — where to find your API endpoint, key, and secret