You read about Jev, saw the $0.0004-per-decision price, did the math on your search terms report, and requested access. Then you hit the wall every other advertiser hit this month: a waitlist with no date on it.

Here is the part almost nobody tells you. You do not need a Jev key to start using Jev for Google Ads. The key gives you a cheaper, faster model. It does not give you the workflow. And the workflow is 90% of the work.

The loop that makes Jev useful — collect the rows, ask one bounded question, act on the confident answers, queue the rest — runs today on a model you already have access to. You build it once. When your Jev invite lands, you change one line and the same loop gets 200x faster and roughly 100x cheaper.

This is the guide to building that loop now, so the waitlist stops being an excuse. I will show you the exact search-term triage pipeline in Python, what to swap when Jev opens, and the three things you should do this week that need no key at all.

What you are actually waiting for (and what you are not)

Let’s separate the model from the method, because conflating them is why people sit on the waitlist doing nothing.

Jev is a decision model from TypeSafe AI. It does not write text. You hand it a block of data — a search term, an ad, a landing page — and a bounded question, and it returns a typed answer with a calibrated confidence score. Three question shapes, and that is the entire API: Choice (pick one from a list), Score (a number on a scale you define), and Noul (yes or no, returned as a probability from 0 to 1).

That’s the model. Here’s the method, and the method is model-agnostic:

  1. Collect the rows with the Google Ads API or an export. No AI needed.
  2. Shortlist with plain rules so the model only sees candidates worth judging.
  3. Ask one bounded question per row.
  4. Threshold on confidence: apply the confident ones, queue the uncertain ones, drop the rest.
  5. Write with a normal LLM only where actual text is needed.

Notice something. Steps 1, 2, and 4 are ordinary code. They do not care which model runs step 3. (internal link: Google Ads API basics)

Which means the honest answer to “should I wait for Jev?” is: no. Build the loop on Claude Haiku 4.5 or Gemini Flash-Lite — both do structured outputs, both are callable today, both cost more per call than Jev but a fraction of a frontier model. Get the whole thing working on a model you can call this afternoon. Then swapping Jev in is a config change, not a rebuild.

The waitlist is gating the cheapest engine. It is not gating the car.

The one job to build first: search-term triage

Do not try to automate eight jobs. Pick the one with the most rows and the clearest rule, prove the loop works, then expand.

For nearly every account, that job is search-term triage. A 30-day search terms report on a mid-size account runs 5,000 to 50,000 rows. Today you either skim the top spenders and ignore the tail, or you dump the whole thing into a chat model that reads it in chunks and forgets the account rules halfway through. Neither is good. The tail is where wasted spend hides. (internal link: search terms report analysis)

The question a decision model answers here is a clean Choice:

Is this search query from a buyer, a researcher, a job seeker, a competitor search, or junk?

Five options. One answer per row. A confidence score attached. That is a textbook decision-model job, and it is the one to build first.

Here’s why it’s the right starting point: the rule for what to do with each answer is simple and lives in your code, not the model. Buyer → keep. Junk with high confidence → auto-negative. Anything in the murky middle → an approval queue you review over coffee. The model sorts; you set the policy.

Build the loop today — the code

Everything below runs on a model you have now. I’ll flag the exact spot where Jev drops in later.

Step 1: Get the rows

Pull the search terms report. If you’re comfortable with the Google Ads API, query it directly. If you’re not there yet, export the report to CSV from the UI and read that — it works identically for building the loop.

python

import csv

def load_search_terms(csv_path):
    rows = []
    with open(csv_path, newline="", encoding="utf-8") as f:
        for row in csv.DictReader(f):
            rows.append({
                "term": row["Search term"],
                "clicks": int(row["Clicks"] or 0),
                "cost": float(row["Cost"] or 0),
                "conversions": float(row["Conversions"] or 0),
                "campaign": row["Campaign"],
            })
    return rows

Plain English: this reads your exported search terms file and turns each line into a tidy record — the term, what it cost, whether it converted. No AI yet. This is just tidying data so the next steps have something clean to work with.

Step 2: Shortlist with rules, not with a model

This step saves you the most money and almost everyone skips it. Do not send 50,000 rows to any model. Filter first with rules that need zero intelligence.

python

def shortlist(rows):
    candidates = []
    for r in rows:
        # Never touch a term that converted recently. This is a hard rule.
        if r["conversions"] > 0:
            continue
        # Only judge terms that actually spent money without converting.
        if r["cost"] >= 5 and r["clicks"] >= 2:
            candidates.append(r)
    return candidates

Plain English: before asking any model anything, we throw out the rows that don’t need judging. A term that converted stays — we never negate a winner. A term that barely spent isn’t worth a model call. What’s left is the pile that’s costing you money with nothing to show for it. That’s the only pile the model needs to see.

On a real account this cuts the rows the model touches by 80% or more. That’s 80% of the cost gone before the model runs — on any model, including Jev.

Step 3: Ask one bounded question per row

Now the model. Here it is on Claude Haiku with structured output, which forces the answer into a fixed shape so your code can act on it without parsing prose.

python

import anthropic
import json

client = anthropic.Anthropic()

CATEGORIES = ["buyer", "researcher", "job_seeker", "competitor", "junk"]

def classify_term(term, campaign):
    prompt = f"""Classify this Google Ads search query into exactly one category.

Search query: "{term}"
Campaign context: {campaign}

Categories:
- buyer: shows intent to purchase or hire now
- researcher: gathering info, not ready to buy
- job_seeker: looking for employment
- competitor: searching for a competitor brand
- junk: irrelevant, spam, or unrelated

Respond ONLY with JSON: {{"category": "...", "confidence": 0.0 to 1.0}}"""

    msg = client.messages.create(
        model="claude-haiku-4-5",
        max_tokens=100,
        messages=[{"role": "user", "content": prompt}],
    )
    return json.loads(msg.content[0].text)

Plain English: for each leftover term, we ask the model one narrow question — which of these five buckets does this belong to, and how sure are you. We force it to answer in a rigid format (a category plus a confidence number) so the next step can act on it mechanically. No essays, no “it depends.” One bucket, one confidence score.

This is the exact spot Jev replaces. When your invite comes, the same five categories become a Jev Choice, the call returns a calibrated confidence instead of a self-reported one, and it runs in milliseconds for a fraction of the price. The rest of your code does not change. That is the whole point of building it this way.

Step 4: Threshold on confidence, then act

The confidence score is what turns a classifier into an automation you can trust. High confidence acts on its own. The murky middle waits for you. Low confidence gets dropped, because a coin-flip answer is worse than no answer.

python

def route(term_row, verdict):
    cat = verdict["category"]
    conf = verdict["confidence"]

    # Junk we're sure about → auto-negative.
    if cat == "junk" and conf >= 0.85:
        return ("AUTO_NEGATIVE", term_row["term"])

    # Buyer we're sure about → leave it alone.
    if cat == "buyer" and conf >= 0.70:
        return ("KEEP", term_row["term"])

    # Everything uncertain → you decide.
    return ("REVIEW_QUEUE", term_row["term"])

Plain English: this is your policy, written as rules. If the model is very sure something is junk, we mark it to be blocked. If it’s confident it’s a buyer, we leave it. Anything it’s unsure about lands in a review list you glance through yourself. You are never letting a shaky guess spend or save money on its own. The thresholds — the 0.85, the 0.70 — are yours to tune, not the model’s.

Set those numbers conservatively at first. Watch the review queue for a week. If the “AUTO_NEGATIVE” bucket keeps getting it right, loosen the threshold. If it’s blocking things it shouldn’t, tighten it. This is how you build trust in the loop before you hand it any real authority.

Step 5: Only now bring in a writing model

The classifier sorted. It did not write anything, and it never should. When you actually need words — a rewritten RSA headline for a term worth chasing, a one-line note explaining a queued decision to a client — that’s a job for a normal LLM. Jev can’t do it, Haiku can, and you route to it deliberately, not by default. (internal link: writing better RSAs with AI)

Keep the two apart. Cheap model sorts the thousands. Expensive model writes the few. That split is where the savings live, and it’s true whether the sorter is Haiku today or Jev next month.

The three things to do this week — no key required

Building the loop is the technical half. The other half is preparation that needs no code and no waitlist, and doing it now means you’re ready the day Jev opens instead of starting from zero.

1. Hand-label 500 rows of your own data. Pull 500 search terms and sort them into your five buckets by hand. This is tedious and it is the most valuable hour you’ll spend. That labeled set is how you’ll measure whether any model — Haiku, Gemini, or Jev — is actually accurate on your account, not on a vendor’s benchmark. Without it, you’re trusting a number you can’t check.

2. Write down your account rules as code, not vibes. “Never negate a converter.” “Brand terms always keep.” “Anything with ‘free’ in a lead-gen campaign gets reviewed.” These rules live in your shortlist and routing steps, and they’re the same regardless of model. Getting them explicit now is pure progress you keep forever.

3. Run the loop on Haiku against your labeled set and check the score. You built the pipeline above. Point it at your 500 labeled rows and see how often it agrees with you. If it hits 85%+ on the buckets that matter, you have a working automation today — before Jev, on a model anyone can call. If it doesn’t, you’ve learned that this job needs better shortlisting or clearer categories, which you’d rather learn now than after paying for a Jev key.

None of that waits on TypeSafe. All of it makes the eventual swap trivial.

What actually changes when Jev arrives

Be clear-eyed about the upgrade, because it’s smaller and larger than the hype suggests at the same time.

What gets better: speed and cost, dramatically. Jev returns answers in 70 to 500 milliseconds and prices input at $0.042 per million tokens with output free — roughly $0.0004 a decision. A search-term job that costs real dollars and runs monthly on a frontier model costs cents and can run nightly. Its confidence scores are also calibrated — trained so that “0.9 confident” genuinely means it’s right about 90% of the time — which makes your thresholds far more meaningful than a self-reported number from a chat model.

What does not change: your loop, your rules, your labeled test set, your review queue. You swap the model, not the machine.

And what to keep your eyes open about: Jev scores 67.8% on TypeSafe’s own benchmark, and that benchmark measures agreement with two frontier models rather than ground truth. It’s triage-grade, not oracle-grade. It can pick the wrong valid answer with confidence. That’s exactly why the confidence threshold and the human review queue are not optional — they’re the part of the design that makes an imperfect model safe to use. The “cannot hallucinate” line means it can’t return an answer outside your five categories. It does not mean it’s always right.

Treat it as a fast, cheap sorter that tells you how much to trust each call. That is a genuinely useful new tool. It is not a robot that runs your account.

Your next 30 minutes

Skip the waitlist anxiety and open a terminal. Export a 30-day search terms report from one account, drop it into the load_search_terms function above, and run the shortlist step. Just that. See how many rows survive the rules — that number alone will tell you how much manual triage you’ve been skipping.

That’s the loop starting. Everything after it is tuning, and none of it needs a key you don’t have yet.