Skip to content
TheThinkLoop

Template - Support

Predicate

Billing escalation

Whether a billing issue should leave the support queue and go to finance.

A predicate decision for billing conversations that carry financial or legal risk and should not wait in a general queue.

The decision

PredicateA probability from 0 to 1 that the condition holds.

Should this billing issue be escalated to the finance team?

Evidence checks (asked in the same request)

  • Duplicate charge: The customer reports being charged more than once.
  • Legal or chargeback risk: The customer mentions a chargeback, bank dispute, or legal action.
  • Repeat contact: The customer has contacted us about this before.

Expected output: A probability from 0 to 1 that the issue should be escalated, plus one probability per evidence check.

Input

The Decisions API reads one input. Combine these fields into it as labeled text so the model sees the facts the decision depends on.

Input fields
FieldTypeRequiredDescription
messagestringYesThe customer's message, verbatim. Include the subject line if there is one.
disputed_amountnumberNoThe amount in question, if known from billing data.

Worked examples

  1. Repeated contact with a threatened bank dispute

    This is the third time I've written about invoice #2291. You charged us $4,800 twice and I still have no response. If this isn't fixed this week I'll dispute it with my bank.

    A careful reviewer would say: Yes. A large duplicate charge, repeated contact, and a threatened dispute all point to escalation.

    Run this example
  2. Routine invoice copy

    Could you send me a copy of last month's invoice? Thanks!

    A careful reviewer would say: No. A routine request any agent can complete.

    Run this example

Expected answers are human judgments written for this template, not model output.

How it works

Most billing tickets are routine: copies of invoices, card updates, plan changes. A few carry real exposure, such as disputed charges or chargeback threats. This decision separates the two.

A chargeback threat is worth gating on by itself. The evidence check for legal or chargeback risk is often more useful than the headline probability.

Human review and thresholds

Recommended review policy

Escalation is itself a hand-off to a person, so automated "Yes" results are low-risk. The risk is in automated "No" results: sample them regularly to see what is being left in the general queue.

Choosing thresholds

A missed escalation can become a chargeback or a lost account, while an unnecessary one costs a few minutes of a finance person's time. That usually justifies a low bar for escalating.

Starting automation threshold
80%
Starting don’t-decide threshold
55%

Starting points for the playground, not recommendations. The right values depend on your costs and on how the model’s confidence tracks accuracy on your data. Calibrate them.

Limitations

  • The amount at stake often isn't in the message. Add it from billing data when you have it.
  • The model can't verify that a duplicate charge actually happened. Escalation means a person checks.
  • Tone is not a reliable indicator of financial risk. Polite messages can describe serious billing errors.

Use it in your code

The template definition is plain JSON: the question, the evidence checks, the input fields, and the starting policy. The SDK call below sends the same question and checks to the Decisions API from your server.

billing-escalation.jsonjson
{
  "$format": "thethinkloop.template/v1",
  "slug": "billing-escalation",
  "title": "Billing escalation",
  "decides": "Whether a billing issue should leave the support queue and go to finance.",
  "question": {
    "name": "decision",
    "type": "predicate",
    "instructions": "Should this billing issue be escalated to the finance team?"
  },
  "evidenceChecks": [
    {
      "name": "factor_1",
      "label": "Duplicate charge",
      "type": "predicate",
      "instructions": "The customer reports being charged more than once."
    },
    {
      "name": "factor_2",
      "label": "Legal or chargeback risk",
      "type": "predicate",
      "instructions": "The customer mentions a chargeback, bank dispute, or legal action."
    },
    {
      "name": "factor_3",
      "label": "Repeat contact",
      "type": "predicate",
      "instructions": "The customer has contacted us about this before."
    }
  ],
  "inputs": [
    {
      "name": "message",
      "type": "string",
      "required": true,
      "description": "The customer's message, verbatim. Include the subject line if there is one."
    },
    {
      "name": "disputed_amount",
      "type": "number",
      "required": false,
      "description": "The amount in question, if known from billing data."
    }
  ],
  "expectedOutput": "A probability from 0 to 1 that the issue should be escalated, plus one probability per evidence check.",
  "examples": [
    {
      "title": "Repeated contact with a threatened bank dispute",
      "input": "This is the third time I've written about invoice #2291. You charged us $4,800 twice and I still have no response. If this isn't fixed this week I'll dispute it with my bank.",
      "expected": "Yes"
    },
    {
      "title": "Routine invoice copy",
      "input": "Could you send me a copy of last month's invoice? Thanks!",
      "expected": "No"
    }
  ],
  "startingPolicy": {
    "automateAt": 0.8,
    "abstainBelow": 0.55,
    "note": "A starting point for exploration, not a recommendation. Calibrate against your own labeled examples."
  }
}
Equivalent SDK calljavascript
import OpenAI from "openai"; // openai >= 7.30.0

const client = new OpenAI(); // reads OPENAI_API_KEY on the server

const decision = await client.decisions.create({
  model: "gpt-6-luna",
  input: "This is the third time I've written about invoice #2291. You charged us $4,800 twice and I still have no response. If this isn't fixed this week I'll dispute it with my bank.",
  questions: [
    {
      type: "predicate",
      name: "decision",
      instructions: "Should this billing issue be escalated to the finance team?"
    },
    {
      type: "predicate",
      name: "factor_1",
      instructions: "The customer reports being charged more than once."
    },
    {
      type: "predicate",
      name: "factor_2",
      instructions: "The customer mentions a chargeback, bank dispute, or legal action."
    },
    {
      type: "predicate",
      name: "factor_3",
      instructions: "The customer has contacted us about this before."
    }
  ],
});

// Answers come back in question order. A question can also be refused.
const [main, ...checks] = decision.answers;
if (main.type === "refusal") throw new Error("The model declined to answer.");
if (main.type === "predicate") {
  console.log(main.probability); // 0–1 estimate that the condition is true
}

Download it as billing-escalation.json, or browse all developer resources.

Need this decision tuned to your policy?

We are running a small number of pilots with B2B teams: your policy, your examples, your thresholds. Request early access.