Recipe catalog / satisfaction-signal
Grade expressed satisfaction
How much satisfaction with the outcome does message express at the close of an interaction, on a five-level rubric?
You need a graded satisfaction signal from closing messages when no survey response is available.
Explore this recipe interactively ยท Source and implementation guide
Use satisfaction-signal in TypeScript
Install with npm install jev-recipes. Requires Node.js 22.9 or newer and ES modules. Set TYPESAFE_API_KEY in your server environment for live calls, which send input to TypeSafe and use API quota. See the installation guide.
import { satisfactionSignal } from 'jev-recipes/satisfaction-signal';
const result = await satisfactionSignal({
"message": "That fixed it, thank you so much for staying on this with me. Really appreciate the quick turnaround.",
"context": "Final customer message after an agent reissued a failed refund.",
"minConfidence": 0.8
});
console.log(result);
Input contract
| Field | Type | Needed |
|---|---|---|
| message | string | Required |
| context | string | Optional |
| minConfidence | number | Optional |
Full input and result schemas
{
"input": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"message": {
"type": "string"
},
"context": {
"type": "string"
},
"minConfidence": {
"type": "number",
"minimum": 0,
"maximum": 1
}
},
"required": [
"message"
]
},
"result": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"model": {
"type": "string"
},
"usage": {
"type": "object",
"properties": {
"input_tokens": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"output_tokens": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
}
},
"required": [
"input_tokens",
"output_tokens"
],
"additionalProperties": false
},
"status": {
"type": "string",
"enum": [
"ready",
"review"
]
},
"score": {
"type": "number",
"minimum": 0
},
"level": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"probabilities": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "number",
"minimum": 0,
"maximum": 1
}
},
"satisfaction": {
"type": "string",
"enum": [
"dissatisfied",
"low",
"neutral",
"satisfied",
"delighted"
]
}
},
"required": [
"model",
"usage",
"status",
"score",
"level",
"confidence",
"probabilities",
"satisfaction"
],
"additionalProperties": false
}
}Saved example result
This hand-authored response demonstrates the contract. It is not a model accuracy measurement. Run it without an API key: npx jev-recipes demo satisfaction-signal.
{
"model": "demo-fixture",
"usage": {
"input_tokens": 0,
"output_tokens": 0
},
"status": "ready",
"score": 3.84,
"level": 4,
"confidence": 0.88,
"probabilities": {
"0": 0,
"1": 0.01,
"2": 0.02,
"3": 0.09,
"4": 0.88
},
"satisfaction": "delighted"
}
Evaluation evidence
No verified live accuracy measurement is available. Evaluate representative cases before using this decision in your workflow.
Use the evaluation guide to measure this decision on your own labeled cases.
Limitations
- Grades expressed wording at the close of an interaction, not actual satisfaction, retention, or survey scores.
- The score is an expected value over rubric levels. Application code chooses cutoffs.
Related recipes
- resolution-check: Use resolution-check to decide whether the customer reported the issue itself resolved.
- frustration-signal: Use frustration-signal for a categorical read on expressed frustration in any message.