Skip to main content
The BigQuery query cost optimizer is a DinoAI agent that finds your most expensive dbt™ models, diagnoses SQL anti-patterns, rewrites the model files, opens a pull request, and posts a cost summary to Slack. You run it from a Bolt schedule so costly models are caught and fixed without manual intervention.
Prerequisites
  • Slack connected (the agent posts the PR link and cost summary to #finops).
  • An active BigQuery connection with permission to read job metadata (the agent calls get_bigquery_query_performance_stats).
  • Familiarity with programmable agents and running an agent with Bolt.
  • API credentials with DinoAI Agent capabilities (Workspace Settings → API, Admin access required).
Estimated time: 25 minutes.

Steps

1

Create the agent

Build the agent in the Agent UI, or commit this file at .dinoai/agents/query-optimizer.yml. It defines the agent’s role, five-phase goal, anti-pattern knowledge, guardrails, and Slack output channel.
.dinoai/agents/query-optimizer.yml
tools.mode: allowlist restricts the agent to only the tools listed, which keeps a write-capable agent from reaching outside the intended optimisation workflow. Update slack.channel before committing if your team routes cost alerts to a different channel.
2

Add the trigger script

The optimizer runs from a small trigger script that reads dbt™ model results from Bolt artifacts (or accepts BigQuery job IDs directly), filters to the top costly models by bytes processed, and hands the full context to the agent. Commit pyproject.toml at the same directory level as your dbt_project.yml so the agent can locate and rewrite model files, and scripts/run_query_optimizer.py alongside it.
pyproject.toml
scripts/run_query_optimizer.py
When --schedule-name is used, the script reads run_results.json from the latest Bolt run and maps each dbt™ model to the BigQuery job ID it produced. When --job-ids is used, the agent receives the job IDs directly and resolves the model files itself. When no model is above the bytes threshold the script exits cleanly with code 0, so it is safe to run on a schedule.
3

Set your environment variables

Store your secrets in Paradime before scheduling. Go to Workspace Settings → Environment Variables and add the following. Bolt schedules read from the same store, so no separate setup is needed.
Your Paradime API endpoint, key, and secret are available under Workspace Settings → API. Make sure the key has DinoAI agent API capabilities enabled.
4

Run it from Bolt

Add a Bolt schedule that runs the trigger script, so costly models are caught and fixed on a cadence. Go to Bolt → Schedules, create a schedule named something like Query Cost Optimizer, and add these two commands in order:
Replace your_dbt_production_schedule with the exact name of the schedule that runs your dbt™ models in production. See Run an agent with Bolt for the full walkthrough, including cron, run-on-merge, and Turbo CI triggers. A sensible default cadence is weekdays at 8 AM (0 8 * * 1-5), which runs after overnight production models complete so the latest artifacts are available.
poetry install runs first on every execution so dependency updates committed to pyproject.toml are picked up automatically. pyproject.toml must sit at the same directory level as dbt_project.yml, since the agent uses run_terminal_command, read_file, and write_file from the repo root.
To run the optimizer manually while testing, you can invoke the script from your local machine instead of a schedule. Detect costly models from a Bolt schedule, supply job IDs directly, or add a follow-up drill-down on one model:
On a run with costly models, the agent opens a PR titled perf: optimise BigQuery cost — <models> and posts a cost summary to #finops. The console shows the pre-fetched model table followed by the session ID and poll lines:
If no PR appears, check that a model actually processed at least 10 GB (the default threshold). Review the PR and merge it.

How it works

The trigger script reads the latest Bolt run’s run_results.json, extracts the BigQuery job ID produced by each dbt™ model, filters to the top-N costliest models above the bytes threshold, and triggers a single agent session with the model context pre-embedded. BigQuery is filtered by bytes processed because that is the direct driver of on-demand query cost. Once triggered, the agent works through five phases without stopping: gather BigQuery stats per job ID, locate the model .sql and YAML files, diagnose anti-patterns and build a plan, apply the changes on a new branch, then open the PR and post the summary. It never drops columns referenced downstream, never pushes to main, and leaves a TODO in the SQL when a business decision is required. The anti-patterns it detects and fixes:

Next steps

Query cost optimizer (Snowflake)

The same recipe for Snowflake, filtered by execution time and credits.

Run an agent with Bolt

Cron, run-on-merge, and Turbo CI triggers for this agent.

Build an agent in the UI

Create this agent visually instead of by hand.

Programmable Agents reference

The agent YAML schema and tools.