Blog · October 31, 2026

How to Stop Paying for an LLM Call on Every Automation Run

Stop paying for an LLM call on every automation run: audit your nodes, split decisions from generation, pick the right option per node, then do the math.

Saina · October 31, 2026 · 7 min read

Every time your automation fires, it calls an LLM. At a hundred runs a day that is a rounding error. At a hundred thousand, the invoice scales with your traffic whether or not the work needed a language model, and much of it often does not: many LLM calls in automations return one label from a fixed set. "Billing / technical / sales." "Urgent? yes/no." "Which tags apply." Paying flagship chat prices for multiple-choice answers is a common source of waste in these systems, often as several separate calls about the same input.

This guide covers how to stop paying for LLM calls on every automation run with one lever: moving decision-shaped steps off per-call LLMs. Audit what you are paying for, tell decisions from generation, pick the right option for each decision node, validate, and do the math. It is useful even if you never install the self-hosted option it describes. For the broader cost levers (caching, batching, prompt trimming, model tiers), see reducing OpenAI API costs.

Step 1: Find every LLM call and what it costs

You cannot cut what you cannot see. One afternoon, one table:

Workflow Node Model Calls/month Avg tokens in/out Est. cost/month Output type
support-in classify label
support-in tags tags
support-in summarize text
billing urgent? yes/no

Fill it from real data, not estimates; the estimates are what got you here.

Step 2: Classify each node: decision vs. generation

It's a decision if the useful output is one choice from a known list, several tags from a known list, a yes/no, or a rating, and any free text is thrown away or parsed into a label. The test: could you write the answer key in advance? If yes, it is a decision.

It's generation if the output text is the product. These stay on an LLM; the only question is which tier.

Examples that show where the boundary sits:

Decisions are the movable nodes. Generation is not going anywhere, and that is fine.

Step 3: Choose the option for each decision node

Four options, one paragraph each:

Keep on a large model. For decisions needing outside knowledge, long multi-step reasoning, or very large and constantly changing option sets. Rare, but real. If you are unsure, your labeled set will tell you.

Move to a cheap chat tier (GPT-6 Luna, Claude Haiku). Lowest friction if you are staying on chat APIs: same SDK, smaller model. Downsides: per-token billing including generated output, one decision per prompt unless you build structured output yourself, and no per-option probabilities unless the API exposes log-probabilities. (You can fold multiple questions into one structured-output prompt; it costs output tokens and gives no probabilities, so treat it as the conservative case in any math.)

Move to a hosted decision model (GPT-6 Luna Decisions). A Decisions API returning per-option probabilities for many questions per request (specs and price: see GPT-6 Luna Decisions alternatives, and check OpenAI's docs on the day). You stop paying for generated tokens because nothing is generated. Downsides: data leaves your servers, per-input-token billing, provider-managed versions.

Replace with Saina Helm (self-hosted decision model). A decision model you run yourself: flat hosting cost instead of per-token, data stays in-house, native multi-label questions, and a per-question confidence threshold whose rejected answers go to a fallback branch. This is the worked example below.

Step 4: The Helm worked example

Helm scores every option you pass and returns a probability for each instead of generating text, and one call can answer several typed questions about the same input (full specs).

Before: a support-ticket workflow makes three separate calls to a flagship chat model: route to a team, apply tags, set priority. Three prompts in, three answers out, three invoice lines per ticket.

After: one /v1/ask call with three questions:

import os
from saina import Saina, SainaError

client = Saina('https://helm.internal.example', api_key=os.environ['SAINA_API_KEY'])
result = client.ask(
    model='saina-helm-2-0.8b',
    state=ticket_text,
    mode='decision',
    threshold=0.8,
    questions={
        'team': {
            'type': 'single_choice',
            'question': 'Which team should handle this?',
            'options': {'billing': 'Charges, invoices, refunds',
                        'technical': 'Outages, errors, account access',
                        'other': 'Anything else'},
        },
        'tags': {
            'type': 'multi_choice',
            'question': 'Which topics apply?',
            'threshold': 0.5,  # per-tag; an example to tune
            'options': {'refund': 'Money back requests',
                        'outage': 'Service down or degraded',
                        'access': 'Login or permission trouble'},
        },
        'priority': {
            'type': 'rating',
            'question': 'How urgent is this?',
            'levels': ['low: routine', 'normal: same-day attention',
                       'high: drop other work'],
        },
    },
)

team = result['answers']['team']['selection']          # None if rejected
tags = result['answers']['tags']['selections']         # labels at or above 0.5
level = result['answers']['priority']['level']         # 0, 1 or 2, or None

The rating returns level as a zero-based index into levels, with probabilities keyed "0", "1", "2".

Confidence handling: for single-choice and yes/no, act on the top option only when it clears the threshold (and, optionally, a minimum margin over the runner-up). Rejected answers come back with no selection and a reason (below_threshold, below_margin, tie), ready for a fallback branch: human review, or escalation to an LLM. Multi-label questions apply the threshold to each tag separately (no margin); ratings ignore the margin. Inference errors are different: the SDK raises SainaError, so catch it and route it the same way. The 0.8 default is a starting point; tune it on your data.

Setup: the example targets Saina Helm 2 0.8B with the pinned saina 0.6.1 Python package, set up as in the release-pinned walkthrough, with TLS and auth in front. Start with at least 4 GB RAM on a CPU and measure memory and latency on your own inputs, as the self-hosting guide describes. In n8n, call /v1/ask from an HTTP Request node with model saina-helm-2-0.8b and branch on each answer's reason; the community node currently hard-codes the Helm 1 model ID. Scope note: Helm replaces the decision node; the rest of the workflow stays as it is. Generation steps and other chat calls stay where they are.

Step 5: Validate before cutting over

Shadow mode, one week, per node:

Step 6: Do the math before you stop paying for an LLM call on every automation run

For the same workload, compare four columns. Plug in current prices from each provider's official pricing page (note the date), your own token counts from Step 1, and your own volume. For self-hosting, use your hosting provider's price for a VM with at least 4 GB RAM, and write it down as a labeled, dated assumption. This post prints no prices: this market reprices often, and the only numbers worth using are the ones on each provider's official pricing page on the day you compare.

Column Calls Cost formula Monthly at your volume
Flagship chat 3 per item tokens × rates your number
Cheap chat tier 3 per item (conservative; see Step 3) tokens × rates your number
Hosted decision API 1 per item input tokens × rate your number
Helm (self-hosted) 1 per item fixed hosting your number

Expect the biggest saving to come from moving decisions off flagship and mid tiers. A hosted decision model can cost less than hosting Helm yourself at moderate volumes; run your numbers. Helm's cost case is a flat cost at very high volume; its main case is data control. Self-hosting has compute and maintenance costs too: there is no per-token fee for these decisions, but the server is not free.

When not to use Helm

Open-ended outputs (the text is the product). Decisions needing outside knowledge or multi-step reasoning. Huge or constantly changing option sets. Workflows where data can leave your servers and a hosted decision model is simply less work. In all of those, the right answer is something else, including, often, "keep the chat model you already have".

Final checklist