How to Use Jev for SEO and GEO: Search Intent, Passage Scoring, and AI Answer Tracking
Jev, the decision model from TypeSafe AI, does not write content. It answers bounded questions with a probability. This guide shows where that fits in SEO and GEO work: classifying search intent across a keyword list, scoring whether a passage can be quoted by an AI answer engine, labeling how ChatGPT or Perplexity answers mention your brand, and flagging AI drafts before they go live, with Python and curl you can copy.
- #jev
- #typesafe-ai
- #seo
- #geo
- #generative-engine-optimization
- #search-intent
- #content-scoring
- #ai-search
Which Jev question type fits which SEO and GEO task?
| Question type | What it returns | SEO use | GEO use |
|---|---|---|---|
| Choice | The top option, a probability per option, and a confidence (1 to 255 options) | Search intent, page type, topic cluster, which of two titles fits a query better | How an AI answer treats your brand: recommended, mentioned, competitors only, absent |
| Score | A probability-weighted level on your ordered rubric (1 to 10 levels), per-level probabilities, a legend | How well a page or snippet matches a target query | How quotable a passage is on its own (answer readiness) |
| Noul | A probability from 0 to 1 that a statement is true | Does the draft state a figure without a source? Is this keyword off-topic for the site? | Does the first sentence answer the question? Does the passage give a concrete fact? |
How do you use Jev for SEO and GEO?
- 1
Get an API key and install the SDK
Create a key at console.typesafe.ai/keys and export it as TYPESAFE_API_KEY; the SDK reads it from there. The Python SDK needs Python 3.10 or newer; the JavaScript SDK (@typesafe-ai/sdk) needs Node.js 20 or newer. Before writing code, try a question in the Playground at console.typesafe.ai/playground to see the answer shape. Use the model alias jev-latest. The response names the exact version that answered (for example jev-1.13.0); store it with your results, because outputs can change between releases.
Terminal export TYPESAFE_API_KEY="your-api-key" python3 -m venv .venv .venv/bin/pip install typesafe-sdk
- 2
Classify search intent across your keyword list
Export your keywords from Search Console or a keyword tool into keywords.csv and run each one through a Choice question with four intents (the full script is in the examples below). Write each option as a description, not just a label: Jev decides from the description, and a criterion left as null is judged by its name alone. Keep the confidence next to each row and send anything below your cut to a person. Intent decides the page type you build, so a misclassified keyword costs a page, not a cell.
- 3
Score each passage for answer readiness (GEO)
AI answer engines quote passages, not pages. For each question a page targets, pass the query and the passage together as the state and ask a Score question: how well does this passage answer the query on its own, if it is quoted without the rest of the page? Add two Noul checks: does the first sentence answer the query, and does the passage give a concrete figure, step, date, or name? Rewrite the passages that score low, then score them again. This measures your rubric, not any engine's ranking, so treat it as a checklist that scales, not a citation forecast.
- 4
Pick between two titles or snippets for a query
When you have two candidate titles, meta descriptions, or opening paragraphs, put the query and both candidates in the state and ask a Choice question with the options a and b. The probabilities tell you how clear the preference is: 0.9 against 0.1 is a decision, 0.55 against 0.45 is a coin toss you should settle with your own judgment or a live test. Ask the same question with a and b swapped to catch position bias before you trust the result.
- 5
Label the AI answers you collect for your prompts
Jev does not query ChatGPT, Perplexity, or Gemini, and it does not browse. Collect their answers yourself for a fixed set of prompts your buyers ask, then send each answer to Jev with a Choice question on how it treats your brand (recommended, mentioned, competitors only, absent) and a Noul question on whether the framing is favorable. Run the same prompts on the same schedule so the labels are comparable week to week. Whether your domain appears in the cited sources is an exact string match: do it in code, not with Jev.
- 6
Flag AI-written drafts before they publish
If an LLM writes your drafts, put Jev between the writer and the CMS. Ask Noul questions that catch the failures that hurt SEO and GEO: the draft states a figure without naming its source; the introduction restates the title without adding information; the draft answers a different question than the target query. Send anything above your cut to an editor rather than blocking it outright. Jev flags; a person decides.
- 7
Set your thresholds from your own labeled examples
Label 50 to 100 examples by hand for each question (keywords with the intent you would assign, passages you would or would not quote) and run Jev over them. Pick the cut where its answers agree with yours often enough for the cost of a mistake. TypeSafe describes the probabilities as calibrated in aggregate: across many answers, 0.8 should be right about 80% of the time, and any single answer can still be wrong. Confidence describes how concentrated the probabilities are, not whether the answer is correct, so it is a trigger for review, not a measure of accuracy.
- 8
Optional: give your coding agent the TypeSafe skill
If you build these scripts with Claude Code or another coding agent, install the official TypeSafe skill so the agent knows the API instead of guessing it. Installs are project-local by default; add -g to install globally. Then ask the agent to build one of the scripts above and review what it writes against the examples in this guide.
Terminal # Claude Code claude plugin marketplace add typesafe-ai/skills claude plugin install typesafe@typesafe-ai # other agents npx skills add typesafe-ai/skills --skill typesafe-ai
Copy-ready scripts
import csv
from typesafe_sdk import Choice, TypeSafeClient
INTENT = Choice(
instructions="The main search intent behind this query",
criteria={
"informational": "Wants to learn or understand something",
"commercial": "Comparing products, brands, or options before buying",
"transactional": "Ready to buy, sign up, or download now",
"navigational": "Looking for one specific site, brand, or page",
},
)
REVIEW_BELOW = 0.6 # starting point; set yours from labeled examples
with TypeSafeClient(model="jev-latest") as client, \
open("keywords.csv") as src, open("intent.csv", "w", newline="") as dst:
out = csv.writer(dst)
out.writerow(["keyword", "intent", "confidence", "needs_review", "model"])
for row in csv.DictReader(src):
r = client.system_one(state=row["keyword"], questions={"intent": INTENT})
a = r.choices["intent"]
out.writerow([row["keyword"], a.choice, round(a.confidence, 2),
a.confidence < REVIEW_BELOW, r.model])keywords.csv needs a keyword column. One request per keyword keeps the script simple; for large lists, use the AsyncTypeSafeClient the SDK also ships.
from typesafe_sdk import Noul, Score, TypeSafeClient
query = "how to reset a router to factory settings"
passage = open("passage.txt").read()
with TypeSafeClient(model="jev-latest") as client:
r = client.system_one(
state={"query": query, "passage": passage},
questions={
"readiness": Score(
instructions="How well the passage answers the query on its own, "
"if quoted without the rest of the page",
criteria=[
"Does not answer the query",
"Mentions the topic, but the answer is vague or buried",
"Answers the query, but needs surrounding context to make sense",
"Answers the query directly and completely, self-contained",
],
),
"answer_first": Noul(
instructions="The first sentence of the passage directly answers the query"),
"specific": Noul(
instructions="The passage gives a concrete figure, step, date, or name "
"rather than general statements"),
},
)
readiness = r.scores["readiness"]
print("readiness", round(readiness.score, 2), "of 3", readiness.probabilities)
print("answer_first", r.nouls["answer_first"].noul)
print("specific", r.nouls["specific"].noul)Score levels start at 0, so this four-level rubric returns a value from 0 to 3. It is a probability-weighted average and can fall between levels (2.4, for example). Keep each passage to the paragraph you want quoted; long state is slower and less accurate.
curl --fail-with-body --silent --show-error \
https://api.typesafe.ai/v1/systemone \
-H "Authorization: Bearer $TYPESAFE_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @- <<'JSON'
{
"model": "jev-latest",
"state": {
"brand": "Acme CRM",
"prompt": "best CRM for a 10-person sales team",
"answer": "<paste the AI answer here>"
},
"questions": {
"brand_status": {
"type": "choice",
"instructions": "How the answer treats the brand",
"criteria": {
"recommended": "The brand is recommended or listed as a top pick",
"mentioned": "The brand is named, but not recommended",
"competitors_only": "Other products are named; the brand is not",
"absent": "No product or brand is named"
}
},
"favorable": {
"type": "noul",
"instructions": "Where the brand is named, it is described favorably"
}
}
}
JSONThe response holds answers.brand_status.choice with its probabilities, answers.favorable.noul, and usage.input_tokens. Store the prompt, engine, date, and the model field alongside each label.
How to write Jev questions that hold up
Describe every option
A Choice criterion with a description beats one with a bare name. "commercial: comparing products before buying" leaves less room for interpretation than "commercial".
Order Score levels from least to most
A Score is ordinal. Each level needs a real position on one scale, described in words. Mixing two dimensions (length and accuracy) in one rubric gives a number that means neither.
Ask several questions in one call
Questions share one state, so intent, page type, and an off-topic check on the same keyword belong in one request. Input tokens are billed; per the TypeSafe API docs, output tokens are currently free.
Keep arithmetic and exact rules in code
Click deltas, CTR, word counts, and "does this URL contain our domain" are code. Jev is for judgments a regex cannot make.
Keep the state short
Send the passage, snippet, or answer you are judging, not the whole page. Long context is slower and less accurate, and needs an extra opt-in header.
Frequently asked questions
What is Jev?
Jev is a decision model from TypeSafe AI. You send content (the state) and named questions of three main types, Choice, Score, and Noul, and it returns typed answers with probabilities instead of generated text. It is available through the TypeSafe API at api.typesafe.ai/v1/systemone and through Python and JavaScript SDKs.
Can Jev write SEO content or meta descriptions?
No. Jev never returns prose. Use a writing model to draft, then use Jev to choose between drafts, score them against your rubric, or flag problems before an editor reviews them.
Does Jev check whether ChatGPT or Perplexity mention my brand?
Not on its own. Jev does not browse or query other AI engines. You collect the answers for your prompts, and Jev labels each one: recommended, mentioned, competitors only, or absent. That turns a pile of answers into a number you can track over time.
When should I use Choice, Score, or Noul?
Use Choice when the answer is one of several named categories (search intent). Use Score when the answer is a position on an ordered scale (how well a passage answers a query). Use Noul for a single yes or no statement (the first sentence answers the question).
How is Jev billed?
The TypeSafe API documentation says input tokens are billable and output tokens are currently free. Each response returns usage.input_tokens, so you can measure a batch on a few rows before running the full list. Check the TypeSafe console for current prices.
Key takeaways
Jev is a judge, not a writer. Use Choice for search intent and for how AI answers treat your brand, Score for how quotable a passage is on its own, and Noul for single checks such as an answer-first opening or an unsourced figure. Describe every option, keep the state to the text you are judging, and leave arithmetic and exact matches to code. Set thresholds from 50 to 100 examples you labeled yourself, log the model version with every result, and treat a score as a reason to review, not as a forecast of rankings or citations.