How to Build an SEO and AEO Tool with Jev (Step-by-Step Guide)

You can build an SEO and AEO tool with Jev by splitting the work three ways: Jev scores every trending query for niche fit, search intent and answerability, your code ranks the results, and an LLM writes drafts only for the top topics. Jev then audits each draft for AEO before an editor publishes it.
Jev is a new kind of AI model from TypeSafe AI, released in September 2026. Instead of writing text, it makes decisions: it picks from answers you define and returns a probability for each one. That makes it fast and cheap enough to score thousands of topics a day, which is exactly what a content pipeline needs.
In this guide, you'll learn what Jev is, where LLMs fall short for this kind of work, and how to build the tool step by step, with working Python code.
Key takeaways
What you'll build: a pipeline that finds trending topics, ranks them, drafts articles with an LLM and audits each draft for AEO.
Why Jev: it returns typed decisions with probabilities instead of text, and TypeSafe says most calls finish in about 100 milliseconds.
What it costs: at $0.042 per million input tokens, scoring 10,000 topics a day costs about $0.42.
Who does what: Jev decides, your code does the math, an LLM writes and an editor approves.
What is Jev?
Jev is an AI model that answers questions about a piece of content by choosing from answers you define in advance. You send it two things:
State: the content you want judged, such as a search query, a support ticket or a blog draft.
Questions: what you want to know about it, each with a fixed set of possible answers.
Jev returns one answer per question, along with probabilities, so your code can decide what to do next. It never generates free-form text, so it can't invent an answer outside the options you gave it.
Jev comes from TypeSafe AI, a San Francisco lab founded by former OpenAI researcher Diogo Almeida. TypeSafe came out of stealth on September 15, 2026, with $40 million in seed funding and Jev as its first public model.
Why is Jev called a "System One" model?
The name comes from Daniel Kahneman's book Thinking, Fast and Slow, which describes two modes of human thinking:
System 1: fast, intuitive judgment, like recognizing a face or sensing that an email is spam.
System 2: slow, deliberate reasoning, like solving a math problem or planning a project.
TypeSafe's argument is that today's LLMs are built to do System 2 work but are routinely used for System 1 decisions. Jev is designed for the fast half only.
The model's name is a nod to the economist William Stanley Jevons. The Jevons paradox observes that when a resource becomes cheaper to use, people end up using far more of it. TypeSafe's bet is that once an AI decision costs a tiny fraction of a cent, software will start making AI decisions in places where calling an LLM never made sense.
How did we get here? From rules to LLMs to System One models
1950s–2010s: rules and classic classifiers. Fast, cheap and predictable, but brittle when wording changes, and each task needs its own labeled data.
2018 onward: fine-tuned transformers such as BERT. Much better language understanding, but still one trained model per task.
2022 onward: general-purpose LLMs. Any task can be described in plain words, but they're slow and expensive for simple decisions.
2023 onward: structured outputs and tool calling. LLM answers fit into software as JSON, but they're still generated word by word and can break the schema.
2026: System One models such as Jev. Typed answers with calibrated probabilities in milliseconds, but they can't write text and are weak at math and dates.

Where do LLMs fall short for decisions?
LLMs are remarkable at writing, summarizing and reasoning. But many production AI calls aren't asking for any of that. They ask questions like "Is this urgent?", "Which category is this?" or "Is this query worth writing about?" For those, an LLM has five weaknesses.
1. They are slow for simple answers
An LLM produces its answer one token at a time, even when the answer is a single word. TypeSafe measured 3 to 329 seconds for frontier LLMs on its decision tasks, compared with 70 to 500 milliseconds for Jev. For a single request, a few seconds may be fine. For a pipeline that processes 50,000 keywords, or a check that runs while a user types, it isn't.
2. They get expensive at scale
LLM input prices typically range from $0.20 to $10 per million tokens, plus output charges. Classifying tens of thousands of items a day with an LLM adds up quickly, especially when each call needs a long prompt to explain the task.
3. Their answers don't always fit the schema
Ask an LLM to label search intent as "informational," "commercial," "transactional" or "navigational," and it will usually comply. But at scale you'll also see "Informational " with a stray space, "mixed," or a sentence explaining its reasoning. Structured outputs reduce this problem, but generation can still fail or stop early. Jev's answers are drawn only from the options you define, so a malformed label can't happen.
4. Their confidence numbers aren't reliable
If you ask an LLM "How confident are you?", it will produce a number, but that number is generated text, not a measured probability. Jev was trained with a method TypeSafe calls Reinforcement Learning for Calibrated Decisions (RLCD). The goal is that answers given 90% probability turn out right about 90% of the time. That lets you set rules such as "act automatically above 0.9, ask a human below 0.5."
5. They answer one question at a time
With an LLM, asking five questions about the same content usually means five calls or one long, fragile prompt. Jev evaluates every question in a request in parallel against the same state. Adding more questions barely changes response time and costs only the tokens of the extra questions.
Jev vs LLMs vs traditional classifiers
Traditional classifier: needs labeled data and training for each task, and returns a fixed label. Very fast and very cheap once trained, but to change the task you retrain it. Can't write text. Best for one stable task with lots of labeled data.
LLM (ChatGPT, Claude, Gemini): needs only a prompt, and returns free-form text or JSON. Takes seconds and costs $0.20–$10 per million input tokens, plus output. To change the task, you edit the prompt. Can write text. Best for writing, reasoning and explaining.
Jev (System One model): needs questions and possible answers, and returns typed answers with probabilities. Takes about 100 ms (TypeSafe's figure) and costs $0.042 per million input tokens, with free output. To change the task, you edit the questions. Can't write text. Best for high-volume decisions that change often.
A traditional classifier still wins when you have a stable set of labels and plenty of training examples. Jev earns its place when the questions change from request to request, or when training a new model for each task isn't practical.
How does Jev work?
Jev has three building blocks: state, questions and confidence.
State: what Jev looks at
The state is the content being judged. It can be a plain string, a JSON object or a JSON array. Using an object with named fields is usually best, because your questions can then refer to specific fields in backticks, such as query or existing_titles.
Keep the state focused. Like any model, Jev gets less accurate as you fill its context with irrelevant material, so filter in code before you send anything.
Questions: the three answer types
Noul ("Is this true?") returns a probability from 0 to 1. SEO example: "Is this query about AI tools?"
Choice ("Which of these options fits?") returns the top option, a probability for every option and a confidence score. SEO example: "Is this query informational, commercial, transactional or navigational?"
Score ("Where does this sit on a scale?") returns a score between your levels, probabilities and a confidence score. SEO example: "How useful would an article on this be to our readers?"
A Choice can have up to 255 options, and a Score between 2 and 10 levels. The state plus all questions can use about 64,000 tokens in total.
Confidence: when to act and when to ask
Every Choice and Score answer includes a confidence value between 0 and 1. It's high when one option clearly wins and low when probability is spread across several options. A Noul's probability already tells you how sure the model is.
This is what makes Jev practical in production. You decide in code what counts as confident enough, depending on the cost of a wrong answer:
High confidence: act automatically.
Medium confidence: flag for review or ask the user to confirm.
Low confidence: send to a person or a more capable model.
Getting started: your first Jev call
Jev is in early access. You can join the waitlist at typesafe.ai, then create an API key in the TypeSafe console. The examples below use the official Python SDK, which needs Python 3.10 or newer.
pip install typesafe-sdk
export TYPESAFE_API_KEY="your_api_key_here"Here is a first call that labels the search intent of one query and checks whether it can be answered directly:
from typesafe_sdk import Choice, Noul, TypeSafeClient
client = TypeSafeClient() # reads TYPESAFE_API_KEY from the environment
response = client.system_one(
state={"query": "best budget running shoes for flat feet"},
questions={
"search_intent": Choice(
instructions="What is the person searching for `query` trying to do?",
criteria={
"informational": "Wants to learn or understand something",
"commercial": "Comparing products or brands before buying",
"transactional": "Ready to buy or sign up now",
"navigational": "Looking for a specific website or brand",
},
),
"direct_answer_possible": Noul(
instructions="Can `query` be answered well in two or three sentences?",
),
},
)
intent = response.answers["search_intent"]
print(intent.choice) # e.g. "commercial"
print(intent.probabilities) # probability for every option
print(intent.confidence) # how clearly one option won
print(response.answers["direct_answer_possible"].noul)Both questions run in a single request. The search_intent answer can only be one of the four labels you defined, and your code gets the full probability distribution instead of a sentence to parse.
Note: Jev launched in September 2026 and its SDK is still evolving. Check the official documentation at docs.typesafe.ai for the latest method and field names before you deploy.
Use case: an AI-powered SEO and AEO content pipeline with Jev
Here is where Jev becomes useful for marketers. Search has split into two audiences:
SEO (search engine optimization): ranking in traditional search results.
AEO (answer engine optimization): getting your content quoted by AI answer engines such as ChatGPT, Perplexity, Gemini and Google's AI results.
Both reward the same habits: covering topics people are searching for right now, answering the question directly and early, and addressing follow-up questions. The hard part is volume. A content team might see thousands of candidate queries every week and can only write about a handful.
This pipeline splits the work between the two kinds of model:
Collect topics (code) → Score every topic (Jev) → Rank topics (code) → Write drafts (LLM) → Audit for AEO (Jev) → Human review and publish
Jev makes the thousands of small decisions. The LLM writes only for the topics that earn it. Your code does all the math.

Step 1: Collect trending topic candidates
Start by gathering candidate queries from sources you already have, such as Google Search Console exports, Google Trends, "People Also Ask" boxes, Reddit and industry news feeds. For each query, record how its search impressions changed week over week.
Jev isn't reliable at arithmetic, so calculate growth in plain code and turn it into a named bucket:
candidates = [
{"query": "what is jev ai", "impressions_7d": 1800, "impressions_prev_7d": 0},
{"query": "jev vs gpt for classification", "impressions_7d": 420, "impressions_prev_7d": 60},
{"query": "how to rank in chatgpt answers", "impressions_7d": 950, "impressions_prev_7d": 700},
{"query": "best seo plugin for wordpress", "impressions_7d": 300, "impressions_prev_7d": 320},
{"query": "cheap flights to goa", "impressions_7d": 40, "impressions_prev_7d": 10},
]
def growth_bucket(current: int, previous: int) -> str:
"""Turn week-over-week numbers into a trend label. Math stays in code."""
if previous == 0:
return "new" if current > 0 else "flat"
change = (current - previous) / previous
if change >= 1.0:
return "breakout" # at least doubled
if change >= 0.25:
return "rising"
if change > -0.25:
return "stable"
return "declining"Step 2: Score every topic with one Jev call
Next, define every question you want answered about each topic. Since Jev answers all of them in parallel, ask everything you might need in one request, even questions that only matter for some topics. TypeSafe calls this pattern speculative fan-out.
Keep all questions in one place so your team can review and tune them:
from typesafe_sdk import Choice, Noul, Score
NICHE = "AI tools, AI models and AI-powered SEO for marketers and developers"
TOPIC_QUESTIONS = {
"fits_niche": Noul(
instructions="Is `query` about a subject covered by `niche`?",
),
"already_covered": Noul(
instructions="Does any title in `existing_titles` already answer `query`?",
),
"aeo_answerable": Noul(
instructions=(
"Can `query` be answered with a clear, factual answer of a few "
"sentences that an AI assistant could quote?"
),
),
"intent": Choice(
instructions="What is the person searching for `query` trying to do?",
criteria={
"informational": "Wants to learn or understand something",
"commercial": "Comparing products or brands before buying",
"transactional": "Ready to buy or sign up now",
"navigational": "Looking for a specific website or brand",
},
),
"content_format": Choice(
instructions="Which article format best serves the person searching for `query`?",
criteria={
"explainer": "A 'what is' or definition article",
"how_to": "A step-by-step tutorial",
"comparison": "An 'X vs Y' or 'best of' article",
"news": "Coverage of a recent launch or event",
"other": None,
},
),
"audience_value": Score(
instructions="How useful would an article about `query` be to the readers described in `niche`?",
criteria=[
"Off-topic or trivial; these readers would not care",
"Loosely related; interesting but not something they would act on",
"Directly useful; readers could apply it in their work",
],
),
}A few details make these questions work well:
One judgment per question. Relevance, duplication and answerability are separate questions, so each answer means one thing.
Concrete Score levels. Each level describes a situation ("readers could apply it in their work") rather than a vague degree like "medium."
An escape option.
content_formatincludesother, so Jev isn't forced into a bad fit.No math. Trend growth was calculated in Step 1 and never goes to Jev.
Step 3: Rank topics in code
Jev supplies the judgments. Your code combines them with weights you control. This keeps your strategy readable and easy to change: if the rankings feel wrong, adjust a number rather than rewriting a prompt.
TREND_WEIGHT = {
"breakout": 1.0,
"new": 0.9,
"rising": 0.7,
"stable": 0.3,
"declining": 0.0,
"flat": 0.0,
}
def priority(candidate: dict, answers: dict) -> float | None:
"""Return a 0-1 priority score, or None if the topic should be skipped."""
# Hard filters: off-topic, or we already have an article for it
if answers["fits_niche"].noul < 0.7:
return None
if answers["already_covered"].noul > 0.6:
return None
trend = TREND_WEIGHT[
growth_bucket(candidate["impressions_7d"], candidate["impressions_prev_7d"])
]
value = answers["audience_value"].score / 2 # 3-level scale (0-2) -> 0-1
answerable = answers["aeo_answerable"].noul
# Weights you own: 50% trend, 30% reader value, 20% AEO potential
return round(0.5 * trend + 0.3 * value + 0.2 * answerable, 3)In this example, "cheap flights to goa" fails the fits_niche filter and never reaches a writer, while "what is jev ai" scores high on all three factors.
Step 4: Run it at scale
Jev also ships an async client, so you can score thousands of topics concurrently. A semaphore keeps you within the rate limit, and low-confidence answers go to a review list instead of being guessed:
import asyncio
from typesafe_sdk import AsyncTypeSafeClient
aclient = AsyncTypeSafeClient()
limit = asyncio.Semaphore(10) # max concurrent requests
async def score_one(candidate: dict, existing_titles: list[str]):
async with limit:
response = await aclient.system_one(
state={
"query": candidate["query"],
"niche": NICHE,
"existing_titles": existing_titles,
},
questions=TOPIC_QUESTIONS,
)
return candidate, response.answers
async def rank_topics(candidates: list[dict], existing_titles: list[str]):
results = await asyncio.gather(
*(score_one(c, existing_titles) for c in candidates)
)
ranked, needs_review = [], []
for candidate, answers in results:
# Unsure about intent? Let a person look instead of guessing.
if answers["intent"].confidence < 0.5:
needs_review.append(candidate["query"])
continue
score = priority(candidate, answers)
if score is not None:
ranked.append({
"query": candidate["query"],
"priority": score,
"intent": answers["intent"].choice,
"format": answers["content_format"].choice,
})
ranked.sort(key=lambda t: t["priority"], reverse=True)
return ranked, needs_review
# Keep the state small: pass your most related titles, not your whole sitemap
existing_titles = [
"What Is Answer Engine Optimization (AEO)?",
"SEO vs AEO vs GEO: What's the Difference?",
"How to Rank in ChatGPT: A Practical Guide",
]
ranked, needs_review = asyncio.run(rank_topics(candidates, existing_titles))
for topic in ranked[:10]:
print(f'{topic["priority"]:.2f} {topic["query"]} ({topic["intent"]}, {topic["format"]})')The output is a ranked content calendar: what to write, in what format and for which search intent.
Step 5: Let an LLM write the draft
Now the LLM does what it does best. Only the top-ranked topics reach this step, so you spend generation costs where they matter. This example uses Anthropic's Claude, but any LLM works. Note how Jev's labels feed directly into the prompt:
import anthropic
llm = anthropic.Anthropic() # reads ANTHROPIC_API_KEY from the environment
def write_draft(topic: dict, paa_questions: list[str]) -> str:
prompt = f"""Write a {topic["format"]} blog post for readers interested in {NICHE}.
Target search query: "{topic["query"]}"
Search intent: {topic["intent"]}
Requirements:
- Open with a direct answer to the query in 40-60 words.
- Use question-style H2 headings in Markdown (## Heading?).
- Answer each of these follow-up questions somewhere in the article:
{chr(10).join(f" - {q}" for q in paa_questions)}
- End with a short FAQ section."""
message = llm.messages.create(
model="claude-sonnet-5",
max_tokens=4000,
messages=[{"role": "user", "content": prompt}],
)
return message.content[0].textStep 6: Audit the draft for AEO with Jev
LLMs don't always follow every instruction. Before a human editor sees the draft, Jev checks it against your AEO checklist. The pattern is the same: code handles anything countable, and Jev handles anything that needs understanding.
from typesafe_sdk import Noul, Score
def audit_draft(target_query: str, draft: str, paa_questions: list[str]) -> dict:
# Deterministic checks stay in code
blocks = [b.strip() for b in draft.split("\n\n") if b.strip()]
intro = next(b for b in blocks if not b.startswith("#"))
headings = [b.lstrip("#").strip() for b in blocks if b.startswith("## ")]
# Semantic checks go to Jev, all in one request
questions = {
"direct_answer": Noul(
instructions="Does `intro` directly answer `target_query` on its own?",
),
"quotability": Score(
instructions="How easily could an AI assistant quote `intro` as the answer to `target_query`?",
criteria=[
"Vague or promotional; there is no clear answer to quote",
"Answers the query, but the answer is mixed in with other ideas",
"A clear, self-contained answer an assistant could quote as is",
],
),
}
# One yes/no question per "People Also Ask" query
for i in range(len(paa_questions)):
questions[f"covers_paa_{i}"] = Noul(
instructions=f"Does `draft` clearly answer `paa_questions[{i}]`?",
)
response = client.system_one(
state={
"target_query": target_query,
"intro": intro,
"draft": draft,
"paa_questions": paa_questions,
},
questions=questions,
)
a = response.answers
return {
"intro_word_count": len(intro.split()),
"question_headings": sum(h.endswith("?") for h in headings),
"direct_answer": round(a["direct_answer"].noul, 2),
"quotability": round(a["quotability"].score, 2),
"missing_questions": [
q for i, q in enumerate(paa_questions)
if a[f"covers_paa_{i}"].noul < 0.5
],
}A typical report looks like this:
python
{
"intro_word_count": 52,
"question_headings": 6,
"direct_answer": 0.97,
"quotability": 1.8,
"missing_questions": ["How much does Jev cost?"],
}Word counts and question marks are computed in code because they're exact. Whether the intro actually answers the query, and which follow-up questions the draft missed, requires understanding. That's Jev's job.
Step 7: Close the loop
Use the audit to decide what happens next:
Passes every check: send the draft to an editor for fact-checking and final review.
Missing questions or a weak intro: send the audit report back to the LLM with a request to fix those specific gaps, then audit again.
Low confidence anywhere: flag it for a human instead of trusting the automated check.
You can extend the audit with other checks, too. For example, you could add one Noul per factual claim asking whether your source notes support it, so unsupported claims get flagged before publishing.
What does this pipeline cost?
Here's a rough estimate for a team scoring 10,000 candidate queries a day, at about 1,000 input tokens per request (the query, niche description, related titles and questions):
Daily tokens: 10,000 × 1,000 = 10 million input tokens
Jev cost: 10 million × $0.042 per million = $0.42 per day, or about $12.60 per month
Same volume on an LLM: at $0.20–$10 per million input tokens, $2–$100 per day before output charges
At the current early-access limit of 1,200 requests per minute, all 10,000 queries can be scored in under ten minutes. The LLM bill doesn't disappear, since you still pay for drafts. But you only pay for drafts worth writing.

Other practical use cases for Jev
The same "Jev decides, code acts, LLM writes" pattern works across a business:
Support ticket triage: route each ticket to billing, technical or sales, score its urgency, and escalate low-confidence cases to a person.
Model routing: decide whether a request needs a cheap, fast LLM or an expensive reasoning model. LangChain already ships routing middleware built on Jev.
Agent guardrails: before an AI agent runs a command, classify it as read-only, reversible or destructive, and require approval for risky actions.
Content moderation: flag spam, abuse or off-topic comments with categories you define.
Fact verification: check each claim in an LLM-written summary against the source material.
Data labeling: tag large datasets, such as product listings, research papers or reviews, for a fraction of LLM costs.
Where Jev falls short
Jev is a specialist, and it has clear limits:
It can't write. No replies, summaries, code or explanations. Pair it with an LLM whenever you need text.
It's weak at math, counting and dates. Do calculations in code and pass Jev the result, as the growth bucket example shows.
It reads your questions literally. Vague or double-negative questions produce worse answers. Write the exact condition you mean.
Accuracy drops with cluttered input. Send only the content your questions need.
It can be steered by adversarial text. Content written to manipulate the model can still shift answers. TypeSafe says it's working on this, so test with hostile inputs before exposing Jev to user content.
It's text-only. Images, audio and video need to be converted into text first.
It's brand new. Jev is in early access, TypeSafe's speed and cost figures come from its own evaluations, and the service runs in the US. If your users are elsewhere, such as in India or Europe, measure the latency from your own region.
Best practices for writing Jev questions
Ask one thing per question. Split compound judgments into separate questions and combine the answers in code.
Describe situations, not degrees. "Readers could apply it in their work" beats "high value."
Always include an escape option. Add
otheror "not stated" when your list might not cover every input.Phrase yes/no questions so that yes means yes. Avoid questions where a high probability means "no."
Keep all questions and thresholds in one file. That's the part your team needs to review.
Test before you automate. Run Jev alongside your current process on real examples, compare the results, then tune thresholds before letting it act on its own.
How to get access to Jev
TypeSafe directly: join the waitlist at typesafe.ai. Once approved, the console at console.typesafe.ai includes a playground, API keys and usage tracking.
SDKs:
typesafe-sdkfor Python and@typesafe-ai/sdkfor Node.js.Vercel AI Gateway: Jev is available as
typesafe-ai/jevat the same price.LangChain: the
langchain-typesafepackage exposes Jev as a classifier, plus middleware for model routing and tool-risk checks.Open alternatives: open models built on the same idea, such as Laya and Nimble, have started to appear.
The bigger picture: what Jev means for the future of AI
For the past few years, AI progress has meant bigger models and longer reasoning. Jev points to a different direction: specialized models built for the thousands of small decisions inside everyday software. A person might open a chatbot a few times a day. A support queue, a content pipeline or an AI agent might make thousands of decisions an hour.
The likely future isn't one model that does everything. It's a team: a fast decision model routing and checking, a generative model writing and reasoning, and people handling what neither is sure about. For content teams, that means using AI to decide what to write and whether it's ready, not just to write it.
Frequently asked questions
What is Jev AI?
Jev is a System One model from TypeSafe AI, launched in September 2026. It answers questions about text by choosing from answers you define, returning typed results with probabilities instead of generated text.
Is Jev a large language model?
No. Jev accepts plain-language questions like an LLM, but it doesn't generate text. It returns yes/no probabilities, choices from a list, or scores on a scale.
How much does Jev cost?
Jev costs $0.042 per million input tokens, and output tokens are free. A typical request of a few hundred tokens costs a tiny fraction of a cent.
Can Jev replace ChatGPT or Claude?
No. Jev can't write, summarize or explain. It works best alongside an LLM, handling fast decisions so the LLM is only called when text or deeper reasoning is needed.
How can Jev help with SEO and AEO?
Jev can score large lists of trending queries for relevance, search intent, content format and how easily an AI answer engine could answer them. After an LLM writes a draft, Jev can check whether the introduction answers the target query directly and whether the article covers related "People Also Ask" questions.
What does "System One" mean?
It refers to the fast, intuitive "System 1" thinking described by Daniel Kahneman in Thinking, Fast and Slow. System One models handle quick judgments, while LLMs and reasoning models handle slower, deliberate "System 2" work.
How accurate is Jev?
Jev is trained to produce calibrated probabilities, meaning its confidence should match how often it's right. It can still be wrong on any single answer, so test it on your own data and route low-confidence answers to a person.
Sources and further reading
TypeSafe AI: Introducing System One Models and Jev
TypeSafe documentation: docs.typesafe.ai
LangChain: Building a Harness with Jev
Flavio Copes: A deep dive into Jev, TypeSafe's System One model
DataCamp: Jev: TypeSafe's System One Model
Invide Labs: System One models: Jev and its open-source alternatives
More posts

Why Prompt Engineering Is Evolving into Context Architecture
Better wording stopped being the main lever. What an AI model sees now matters more than how you ask. Here is what context architecture is, how to build a knowledge tree, and the tools for each layer.