Schema Validation Costs 0 Tokens: How Deterministic Tools Cut LLM Spend

Schema validation, lineage and lint can run as compiled code with no model call. See how deterministic tools cut LLM spend on one dbt change, and what remains.

On this page7 sections
  1. One Column Rename Shows Where Deterministic Tools Cut LLM Spend
  2. A Model Pays for Schema Context on Every Turn
  3. Six Checks on the Rename Run Without a Model Call
  4. The Validator Returns a Short Result the Model Can Act On
  5. Zero Tokens Means Zero LLM Tokens, and Other Costs Remain
  6. Four Questions About the Rename Still Need the Model
  7. Move Your Most Repeated Check Out of the Prompt First
tl;dr

A data agent can answer many questions about a dbt change without asking the model. A parser, a schema validator, a lineage walker and a linter each return the exact answer. None of them spends LLM tokens to compute it. That is how deterministic tools cut LLM spend: the model stops carrying the schema and the manifest in its context just to answer yes or no.

The saving has limits. The model still pays tokens to call a tool and read its result. The tools still use CPU and warehouse metadata queries. No tool can tell you whether the change was the right one.

You rename one column in a dbt staging model, and your coding agent has to confirm that nothing downstream breaks. The model can answer that question if you give it enough text. That text is the warehouse schema, the dbt manifest and every downstream SQL file. You pay for all of it as input tokens, again on each turn that keeps it in context.

A compiled tool answers the same question from the same files and sends the model a few lines back. That swap is the most direct way to cut LLM spend on data work. The model keeps the parts of the job that need judgment, and the checks with one right answer move to code.

This post follows one real change through six checks. For each check, it names the Altimate Code tool that runs it. It also names the text the model would need in context to answer without that tool. Prices are Anthropic list prices as of September 2026.

The model needs the whole project in context to answer by reading. The validator sends back a few lines.

One Column Rename Shows Where Deterministic Tools Cut LLM Spend

The example project is the jaffle-shop sample that ships in the altimate-code repo. It runs on DuckDB and holds four models, two seeds and 13 tests. The mart model customers sums o.amount from stg_orders.

The change renames amount to amount_usd in stg_orders:

-- models/staging/stg_orders.sql, after the change
select
    id as order_id,
    customer_id,
    order_date,
    amount as amount_usd
from {{ ref('raw_orders') }}

The customers model still reads o.amount, so the project is now broken. Six questions decide whether the change is safe to merge:

  • The agent has to know which models depend on stg_orders.
  • The agent has to confirm that customers still references columns that exist.
  • The agent has to trace which output columns read the renamed column.
  • The agent has to check the edited SQL for known anti-patterns.
  • The agent has to prove that the rows did not change.
  • The agent has to check whether the change exposes personal data.

Each of these questions has one correct answer. None of them needs a model to compute it.

A Model Pays for Schema Context on Every Turn

Anthropic's Claude Code cost guide says that token costs "scale with context size" on every request. A model that answers a schema question by reading needs the schema in its context window. Anthropic bills that text as input on each request that carries it, until the session drops or compacts it.

The table below prices 100,000 tokens of context for one turn. The rates come from Anthropic's pricing page as of September 2026. A cache read costs 0.1x the base input price, and the first write to the 5-minute cache costs 1.25x.

ModelInput per million tokens100,000 tokens, uncached100,000 tokens, cache read
Claude Haiku 4.5$1$0.10$0.01
Claude Sonnet 5$2$0.20$0.02
Claude Opus 5$5$0.50$0.05

Multiply the per-turn figure by the number of turns that keep the context loaded. Caching lowers the rate, but the cost still grows with every turn. The same guide warns that compaction has a cost too: "/compact reads the conversation it summarizes."

List prices as of September 2026. A tool that answers from files keeps this text out of the context window.

Six Checks on the Rename Run Without a Model Call

Each subsection below names the check, the tool, and the text the model would need to answer without that tool. The tool names come from the Altimate Code tool registry at commit 024e800.

1. Parse the Project Instead of Reading the Manifest

dbt_manifest parses target/manifest.json and returns a table of models, dependencies and columns. For the sample project, that table has four model rows.

A model that answers by reading needs the manifest itself. The sample's manifest.json is 684,396 bytes for four models. Most of that size is macro definitions: the file carries 475 macros. You can check a larger project yourself with wc -c target/manifest.json.

If you only need to confirm that the project still parses, dbt parse does that without a warehouse connection. It "parses and validates the contents of your dbt project."

2. Validate the SQL Against the Schema

The altimate_core_validate tool checks SQL syntax and schema references. It runs in the Rust engine, altimate-core. It takes the schema as a file path or as an inline table map. The inline shape is { table: { column: TYPE } }. For customers, the check needs only the columns of stg_customers and stg_orders.

The model alternative needs those same column lists in context, plus the compiled SQL. It then has to reason over them without error. On a larger project, the agent must first find the referenced tables. Until it finds them, it loads more schemas than the check needs.

3. Trace Column Lineage From the Parsed SQL

The altimate_core_column_lineage tool maps how columns flow from source tables to the query output. Its description says it runs fully offline in the native engine. For the rename, the question is which output columns of customers read stg_orders.amount. In the sample SQL, that column is total_amount.

A model needs every downstream SQL file in context to answer the same question. It then has to follow each CTE and alias by reading. For column-level lineage across more models, see the column-level lineage use cases.

4. Lint for Known Anti-Patterns

The sql_analyze tool checks SQL for anti-patterns and safety issues. It does not run the query. The headless form is the altimate-code check command, which runs lint and safety by default. The check command docs say it needs no model provider and no API key.

The model alternative needs the rule definitions in the prompt, plus the SQL. It also returns a paragraph where the linter returns a rule ID and a line number.

5. Diff the Rows Before and After

data_diff compares two tables or two queries row by row. For a rename, pass two queries keyed on order_id. The first selects amount from the old model, and the second selects amount_usd as amount from the new one. List amount in extra_columns, because a query diff compares only key columns without it.

A model has no way to answer this question by reading. It has to run queries, read the results into context and compare them. That path costs tokens in proportion to the rows it reads.

6. Scan for Personal Data

The altimate_core_classify_pii tool classifies schema columns by name patterns and data types. The schema_detect_pii tool scans column names across an indexed warehouse. The model alternative needs every column name in context. A rename can move a personal field under a new name, so run the scan on each schema change.

The Validator Returns a Short Result the Model Can Act On

The validator's reply decides how many tokens the next turn costs. altimate_core_validate returns a title, a small metadata object and a few lines of text. The shape below comes from altimate-core-validate.ts. The engine writes the message text, and its exact wording varies by version.

{
  "title": "Validate: INVALID",
  "metadata": {
    "success": true,
    "valid": false,
    "has_schema": true,
    "findings": [{ "category": "missing_column" }]
  },
  "output": "Validation failed:\n\n  • <engine message naming the missing column>\n    at line 6"
}

Two fields matter to you. The success: true field means the engine ran, so an invalid query counts as a finding. The has_schema field tells the model whether table and column checks ran at all. With no schema, the tool still checks syntax and dialect. Its output then says that it skipped the existence checks.

The headless CLI reports the same finding as structured JSON. Each finding carries file, line, rule, severity, message and an optional suggestion. An agent that reads this result knows to edit line 6 of customers.sql.

Zero Tokens Means Zero LLM Tokens, and Other Costs Remain

The "0 tokens" in the title covers one thing only: the check itself makes no LLM call. Four costs remain, and you should plan for each.

  • The tool call costs tokens. The model writes the SQL into the call as output tokens, and it reads the result back as input.
  • Tool definitions cost context. The Altimate Code docs say sending about 78 tool definitions on every turn "floods the context window." The opt-in setting ALTIMATE_TOOL_RETRIEVAL=1 trims that set per turn.
  • The engine uses CPU. The Correctness Layer post reports that the benchmark battery "validates 1,000 SQL queries in 30 ms."
  • Warehouse checks use the warehouse. The schema_index tool calls listTables and describeTable on your connection. It stores the result in ~/.altimate-code/schema-cache.db. The data_diff tool runs its comparison queries in the warehouse too.

One more cost is easy to miss. The data_diff tool description warns that up to 5 sample diff rows appear in its output. Those rows go to the LLM provider. For regulated data, the description says to use algorithm='profile'. That mode returns statistics only.

Four Questions About the Rename Still Need the Model

A compiled check answers whether the SQL is consistent with the schema. It cannot answer whether the change is right. These four questions stay with the model or with you:

  • The model can judge whether amount_usd is the right name for your team's conventions.
  • The model can decide whether customers should follow the rename or keep its output column name.
  • The model can explain the change in the pull request so a reviewer understands the intent.
  • You decide whether the values in amount really are US dollars.

That last question is a data question that no validator settles. The validator checks references and syntax. It does not check whether a join key is unique. A unique test in dbt, or a query against the data, answers that.

Two more limits apply. The schema_detect_pii tool scans column names, so it misses personal data stored under a neutral name. And the lint rules have a published benchmark only on synthetic Snowflake queries.

The split still saves money, because the model now reads a short finding instead of the project. Deterministic tooling for AI agents covers the wider argument for that split. The correctness layer shows the three points in an agent loop where these checks run. The hidden cost of AI coding tools shows how re-sent context grows a Claude Code bill.

Move Your Most Repeated Check Out of the Prompt First

Pick the check your agent runs most often by reading files. For most dbt teams, that check asks whether a column exists. Give it to a validator with an explicit schema. Then compare the input token count on your next session.

You can run the same checks headless before you change any agent setup. Compile first, because the checks parse SQL and a raw model still holds Jinja. dbt compile needs a warehouse connection.

npm install -g altimate-code
dbt compile
altimate-code check "target/compiled/**/*.sql" --checks lint,validate,safety --schema schema.yml --format json

The sql-review skill wraps these checks in a review workflow. Altimate Code runs them inside the agent loop. For the team-wide version, see the agentic data engineering platform.

Frequently Asked Questions

Get started

Ready to get started?

You are only a few clicks away from experiencing your own autopilot for data.