Template - Policy
PredicateRefund eligibility
Whether a refund request should be approved under your written refund policy.
A predicate decision for refund requests, with evidence checks for the facts a policy usually turns on: duplicate charges, the refund window, and refund history.
The decision
Should this refund request be approved under our 30-day refund policy?
Evidence checks (asked in the same request)
- Duplicate charge: The customer reports being charged more than once.
- Within refund window: The purchase was made within the 30-day refund window.
- Prior refunds: The customer has received a previous refund.
Expected output: A probability from 0 to 1 that the request should be approved, 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.
| Field | Type | Required | Description |
|---|---|---|---|
message | string | Yes | The customer's message, verbatim. Include the subject line if there is one. |
purchase_date | string | No | ISO date of the purchase. Prepend it to the input so the model doesn't have to infer it. |
prior_refund_count | number | No | Refunds this customer has already received. |
Worked examples
Duplicate charge, five days after purchase
I was charged twice for my annual plan (order #48213). I only signed up once, 5 days ago. Please refund the duplicate charge.
A careful reviewer would say: Yes. A duplicate charge is a billing error, and the request is inside the window.
Run this exampleChange of mind, seven months later
I bought the Pro plan 7 months ago and used it daily, but I no longer need it. Can I get my money back?
A careful reviewer would say: No. Well outside the 30-day window, with heavy use and no fault on the company's side.
Run this example
Expected answers are human judgments written for this template, not model output.
How it works
Refund decisions are a good first candidate for automation because the policy is usually written down and the outcome is binary. The predicate asks one thing: does this request meet the policy?
Put the policy's actual terms in the question. "Under our 30-day refund policy" gives the model a concrete test. "Should we refund this?" invites it to apply its own idea of fairness.
The evidence checks do two jobs. They show a reviewer why a request scored the way it did, and they give you facts you can gate on directly: you may choose to auto-approve every duplicate charge that billing data confirms, regardless of the overall probability.
Human review and thresholds
Recommended review policy
Automate approvals only at high probability and when the amount is under a limit you set. Send mid-range probabilities to a person. Consider routing every likely denial to review at first: a wrongly denied refund costs more goodwill than a slow one.
Choosing thresholds
The two errors are not symmetric. A false approval costs the refund amount. A false denial costs a customer relationship and possibly a chargeback. Most teams should set a higher bar for automated denials than for automated approvals, and scale the approval bar with the refund amount.
- Starting automation threshold
- 90%
- Starting don’t-decide threshold
- 60%
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 model only sees what you send. If purchase dates and refund history live in your billing system, include them in the input rather than hoping the customer mentions them.
- Customers can be wrong or dishonest about facts. A stated duplicate charge should be verified against billing data before money moves.
- Policies with judgment clauses ("at our discretion", "in exceptional circumstances") need a separate decision. See the policy exception template.
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.
{
"$format": "thethinkloop.template/v1",
"slug": "refund-eligibility",
"title": "Refund eligibility",
"decides": "Whether a refund request should be approved under your written refund policy.",
"question": {
"name": "decision",
"type": "predicate",
"instructions": "Should this refund request be approved under our 30-day refund policy?"
},
"evidenceChecks": [
{
"name": "factor_1",
"label": "Duplicate charge",
"type": "predicate",
"instructions": "The customer reports being charged more than once."
},
{
"name": "factor_2",
"label": "Within refund window",
"type": "predicate",
"instructions": "The purchase was made within the 30-day refund window."
},
{
"name": "factor_3",
"label": "Prior refunds",
"type": "predicate",
"instructions": "The customer has received a previous refund."
}
],
"inputs": [
{
"name": "message",
"type": "string",
"required": true,
"description": "The customer's message, verbatim. Include the subject line if there is one."
},
{
"name": "purchase_date",
"type": "string",
"required": false,
"description": "ISO date of the purchase. Prepend it to the input so the model doesn't have to infer it."
},
{
"name": "prior_refund_count",
"type": "number",
"required": false,
"description": "Refunds this customer has already received."
}
],
"expectedOutput": "A probability from 0 to 1 that the request should be approved, plus one probability per evidence check.",
"examples": [
{
"title": "Duplicate charge, five days after purchase",
"input": "I was charged twice for my annual plan (order #48213). I only signed up once, 5 days ago. Please refund the duplicate charge.",
"expected": "Yes"
},
{
"title": "Change of mind, seven months later",
"input": "I bought the Pro plan 7 months ago and used it daily, but I no longer need it. Can I get my money back?",
"expected": "No"
}
],
"startingPolicy": {
"automateAt": 0.9,
"abstainBelow": 0.6,
"note": "A starting point for exploration, not a recommendation. Calibrate against your own labeled examples."
}
}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: "I was charged twice for my annual plan (order #48213). I only signed up once, 5 days ago. Please refund the duplicate charge.",
questions: [
{
type: "predicate",
name: "decision",
instructions: "Should this refund request be approved under our 30-day refund policy?"
},
{
type: "predicate",
name: "factor_1",
instructions: "The customer reports being charged more than once."
},
{
type: "predicate",
name: "factor_2",
instructions: "The purchase was made within the 30-day refund window."
},
{
type: "predicate",
name: "factor_3",
instructions: "The customer has received a previous refund."
}
],
});
// 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 refund-eligibility.json, or browse all developer resources.
Need this decision tuned to your policy?
Related
- Predicate template
Policy exception
Whether a request that falls outside policy deserves an exception.
- Predicate template
Billing escalation
Whether a billing issue should leave the support queue and go to finance.
- Predicate template
Automate or review
Whether a request is safe to resolve automatically or needs a person.
- Guide
Confidence thresholds
Probability, confidence, accuracy, calibration, and correctness are different things. How to set a review policy from the cost of each kind of mistake.
- Guide
Human-in-the-loop AI
When should AI decide and when should it ask? Review patterns, what reviewers need to see, sizing the queue, and keeping oversight real.
- Guide
Calibrating AI decisions
The procedure for checking whether confidence means what it says: how much data you need, what to compute, and how to read the result without fooling yourself.