jevrecipes

Recipe catalog / handoff

Check handoff rules

Decide whether a request matches your human escalation rules.

You need to decide whether your escalation rules call for a human.

Explore this recipe interactively ยท Source and implementation guide

Use handoff 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 { handoff } from 'jev-recipes/handoff';

const result = await handoff({
  "request": "Please connect me with a person.",
  "rules": [
    {
      "id": "requested-human",
      "description": "The customer explicitly asks to speak with a human support representative."
    }
  ]
});
console.log(result);

Input contract

FieldTypeNeeded
requeststringRequired
contextstringOptional
rulesarrayRequired
minConfidencenumberOptional
Full input and result schemas
{
  "input": {
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "type": "object",
    "properties": {
      "request": {
        "type": "string"
      },
      "context": {
        "type": "string"
      },
      "rules": {
        "minItems": 1,
        "maxItems": 50,
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string"
            },
            "description": {
              "type": "string"
            }
          },
          "required": [
            "id",
            "description"
          ]
        }
      },
      "minConfidence": {
        "type": "number",
        "minimum": 0,
        "maximum": 1
      }
    },
    "required": [
      "request",
      "rules"
    ]
  },
  "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"
        ]
      },
      "decision": {
        "type": "string",
        "enum": [
          "human",
          "continue",
          "review"
        ]
      },
      "matchedRules": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "uncertainRules": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "checks": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string"
            },
            "status": {
              "type": "string",
              "enum": [
                "ready",
                "review"
              ]
            },
            "verdict": {
              "type": "string",
              "enum": [
                "matches",
                "does_not_match",
                "unclear"
              ]
            },
            "confidence": {
              "type": "number",
              "minimum": 0,
              "maximum": 1
            },
            "probabilities": {
              "type": "object",
              "propertyNames": {
                "type": "string",
                "enum": [
                  "matches",
                  "does_not_match",
                  "unclear"
                ]
              },
              "additionalProperties": {
                "type": "number",
                "minimum": 0,
                "maximum": 1
              },
              "required": [
                "matches",
                "does_not_match",
                "unclear"
              ]
            }
          },
          "required": [
            "id",
            "status",
            "verdict",
            "confidence",
            "probabilities"
          ],
          "additionalProperties": false
        }
      }
    },
    "required": [
      "model",
      "usage",
      "status",
      "decision",
      "matchedRules",
      "uncertainRules",
      "checks"
    ],
    "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 handoff.

{
  "model": "demo-fixture",
  "usage": {
    "input_tokens": 0,
    "output_tokens": 0
  },
  "status": "ready",
  "decision": "human",
  "matchedRules": [
    "requested-human"
  ],
  "uncertainRules": [],
  "checks": [
    {
      "id": "requested-human",
      "status": "ready",
      "verdict": "matches",
      "confidence": 0.96,
      "probabilities": {
        "matches": 0.97,
        "does_not_match": 0.015,
        "unclear": 0.015
      }
    }
  ]
}

Evaluation evidence

Earlier-evaluator measurement

jev-1.13.0 / 2026-09-27 / 40 held-out cases

Scoring revision 1.

90%All-case accuracy
12Sent for review
0Failed calls / cases

28 ready decisions, with 100% accuracy among those decisions.

95% case-level interval: 77% to 96%. 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

Related recipes