Scoring · Score
Score Customer Sentiment with Jev
Jev sentiment as a Score: situational levels, a full probability distribution, and a code path that escalates angry mail.
- Published
- Sep 20, 2026
- Updated
- Sep 20, 2026
- Last verified
- Sep 20, 2026
Quick answer
Rate message tone on an ordered rubric instead of asking Jev for a happy/sad adjective.
Problem
A CSAT follow-up and a public review feed need a tone rank so agents see the worst threads first. A binary 'negative' flag loses the middle.
Why Jev fits this task
Tone is a spectrum. Official docs use customer frustration as the Score example. Keep the levels about observable language, not unstated emotion.
Input state
Send only the fields the questions name. Official docs warn that extra unrelated state costs accuracy.
{
"source": "in-app chat",
"message": "The new export is slower than last month, but your status page explained the backlog. I can wait until Friday."
}Question
How negative or positive is this customer message?
Question type: Score.
Jev schema
{
"model": "jev-latest",
"state": {
"source": "in-app chat",
"message": "The new export is slower than last month, but your status page explained the backlog. I can wait until Friday."
},
"questions": {
"sentiment": {
"type": "score",
"instructions": "What is the overall tone of `message`?",
"criteria": [
"Praise or thanks, no complaint",
"Neutral update or a contained complaint with a workaround",
"Strong dissatisfaction, demand, or public-threat language"
]
}
}
}Python example
from typesafe_sdk import Score, TypeSafeClient
state = {
"source": "in-app chat",
"message": "The new export is slower than last month, but your status page explained the backlog. I can wait until Friday.",
}
with TypeSafeClient() as client:
response = client.system_one(
state=state,
questions={
"sentiment": Score(
instructions="What is the overall tone of `message`?",
criteria=[
"Praise or thanks, no complaint",
"Neutral update or a contained complaint with a workaround",
"Strong dissatisfaction, demand, or public-threat language",
],
),
},
)
print(response.answers["sentiment"].score)
print(response.model)TypeScript example
import { score, TypeSafeClient } from "@typesafe-ai/sdk";
const client = new TypeSafeClient();
const response = await client.systemOne({
state: {
"source": "in-app chat",
"message": "The new export is slower than last month, but your status page explained the backlog. I can wait until Friday."
},
questions: {
sentiment: score("What is the overall tone of `message`?", [
"Praise or thanks, no complaint",
"Neutral update or a contained complaint with a workaround",
"Strong dissatisfaction, demand, or public-threat language"
]),
},
});
console.log(response.answers.sentiment.score);
console.log(response.model);JavaScript example
import { score, TypeSafeClient } from "@typesafe-ai/sdk";
const client = new TypeSafeClient();
const response = await client.systemOne({
state: {
"source": "in-app chat",
"message": "The new export is slower than last month, but your status page explained the backlog. I can wait until Friday."
},
questions: {
sentiment: score("What is the overall tone of `message`?", [
"Praise or thanks, no complaint",
"Neutral update or a contained complaint with a workaround",
"Strong dissatisfaction, demand, or public-threat language"
]),
},
});
console.log(response.answers.sentiment.score);
console.log(response.model);cURL example
curl -s https://api.typesafe.ai/v1/systemone \
-H "Authorization: Bearer $TYPESAFE_API_KEY" \
-H "Content-Type: application/json" \
-d @- <<'EOF'
{
"model": "jev-latest",
"state": {
"source": "in-app chat",
"message": "The new export is slower than last month, but your status page explained the backlog. I can wait until Friday."
},
"questions": {
"sentiment": {
"type": "score",
"instructions": "What is the overall tone of `message`?",
"criteria": [
"Praise or thanks, no complaint",
"Neutral update or a contained complaint with a workaround",
"Strong dissatisfaction, demand, or public-threat language"
]
}
}
}
EOFExpected output
{
"model": "jev-1.13.0",
"answers": {
"sentiment": {
"type": "score",
"score": 1.05,
"legend": {
"0": "Praise or thanks, no complaint",
"1": "Neutral update or a contained complaint with a workaround",
"2": "Strong dissatisfaction, demand, or public-threat language"
},
"probabilities": {
"0": 0.08,
"1": 0.79,
"2": 0.13
},
"confidence": 0.68
}
},
"usage": {
"input_tokens": 190,
"output_tokens": 20
}
}Confidence handling
Low confidence plus a mid score usually means mixed signals. Do not auto-tweet a reply. Official three-path pattern: act / confirm / escalate.
Production considerations
Store probabilities, not only the scalar. A U-shaped distribution (mass on 0 and 2) is a different ticket than a peaked 1.0.
Queue ordering, review triage, and 'do not auto-reply' gates.
When to use Jev
You want a rank to sort a queue and you can describe each rank in a sentence.
When not to use Jev
You need a marketing-grade emotion taxonomy, or you are trying to detect a specific intent — use the intent example.
Sentiment is not the same as urgency or refund eligibility. Official notes: one Score, one dimension. Sarcasm and non-English text need your own tests — English is officially strongest.
Common mistakes
- Asking a Noul 'is the customer unhappy?' and reading 0.5 as medium sentiment.
- Putting 'angry about billing' into one level so billing and tone get tangled.
FAQ
Is this an official sentiment API?
No. Sentiment here is an ordinary Score you define. TypeSafe does not ship a separate sentiment product in the public docs we verified.
Sources
- Primitives (Questions)TypeSafe · accessed 2026-09-20 · documentation
- API referenceTypeSafe · accessed 2026-09-20 · documentation
- Jev 1.13 jaggednessTypeSafe · 2026-09-17 · accessed 2026-09-20 · documentation