cd /news/ai-agents/test-snowflake-sql-locally-with-your… · home › topics › ai-agents › article
[ARTICLE · art-147443] src=blog.localstack.cloud ↗ pub= topic=ai-agents verified=true sentiment=↑ positive

Test Snowflake SQL Locally with Your AI Agent

LocalStack published a walkthrough showing how an AI agent can build and verify a Snowflake SQL report entirely against a local emulator instead of a paid cloud warehouse. The company gave Claude Code access to the LocalStack MCP server and its Snowflake client tool, then had it load three CSV files from a SaaS billing dataset — plans.csv with four subscription tiers, customers.csv with 39 customers, and payments.csv with 495 invoice rows — and produce a quarterly "Revenue by Plan" report. Claude Code started the emulator, found and fixed two problems in its first query, and checked its results against the raw data, all locally at the endpoint snowflake.localhost.localstack.cloud:4566.

by read6 min views3 publishedSep 29, 2026
Test Snowflake SQL Locally with Your AI Agent
Image: Blog (auto-discovered)

#

Developing SQL against a real Snowflake warehouse can be slow and expensive. Every time you test a query, a warehouse starts and you pay for the compute. Building a report often takes many test runs, so the time and cost quickly add up. Worse, SQL errors can be hard to spot. A query may return a believable number that reaches a dashboard before anyone checks it against the raw data.

We gave Claude Code access to the LocalStack MCP server and its Snowflake client tool. We then gave it CSV files with a SaaS company’s billing data and asked it to build a quarterly “Revenue by Plan” report using a local Snowflake emulator. It also had to verify every number.

Claude Code started the emulator, loaded the CSV files, and wrote the report. It found two problems in its first query, fixed them, and checked the results against the raw data. All this happened locally, without using a real Snowflake warehouse. Here is what happened and how you can try it yourself.

#

LocalStack for Snowflake is a local emulator that supports the Snowflake protocol. After starting the emulator, you can point a client to snowflake.localhost.localstack.cloud:4566 and run DDL, DML, and queries as you would with a real Snowflake account.

The LocalStack MCP server connects your AI agent to the emulator. This blog uses two tools from the LocalStack MCP server:

  • localstack-management starts, stops, and checks the LocalStack container. The agent uses it to start the Snowflake emulator.
  • localstack-snowflake-client runs SQL.check-connection checks whether the emulator is available.execute runs a query string or a.sql file. You can also provide a database, schema, warehouse, and role for each call.

Behind the scenes, the client tool uses the Snowflake CLI (snow) and manages the LocalStack connection profile. The Snowflake CLI is the only Snowflake-side tool you need to install. When the agent runs a query, it receives the results as text. It can read those results and decide what to do next, just as you would when working in a SQL console.

#

  • Docker , running.
  • A valid LOCALSTACK_AUTH_TOKEN , available with afree LocalStack account . LocalStack for Snowflake is a licensed emulator, so check that your plan includes it.
- The [Snowflake CLI](https://docs.snowflake.com/en/developer-guide/snowflake-cli/installation/installation) (`snow` ) on your`PATH` .
- [Node.js](https://nodejs.org/) , to run the MCP server through`npx` .
- [Claude Code](https://www.claude.com/product/claude-code) , or any other MCP client.

#

The MCP server ships with a wizard that writes the client configuration for you:

The wizard checks if Docker is available and reads LOCALSTACK_AUTH_TOKEN from your environment. If the token is missing, it asks you to enter it. The wizard then finds your installed MCP clients and configures the ones you choose.

The LocalStack tools will be available the next time you start your agent. You do not need to start the emulator yourself. The agent will do that in Step 3.

#

The dataset contains three CSV files similar to those exported from a billing system:

Download them into a data folder:

plans.csv contains four subscription tiers:

customers.csv contains 39 customers. Each customer has a plan_id, a status (active or churned), a signup_date, and a churn_date. The churn_date is blank for active customers.

payments.csv contains 495 rows. Each row represents a paid monthly invoice and includes a payment_date and an amount. Some customers made payments before leaving partway through the quarter. This detail becomes important later.

#

Open Claude Code in the folder that contains your data directory. Select your model (e.g., claude-opus-5) and use the following prompt. The key requirement is verification: the agent must check the report before calling it complete.

Step 4 is important. An agent that only writes a query may return incorrect results without noticing. Asking it to compare the results with the raw data helps it find and fix its own mistakes.

#

The agent first started the emulator and checked the connection:

Next, it created a database, a schema, and one table for each CSV file. It uploaded the files to an internal stage and loaded them with COPY INTO:

The three tables contained 4, 39, and 495 rows. The agent checked that these row counts and the total payment amount matched the original CSV files.

The agent also handled two details. The emulator compresses uploaded files, so COPY had to use the .gz filename. It also used EMPTY_FIELD_AS_NULL to load blank churn_date values as NULL.

#

The first query joined the three tables and grouped the results by plan. It ran without errors and returned numbers that looked reasonable:

However, checking the results against the raw tables revealed errors in both money columns.

Active MRR was about 12 times too high. MRR should count each customer once. However, joining the PAYMENTS table created one row per payment. As a result, the query counted each customer’s monthly price once for every invoice they had paid.

Collected revenue had a different problem. The query filtered for customers with status = 'active'. This filter is correct for MRR, but not for collected revenue. It excluded seven customers who paid during Q2 and later churned, leaving out $3,279 in revenue.

Neither problem caused an error, and the results still looked believable. That made both bugs easy to miss.

#

The fix was to calculate MRR and collected revenue separately. The agent used one CTE for each calculation, then joined both results to the plan list. It calculated MRR from CUSTOMERS only, which prevented duplicate customer counts. It calculated revenue from PAYMENTS without a status filter, so payments from churned customers were included:

The corrected report:

Plan Active MRR Active customers Collected (Q2 2026)
Starter $290 10 $899
Pro $792 8 $2,574
Business $1,794 6 $6,279
Enterprise $2,997 3 $10,989
Total $5,873 27 $20,741

The agent then verified the results. It calculated every value again using correlated subqueries instead of joins and arithmetic instead of SUM. It compared the two sets of results one value at a time.

It also checked the totals directly against the raw PAYMENTS table without any joins. This check would reveal any missing or duplicate rows. All checks passed:

#

The full session took about nine minutes with claude-opus-5 and cost $2.80 in model usage. This included creating the report, verifying the results, and saving the SQL. The agent made 42 tool calls, including 27 calls to the Snowflake client.

Because everything ran locally, there was no Snowflake compute cost. Running the same queries on a real account would have used billable compute. The missing-revenue bug could also have gone unnoticed until someone questioned the numbers later.

#

The Snowflake client tool in the LocalStack MCP server lets an agent complete common data tasks. It can start the emulator, create schemas, load CSV files, run queries, and read the results. Because everything runs locally, the agent can test and verify queries many times without Snowflake compute costs.

The two bugs in this example were common: a join duplicated values, and a filter removed valid rows. Both produced believable but incorrect results. Verifying the report against the raw data exposed them before the report was used. If you build reports or data transformations for Snowflake, local verification can help you find these problems early.

#

- [LocalStack for Snowflake](https://docs.localstack.cloud/snowflake/) : getting started, configuration, and the local emulator.
- [Snowflake feature coverage](https://docs.localstack.cloud/snowflake/feature-coverage/) : what the emulator supports.
- [LocalStack MCP server](https://github.com/localstack/localstack-mcp-server) : the server, its tools, and setup.
- [Model Context Protocol](https://modelcontextprotocol.io/) : how agents talk to tools.
- [LocalStack Slack Community](https://localstack.cloud/slack) : join for questions and discussion.
── more in #ai-agents 4 stories · sorted by recency
── more on @localstack 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/test-snowflake-sql-l…] indexed:0 read:6min 2026-09-29 · —