Recipe catalog / callback-responsibility
Identify who should initiate a callback
Which party is expected to initiate the next call?
You need to decide whether the business or customer is expected to initiate the next call.
Explore this recipe interactively ยท Source and implementation guide
Use callback-responsibility 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 { callbackResponsibility } from 'jev-recipes/callback-responsibility';
const result = await callbackResponsibility({
"conversation": "Avery: I will call you when the replacement arrives. Sam: Thanks, I will wait for your call.",
"roles": "Avery is the business representative. Sam is the customer.",
"minConfidence": 0.8
});
console.log(result);
Input contract
| Field | Type | Needed |
|---|---|---|
| conversation | string | Required |
| roles | string | Required |
| minConfidence | number | Optional |
Full input and result schemas
{
"input": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"conversation": {
"type": "string"
},
"roles": {
"type": "string"
},
"minConfidence": {
"type": "number",
"minimum": 0,
"maximum": 1
}
},
"required": [
"conversation",
"roles"
]
},
"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"
]
},
"verdict": {
"type": "string",
"enum": [
"business",
"customer",
"either",
"none",
"unclear"
]
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"probabilities": {
"type": "object",
"propertyNames": {
"type": "string",
"enum": [
"business",
"customer",
"either",
"none",
"unclear"
]
},
"additionalProperties": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"required": [
"business",
"customer",
"either",
"none",
"unclear"
]
}
},
"required": [
"model",
"usage",
"status",
"verdict",
"confidence",
"probabilities"
],
"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 callback-responsibility.
{
"model": "demo-fixture",
"usage": {
"input_tokens": 0,
"output_tokens": 0
},
"status": "ready",
"verdict": "business",
"confidence": 0.94,
"probabilities": {
"business": 0.94,
"customer": 0.01,
"either": 0.01,
"none": 0.01,
"unclear": 0.03
}
}
Evaluation evidence
jev-1.13.0 / 2026-09-27 / 40 held-out cases
Scoring revision 1.
24 ready decisions, with 100% accuracy among those decisions.
95% case-level interval: 87% to 100%. Related synthetic cases are correlated.
Measured on these synthetic cases
This measurement uses an earlier or unverified recipe or evaluator version. Rerun with the current recipe and evaluator before treating these numbers as current.
Use the evaluation guide to measure this decision on your own labeled cases.
Limitations
- Requires speaker roles. Does not infer identities from names or assume every agent speaks for the business.
- Only identifies initiation of a future call, including a conditional call. Does not assign general task ownership or verify the call occurred.
- An unaccepted suggestion, contradictory exchange, or unresolved pronoun requires review.
Related recipes
- promise-check: Use promise-check to check whether a draft introduces an unsupported commitment.
- commitment-strength: Use commitment-strength to grade how firmly a statement commits its speaker.
- followup-timing: Use followup-timing for when another contact is wanted.