Triage customer calls, chats and messages for fraud reports

Grayson reads a call transcript, chat or secure message with the account's recent sign-ins, payments and contacts, and decides what it's about, whether to freeze now, where to route it and whether the customer is vulnerable.

Grayson reads a customer contact (a call transcript, a chat or a secure message) next to what your systems already know about the account, and returns what the contact is really about, whether to stop money leaving now, whether it goes to a fraud specialist now, the fraud queue or the support team for its topic, and whether the customer shows signs of vulnerability. It costs about $0.41 to $0.59 per 1,000 decisions.

  • Decides: Find fraud reports and scams in progress among customer contacts; decide whether to freeze now and where to route.
  • Call it: When a call, chat or message reaches your contact center, and while a call or chat is in progress
  • Questions: 2 choice, 2 yes/no
  • Cost: $0.00041 to $0.00059 per decision ($0.41 to $0.59 per 1,000) for these examples' 11,711 to 16,961 input tokens
  • Latency: 197 to 272 ms for these examples, the median of 5 calls each through api.finic.ai from US-West

Examples

Three contacts, each sent with the customer's profile and contact-detail changes, 60 days of transactions and digital banking sessions, payees, fraud rule hits, a phone-number check and a year of earlier contacts. They are a call about being locked out from a customer whose mobile number was just taken over, an angry secure message headed "FRAUD" about a gym membership and a hotel hold, and a chat from a recently widowed customer asking to raise her P2P limit for a roofer's deposit.

Open in Playground

Open in Playground

Open in Playground

A yes/no answer is Grayson's probability that it's true. A choice answer is the top option and Grayson's confidence: 0% when every option is equally likely, 100% when one option has all the probability. A score answer is the expected level, numbering the levels in its criteria from 0, with its confidence measured the same way and, when no level reaches 70%, each level's probability. A multiple-choice answer lists the options at 50% or more.

  • route is the routing decision: send fraud_now above a threshold straight to a specialist (warm transfer or a callback within minutes), and use fraud_queue and support_queue to set the queue when your keyword or IVR routing disagrees.
  • freeze_now is the probability that it's true: above a high threshold, block cards and hold outgoing payments automatically; between that and a lower one, prompt the agent to do it on the call.
  • intent sets the queue's reason code, and vulnerable turns on your vulnerable-customer handling (more time, a specialist, the trusted contact person), whatever the route.

Call it from your code

Save an example as request.json, such as legitimate.json, and send it with your API key in GRAYSON_API_KEY:

curl https://api.finic.ai/v1/decide \
  -H "Authorization: Bearer $GRAYSON_API_KEY" \
  -H "Content-Type: application/json" \
  --data @request.json

The problem

Contact centers route on words: an IVR hears "can't log in", a keyword rule sees "fraud". Customers in the middle of an account takeover often describe a login problem, scam victims ask for a higher limit, and angry customers call a gym's billing "fraud". The difference is in the records next to the contact: a SIM change an hour ago, a new device, a payee added today, or a recurring charge paid for 18 months.

What to send

Send the contact as your platform exports it, with what an agent's screens would show. The examples are about 12,000 to 17,000 input tokens each.

  • The contact, verbatim. Speaker turns and timestamps for calls and chats, subject and body for messages, with your IVR intent, routing and authentication.
  • Sign-ins, devices and security events. A password reset, new device or email change minutes before money moves is the core of an account takeover.
  • A phone-number check on the number on file. A recent SIM change explains a customer whose phone "just lost service" and whose codes went to someone else.
  • Recent payments, payees and what is still pending. A same-day ACH or a wire waiting for a callback is what a freeze can still stop.
  • Fraud rule hits and their status. An alert sitting unassigned in a queue is evidence that the contact is about it.
  • Earlier contacts and the customer profile. Bereavement notes, a trusted contact person and earlier calls about the same payee show who you are talking to.

Add your own policy

Whether every customer who says "fraud" goes to the fraud team is a policy choice, often made for complaint and Regulation E reasons, so put your routing standard in the state. This one sends any contact that calls a charge fraudulent or a scam to the fraud queue, and leaves the fraud team to pass merchant disputes on.

Your fraud-claim routing standard adds this to the state of the legitimate example:

{
  "routing_standard": "Contact routing standard, section 2 (rev. 2026-05). Any call, chat or message in which the customer says a charge or payment on their account is fraudulent, unauthorized, stolen or a scam goes to the fraud team's queue, to be worked the same business day, even when it looks like a merchant dispute or a billing error. The fraud team decides whether to handle it as an unauthorized-transaction claim or pass it to disputes. Freezes and holds are decided separately, on the evidence."
}
QuestionWithoutWith your fraud-claim routing standard
intentmerchant_dispute, confidence 88%merchant_dispute, confidence 84%
freeze_now2% true2% true
routesupport_queue, confidence 88%fraud_queue, confidence 87%
vulnerable2% true2% true

Applied to the routine support example: Jordan calls the studio's charges fraud and says they "stole" from him, so the route moves from the support queue to the fraud queue, while the intent stays a merchant dispute and there is still no freeze.

Where to call it

  • When a contact arrives: on each secure message and email, and when the IVR or virtual assistant hands a call or chat to a queue.
  • During a call or chat, each time the agent places the customer on hold or submits a request such as a limit increase, with the transcript so far.
  • On contacts already in a support queue, to pull out the fraud reports that keyword routing missed.

Cost and latency

ExampleInput tokensPer decisionPer 1,000 decisionsLatency
Obvious16,961$0.00059$0.59272 ms
Legitimate16,011$0.00056$0.56224 ms
Ambiguous11,711$0.00041$0.41197 ms

You pay only for input tokens, at $0.035 per million, and each request is rounded up to the next millionth of a dollar, so a request with a larger state costs proportionally more; every response reports its size in usage.input_tokens. Latency is the median of 5 calls each through api.finic.ai from US-West, and grows with the number of input tokens. Add your own network time to api.finic.ai.

Evaluate on your own data

Score Grayson on your own past cases before you use it: a CSV with one row per case and a column with the right answer to each question. Every other column is sent as the case.

pipx install https://docs.finic.ai/downloads/grayson_cli-0.4.0-py3-none-any.whl
grayson eval my-cases.csv --questions https://docs.finic.ai/recipes/customer-contact-triage/questions.json --label intent=<column> --label freeze_now=<column> --label route=<column> --label vulnerable=<column>

Each --label names the column with that question's right answer:

  • intent: unauthorized_activity, scam, lost_or_stolen, account_access, merchant_dispute, complaint, general_support
  • freeze_now: true or false
  • route: fraud_now, fraud_queue, support_queue
  • vulnerable: true or false

Or run grayson on its own to set up your questions step by step. You get each question's accuracy and a CSV with Grayson's answer next to yours for every case.

FAQ

Can it run while the customer is still on the line?

Yes. Send the transcript so far from your speech-to-text or agent-assist feed at natural pauses, such as a hold or a request the agent submits, and act on the latest answer. A call usually needs only a few requests, and each is priced and timed like the examples above.

What if a customer reports fraud in the wrong channel?

Under Regulation E, a consumer can notify you of an unauthorized electronic transfer in person, by phone or in writing, and notice counts as given when they take reasonable steps to tell you, whether or not the right employee receives it. A fraud report that waits in a general support queue can still start your clock, which is a reason to triage every contact, not only those your keyword rules catch.

Does vulnerable mean the customer lacks capacity?

No. It flags signs your team should act on, such as a recent bereavement, confusion or someone pressuring the customer, and leaves the judgment to trained staff. Upset or anger about the problem being reported doesn't count on its own, and neither does age, so an angry customer reporting fraud isn't flagged for that reason alone.

On this page