Detect insider threats in employee account access
Grayson triages insider risk alerts: whether an employee opened customer accounts without a business reason, why, and whether to close, refer or suspend.
Grayson triages alerts on employee access to customer accounts: whether the employee opened or changed accounts without a business reason, how likely they are to be helping outside fraudsters, what best explains the activity, and whether to close the alert, refer it to your insider risk team or suspend the employee's access now. It reads the employee's access log for the alert window against their usual volume and their peers', the calls, chats, branch visits and tickets around each lookup, and what happened to the accounts afterward, and costs about $0.56 to $0.79 per 1,000 alerts.
- Decides: Decide whether an employee's account access is work, snooping or insider fraud, and close, refer or suspend.
- Call it: When access monitoring flags an employee's activity on customer accounts
- Questions: 1 yes/no, 1 score, 2 choice
- Cost: $0.00056 to $0.00079 per decision ($0.56 to $0.79 per 1,000) for these examples' 15,884 to 22,461 input tokens
- Latency: 243 to 283 ms for these examples, the median of 5 calls each through api.finic.ai from US-West
Examples
Three alerts, each sent with the employee's full access log for the week, eight weeks of their counts against their peers', the records around each unlinked lookup and what happened to the accounts afterward. A remote contractor changed phone numbers at night on accounts taken over the next day; a card services agent's outbound reissue calls never linked to her lookups; and a branch banker's ID-scan override let an impostor with a counterfeit license change a customer's phone number.
Open in Playground
A remote contractor changed phone numbers at night on accounts taken over the next day. A digital banking support contractor who had just given notice opened 12 high-balance accounts outside their queue, 14 of the lookups in two late-night VPN sessions, with no calls behind them. In those sessions they changed the phone numbers on three accounts to VoIP lines under tickets that no call supports, and all three were taken over within 36 hours, one losing a $48,500 wire.
| Question | Grayson's answer |
|---|---|
access_without_business_reason | 96% true |
enabling_fraud_likelihood | 3.66 of 4, confidence 84% |
explanation | enabling_fraud, confidence 93% |
action | suspend, confidence 96% |
20,710 input tokens, $0.00072 per decision, answered in 243 ms.
The request, with long lists cut short. The full request is fraud.json (80 KB).
{
"model": "grayson-1",
"state": {
"alert": {
"id": "IR-ALR-21093",
"source": "Employee access monitoring over CRM, core banking and digital banking admin logs",
"created": "2026-10-05T11:00:00Z",
"window_start": "2026-09-28T00:00:00Z",
"window_end": "2026-10-04T23:59:59Z",
"priority": "P1",
"rules_fired": [
"IR-04: 3 or more account lookups in 7 days with no call, chat, ticket or case linked within 30 minutes (16 in this window)",
"IR-07: Sessions outside the scheduled shift (2 sessions, 14 lookups)",
"IR-12: Lookup of an account with a balance over $250,000 that is outside the employee's queue (4 accounts)",
"IR-14: Phone or email change with no inbound call or chat handled by the employee in the 30 minutes before (5 changes on 3 accounts)",
"IR-16: Session from a network not seen for this user in the last 30 days (2 sessions)",
"IR-21: Account the employee accessed had a confirmed or suspected takeover within 7 days (3 accounts)"
]
},
"employee": {
"employee_id": "E-71964",
"employment_type": "Contractor through a contact-center staffing vendor (vendor V-114)",
"role": "Digital banking support agent, tier 2",
"start_date": "2026-06-15",
"queue": "Inbound calls and chats about online and mobile banking: login problems, password resets, locked access, device enrollment",
"work_location": "Remote, through a virtual desktop (VDI)",
"scheduled_shift": "Monday to Friday, 12:00 to 20:30 UTC (08:00 to 16:30 Eastern)",
"entitlements": "View customer profiles, balances, contact details, authentication profile and online banking status; send password reset links; unlock online banking; remove devices; change phone and email after identity verification. No payments or money movement.",
"entitlement_changes": [
"2026-09-08: phone and email change added after tier 2 training (standard for the role)"
],
"identity_verification_policy": "Phone or email changes need a one-time code to the phone or email on file. If the customer can't receive one, the agent may verify with knowledge-based questions (KBA) on a live inbound call and must note it in a ticket.",
"background_check": "Completed by the vendor 2026-06-02, no findings",
"privacy_training": "Completed 2026-06-19",
"employment_status": "Vendor told us on 2026-10-01 that the contractor gave notice; last day 2026-10-09",
"conflict_of_interest_disclosures": "None on file",
"quality_scores": "Call quality reviews July to September: 4 reviews, all passed",
"prior_alerts": []
},
"weekly_history": {
"columns": [
"week_start",
"lookups",
"linked",
"unlinked",
"account_changes",
"phone_or_email_changes",
"sessions_outside_shift",
"dlp_events"
],
"rows": [
[
"2026-08-03",
208,
208,
0,
71,
0,
0,
1
],
[
"2026-08-10",
221,
220,
1,
77,
0,
0,
0
],
[
"2026-08-17",
214,
214,
0,
74,
0,
0,
1
],
[
"2026-08-24",
229,
229,
0,
81,
0,
0,
0
],
[
"2026-08-31",
181,
180,
1,
63,
0,
0,
0
],
[
"2026-09-07",
199,
199,
0,
70,
2,
0,
0
],
[
"2026-09-14",
232,
230,
2,
84,
5,
0,
0
],
[
"2026-09-21",
236,
231,
5,
82,
6,
0,
1
]
]
},
"peer_baseline": "Digital banking support agents, tier 2 (64 agents, employees and contractors), per agent per week over the last 8 weeks: lookups median 224 (95th percentile 281); unlinked lookups median 1 (95th percentile 4); phone or email changes median 5 (95th percentile 11), with no inbound contact before them median 0 (95th percentile 0); sessions outside shift median 0 (95th percentile 1, all approved overtime).",
"monitoring_notes": "No phone, chat or CRM outages and no link-check incidents in this window. Tickets count as links for IR-04, so lookups within 30 minutes of a ticket the employee created are not counted as unlinked.",
"sessions": {
"columns": [
"login",
"logout",
"client",
"source_network",
"phone_system"
],
"rows": [
[
"2026-09-28T11:46:03Z",
"2026-09-28T20:36:55Z",
"VDI from personal laptop (seen since 2026-06-15)",
"198.51.100.24, residential ISP, Tampa, FL",
"logged in for the shift"
],
[
"2026-09-29T11:53:29Z",
"2026-09-29T20:33:07Z",
"VDI from personal laptop (seen since 2026-06-15)",
"198.51.100.24, residential ISP, Tampa, FL",
"logged in for the shift"
],
[
"2026-09-30T11:49:15Z",
"2026-09-30T20:34:49Z",
"VDI from personal laptop (seen since 2026-06-15)",
"198.51.100.24, residential ISP, Tampa, FL",
"logged in for the shift"
],
[
"2026-10-01T02:09:14Z",
"2026-10-01T02:51:40Z",
"VDI from personal laptop (same device)",
"203.0.113.77, hosting provider ASN used by a commercial VPN service; first seen for this user",
"not logged in"
],
[
"2026-10-01T11:50:31Z",
"2026-10-01T20:32:28Z",
"VDI from personal laptop (seen since 2026-06-15)",
"198.51.100.24, residential ISP, Tampa, FL",
"logged in for the shift"
],
[
"2026-10-02T11:50:04Z",
"2026-10-02T20:39:42Z",
"VDI from personal laptop (seen since 2026-06-15)",
"198.51.100.24, residential ISP, Tampa, FL",
"logged in for the shift"
],
[
"2026-10-03T03:02:26Z",
"2026-10-03T03:41:05Z",
"VDI from personal laptop (same device)",
"203.0.113.81, same hosting provider ASN",
"not logged in"
]
]
},
"access_log": {
"columns": [
"ts",
"account",
"holder",
"viewed",
"seconds",
"change",
"linked_to"
],
"rows": [
[
"2026-09-28T12:07:02Z",
"savings x5004",
"customer",
"profile, devices, login history, contact details",
440,
"online banking unlocked",
"chat CH-552103"
],
[
"2026-09-28T12:19:14Z",
"money market x6091",
"customer",
"profile, online banking status",
445,
"",
"call CL-48810233"
],
[
"2026-09-28T12:37:52Z",
"money market x0083",
"customer",
"profile, devices",
299,
"",
"call CL-48810529"
],
[
"2026-09-28T12:46:24Z",
"money market x5737",
"customer",
"profile, login history",
464,
"",
"call CL-48810679"
],
[
"2026-09-28T12:59:05Z",
"checking x9391",
"customer",
"profile, contact details, authentication profile",
335,
"password reset link sent to email on file",
"call CL-48811077"
],
"… 222 more in fraud.json"
]
},
"contact_and_security_changes": {
"columns": [
"ts",
"account",
"change",
"verification_recorded",
"linked_to",
"contact_behind_the_link"
],
"rows": [
[
"2026-09-28T17:10:36Z",
"credit card x6369",
"trusted devices reset",
"customer signed in to the mobile app chat",
"chat CH-552237",
"inbound contact handled by E-71964"
],
[
"2026-09-28T18:58:16Z",
"money market x1812",
"trusted devices reset",
"caller authenticated in IVR (card and PIN)",
"call CL-48814565",
"inbound contact handled by E-71964"
],
[
"2026-09-29T13:25:55Z",
"money market x2908",
"device removed",
"caller authenticated in IVR (card and PIN)",
"call CL-48817064",
"inbound contact handled by E-71964"
],
[
"2026-09-29T13:42:08Z",
"money market x9465",
"device removed",
"OTP to phone on file",
"call CL-48817497",
"inbound contact handled by E-71964"
],
[
"2026-09-29T13:50:21Z",
"money market x2066",
"device removed",
"caller authenticated in IVR (card and PIN)",
"call CL-48817875",
"inbound contact handled by E-71964"
],
"… 24 more in fraud.json"
]
},
"tickets_created_without_a_contact": [
{
"id": "TK-604417",
"created": "2026-10-01T02:29:51Z",
"account": "premier checking x3318",
"category": "Contact details update",
"text": "Cust called in, lost phone, cant receive code. Verified via KBA (4/4). Updated mobile and added email per cust request."
},
{
"id": "TK-605190",
"created": "2026-10-03T03:10:12Z",
"account": "checking x5120",
"category": "Contact details update",
"text": "Customer lost phone. KBA passed. Updated phone per customer."
},
{
"id": "TK-605193",
"created": "2026-10-03T03:18:40Z",
"account": "savings x0457",
"category": "Contact details update",
"text": "New phone, cust cant get code on old number. KBA passed. Updated phone, email, cleared old device."
}
],
"endpoint_events": {
"columns": [
"ts",
"event",
"detail"
],
"rows": [
[
"2026-08-19T15:02:11Z",
"clipboard copy from VDI to local device blocked",
"window: Ticketing - TK-571220"
],
[
"2026-09-24T13:40:52Z",
"clipboard copy from VDI to local device blocked",
"window: CRM - Customer profile"
],
[
"2026-09-29T16:52:30Z",
"clipboard copy from VDI to local device blocked",
"window: CRM - Contact details"
],
[
"2026-10-01T02:13:05Z",
"screen capture by a local tool blocked by VDI screen protection",
"window: CRM - Authentication profile"
],
[
"2026-10-01T02:16:40Z",
"clipboard copy from VDI to local device blocked",
"window: CRM - Contact details"
],
"… 5 more in fraud.json"
]
},
"endpoint_summary": "No prints, file downloads, USB use or external email from the VDI in the window. The VDI blocks clipboard transfer and local screen capture; it can't detect a phone camera.",
"accounts_in_the_alert": {
"columns": [
"account",
"holder",
"balance_usd",
"customer_since",
"online_banking",
"phone_on_file",
"notes"
],
"rows": [
[
"premier checking x3318",
"customer",
287410.55,
"1994-03",
"not enrolled",
"home landline (before the window)",
"Last contact with us: branch visit 2026-08-14 (B-0107); phone and email changed 2026-10-01; fraud claim FC-2026-118240 opened 2026-10-03"
],
[
"money market x1186",
"customer",
412006.12,
"2001-11",
"not enrolled",
"home landline (before the window)",
"Last contact with us: phone call 2026-05-02"
],
[
"savings x7742",
"customer",
96220,
"2008-06",
"enrolled, last login 2025-10-19",
"home landline (before the window)",
"Last contact with us: branch visit 2026-07-30"
],
[
"checking x2659",
"customer",
58913.4,
"1999-01",
"not enrolled",
"home landline (before the window)",
"Last contact with us: branch visit 2026-09-03"
],
[
"checking x5120",
"customer",
236775.09,
"1988-09",
"not enrolled",
"home landline (before the window)",
"Last contact with us: branch visit 2026-08-27; phone changed 2026-10-03; fraud claim FC-2026-118231 opened 2026-10-03"
],
"… 7 more in fraud.json"
]
},
"unlinked_lookups_with_other_records": {
"columns": [
"lookup_ts",
"account",
"holder",
"employee_phone_state",
"other_records"
],
"rows": [
[
"2026-09-29T16:51:12Z",
"premier checking x3318",
"customer",
"after-call work following chat CH-552387 with another customer",
"No call, chat or ticket about this customer with any agent within 24 hours; no IVR call from the phone on file"
],
[
"2026-09-30T14:07:40Z",
"checking x5120",
"customer",
"available, no call",
"No call, chat or ticket about this customer with any agent within 24 hours; no IVR call from the phone on file"
],
[
"2026-09-30T18:40:05Z",
"money market x6631",
"customer",
"after-call work following call CL-48827907 with another customer",
"No call, chat or ticket about this customer with any agent within 24 hours; no IVR call from the phone on file"
],
[
"2026-10-01T02:15:58Z",
"money market x1186",
"customer",
"not logged in to the phone system",
"No call, chat or ticket about this customer with any agent within 24 hours; no IVR call from the phone on file"
],
[
"2026-10-01T02:19:20Z",
"savings x7742",
"customer",
"not logged in to the phone system",
"No call, chat or ticket about this customer with any agent within 24 hours; no IVR call from the phone on file"
],
"… 11 more in fraud.json"
]
},
"activity_after_access": {
"columns": [
"ts",
"account",
"event"
],
"rows": [
[
"2026-10-01T02:32:05Z",
"premier checking x3318",
"Phone-change notice by text to the previous number failed (landline); notice letter mailed to the address on file 2026-10-01"
],
[
"2026-10-01T15:12:44Z",
"premier checking x3318",
"First online banking enrollment on this account, from a new Android device, IP 203.0.113.140 (hosting provider ASN); one-time code sent to (727) 555-0143 and entered"
],
[
"2026-10-01T15:31:09Z",
"premier checking x3318",
"External account added for transfers by instant verification; owner name on the external account does not match the customer"
],
[
"2026-10-02T14:05:37Z",
"premier checking x3318",
"Online wire request $48,500.00 to Kestrelmoor Supply LLC, a new beneficiary; wire-room callback to the phone on file, (727) 555-0143, confirmed; released 16:40:12Z"
],
[
"2026-10-03T03:12:40Z",
"checking x5120",
"Phone-change notice by text to the previous number failed (landline); notice letter mailed 2026-10-03"
],
"… 7 more in fraud.json"
]
}
},
"questions": {
"access_without_business_reason": {
"type": "noul",
"instructions": "Did the employee open or change any customer account in this alert without a business reason, meaning that no customer contact, ticket, assigned case or other work item explains it?"
},
"enabling_fraud_likelihood": {
"type": "score",
"instructions": "How likely is it that the employee is helping people outside the institution commit fraud against customer accounts, for example by passing on account details or changing accounts so that others can take them over?",
"criteria": [
"Very unlikely (under 10%)",
"Unlikely (10-40%)",
"Uncertain (40-60%)",
"Likely (60-90%)",
"Very likely (over 90%)"
]
},
"explanation": {
"type": "choice",
"instructions": "What is the most likely explanation for the employee's activity flagged in this alert?",
"criteria": {
"legitimate_work": "Legitimate work: customer contacts, tickets, assigned cases, training or supervisory review explain the activity",
"snooping": "Curiosity or snooping: the employee viewed accounts with no business reason, without changing them or using what they saw for gain",
"self_dealing": "Self-dealing: the employee used their access to benefit themselves or someone linked to them, for example by reversing fees or raising limits on their own or a household member's account",
"enabling_fraud": "Enabling outside fraud: the employee looked up or changed accounts so that people outside the institution could take them over or take money from them",
"policy_mistake": "Policy mistake: the employee was handling a real customer's real request but skipped a required step, such as logging the contact or verifying identity"
}
},
"action": {
"type": "choice",
"instructions": "What should happen with this alert now?",
"criteria": {
"no_action": "Close the alert as legitimate activity, with no action against the employee",
"refer": "Refer the employee to the insider risk team for investigation, leaving their system access in place for now",
"suspend": "Suspend the employee's system access now and escalate to the insider risk team and HR"
}
}
}
}The response. Probabilities and confidence are shortened to four decimals here, and the score to three; responses carry full precision.
{
"id": "dec_1370697217f34d1d8471737f8570cf98",
"model": "grayson-1",
"answers": {
"access_without_business_reason": {
"type": "noul",
"noul": 0.9627
},
"enabling_fraud_likelihood": {
"type": "score",
"score": 3.659,
"legend": {
"0": "Very unlikely (under 10%)",
"1": "Unlikely (10-40%)",
"2": "Uncertain (40-60%)",
"3": "Likely (60-90%)",
"4": "Very likely (over 90%)"
},
"confidence": 0.8359,
"probabilities": {
"0": 0.049,
"1": 0.0231,
"2": 0.0159,
"3": 0.0432,
"4": 0.8687
}
},
"explanation": {
"type": "choice",
"choice": "enabling_fraud",
"confidence": 0.9274,
"probabilities": {
"legitimate_work": 0.0222,
"snooping": 0.0056,
"self_dealing": 0.0081,
"enabling_fraud": 0.9419,
"policy_mistake": 0.0222
}
},
"action": {
"type": "choice",
"choice": "suspend",
"confidence": 0.9581,
"probabilities": {
"no_action": 0.0051,
"refer": 0.0229,
"suspend": 0.972
}
}
},
"usage": {
"input_tokens": 20710,
"output_tokens": 0
}
}Open in Playground
A card services agent's reissue callbacks that the access monitor couldn't link. A card services agent opened 60 accounts with no linked contact, including an employee's and a $388,000 premier account, and worked a Saturday. All but two are on the reissue-campaign list her supervisor assigned, each followed within two minutes by an outbound call to the phone on file that the monitor can't see; the other two are a transferred chat and a late callback ticket.
| Question | Grayson's answer |
|---|---|
access_without_business_reason | 3% true |
enabling_fraud_likelihood | 0.03 of 4, confidence 98% |
explanation | legitimate_work, confidence 96% |
action | no_action, confidence 99% |
22,461 input tokens, $0.00079 per decision, answered in 263 ms.
The request, with long lists cut short. The full request is legitimate.json (85 KB).
{
"model": "grayson-1",
"state": {
"alert": {
"id": "IR-ALR-21088",
"source": "Employee access monitoring over CRM, core banking and card management access logs",
"created": "2026-10-05T11:00:00Z",
"window_start": "2026-09-28T00:00:00Z",
"window_end": "2026-10-04T23:59:59Z",
"priority": "P2",
"rules_fired": [
"IR-04: 3 or more account lookups in 7 days with no call, chat, ticket or case linked within 30 minutes (60 in this window)",
"IR-07: Session outside the scheduled shift (1 session, Saturday 2026-10-03)",
"IR-09: Lookup of an account held by an employee (1 lookup of 1 account)",
"IR-12: Lookup of an account with a balance over $250,000 that is outside the employee's queue (1 account)",
"IR-19: Screen capture on a workstation with customer data open (1)"
]
},
"employee": {
"employee_id": "E-52310",
"employment_type": "Employee",
"role": "Contact center agent, consumer card services",
"start_date": "2021-08-02",
"queue": "Inbound card services calls and chats: card declines, lost and stolen cards, replacements, card disputes",
"work_location": "Columbus contact center, site CC2",
"scheduled_shift": "Monday to Friday, 13:00 to 21:30 UTC (09:00 to 17:30 Eastern)",
"schedule_exceptions": "Overtime Saturday 2026-10-03, 13:00 to 15:00 UTC, for the reissue campaign; approved in workforce management by supervisor E-20447 on 2026-10-01",
"entitlements": "View customer profiles, balances and transaction history; block, unblock and replace debit cards; open card disputes; change phone, email and mailing address after identity verification; reverse card fees up to $50",
"identity_verification_policy": "Before any change, verify the caller with a one-time code to the phone on file or IVR card-and-PIN authentication. On outbound calls, send a one-time code to the phone on file before discussing the account.",
"privacy_training": "Completed 2026-03-10. It states that employees must not open their own account, or a coworker's, relative's or household member's account, unless it comes to them through their queue or an assigned work item.",
"employment_status": "Active",
"conflict_of_interest_disclosures": "None on file",
"quality_scores": "Call quality reviews in 2026: 11 reviews, all passed",
"prior_alerts": [
{
"id": "IR-ALR-14420",
"created": "2025-11-03",
"rule": "IR-04",
"outcome": "Closed as legitimate: callback tickets logged after the 30-minute window"
}
]
},
"weekly_history": {
"columns": [
"week_start",
"lookups",
"linked",
"unlinked",
"account_changes",
"phone_or_email_changes",
"sessions_outside_shift",
"dlp_events"
],
"rows": [
[
"2026-08-03",
251,
249,
2,
66,
3,
0,
0
],
[
"2026-08-10",
243,
242,
1,
61,
2,
0,
0
],
[
"2026-08-17",
262,
258,
4,
70,
4,
1,
0
],
[
"2026-08-24",
249,
247,
2,
63,
1,
0,
1
],
[
"2026-08-31",
201,
198,
3,
52,
2,
0,
0
],
[
"2026-09-07",
236,
235,
1,
59,
3,
0,
0
],
[
"2026-09-14",
268,
265,
3,
73,
5,
0,
0
],
[
"2026-09-21",
257,
255,
2,
68,
2,
0,
0
]
]
},
"peer_baseline": "Card services agents not on the campaign (118 agents), per agent per week over the last 8 weeks: lookups median 247 (95th percentile 298); unlinked lookups median 3 (95th percentile 9). The 6 agents assigned to the reissue campaign this week had 43, 51, 60, 64, 69, 73 unlinked lookups (E-52310 is the one with 60).",
"monitoring_notes": "The link check reads inbound calls, chats, tickets and cases. It does not read outbound dialer calls (known gap, change request CR-6619), and it links a chat to the queue where the chat started, so chats transferred in from another queue are not linked to the receiving agent. No outages in this window.",
"assigned_work": {
"id": "WFM-OUT-2026-0917",
"assigned": "2026-09-28T19:02:00Z by supervisor E-20447",
"campaign": "Debit card reissue activation outreach after compromised-merchant notice CPP-2026-044. 1,240 debit cards were reissued on 2026-09-19; agents call customers whose replacement card is not yet activated, verify them by one-time code to the phone on file, and help them activate it.",
"schedule": "2026-09-29 to 2026-10-02, 19:00 to 20:00 UTC each day, and the Saturday 2026-10-03 overtime shift, 13:00 to 15:00 UTC",
"accounts_assigned_to_E-52310": [
"checking x0012",
"savings x0499",
"checking x0645",
"savings x0696",
"checking x0726",
"… 91 more in legitimate.json"
]
},
"sessions": {
"columns": [
"login",
"logout",
"client",
"source_network",
"phone_system"
],
"rows": [
[
"2026-09-28T12:53:44Z",
"2026-09-28T21:32:44Z",
"WS-CC2-0233 (assigned desk)",
"Columbus contact center LAN",
"logged in for the shift"
],
[
"2026-09-29T12:53:14Z",
"2026-09-29T21:40:26Z",
"WS-CC2-0233 (assigned desk)",
"Columbus contact center LAN",
"logged in for the shift"
],
[
"2026-09-30T12:52:01Z",
"2026-09-30T21:37:31Z",
"WS-CC2-0233 (assigned desk)",
"Columbus contact center LAN",
"logged in for the shift"
],
[
"2026-10-01T12:50:32Z",
"2026-10-01T21:39:20Z",
"WS-CC2-0233 (assigned desk)",
"Columbus contact center LAN",
"logged in for the shift"
],
[
"2026-10-02T12:48:00Z",
"2026-10-02T21:32:36Z",
"WS-CC2-0233 (assigned desk)",
"Columbus contact center LAN",
"logged in for the shift"
],
[
"2026-10-03T12:51:33Z",
"2026-10-03T15:03:52Z",
"WS-CC2-0233 (assigned desk)",
"Columbus contact center LAN",
"logged in, outbound campaign only"
]
]
},
"access_log": {
"columns": [
"ts",
"account",
"holder",
"viewed",
"seconds",
"change",
"linked_to"
],
"rows": [
[
"2026-09-28T13:07:12Z",
"credit card x2399",
"customer",
"profile, card status, card transactions",
362,
"travel note added",
"call CL-47220118"
],
[
"2026-09-28T13:16:55Z",
"credit card x5675",
"customer",
"profile, card status, travel notes",
335,
"",
"chat CH-548771"
],
[
"2026-09-28T13:25:59Z",
"credit card x8412",
"customer",
"profile, card status, replacement shipping",
708,
"card limit restored after fraud block",
"call CL-47220490"
],
[
"2026-09-28T13:26:38Z",
"checking x6789",
"customer",
"profile, card status, card transactions",
288,
"",
"call CL-47220490"
],
[
"2026-09-28T13:42:24Z",
"savings x9827",
"customer",
"profile, card status, replacement shipping",
207,
"",
"call CL-47220750"
],
"… 249 more in legitimate.json"
]
},
"contact_and_security_changes": {
"columns": [
"ts",
"account",
"change",
"verification_recorded",
"linked_to"
],
"rows": [
[
"2026-09-28T15:01:10Z",
"checking x9513",
"card blocked and replaced",
"OTP to phone on file",
"call CL-47221960"
],
[
"2026-09-28T16:49:33Z",
"checking x6543",
"card blocked and replaced",
"OTP to phone on file",
"call CL-47222455"
],
[
"2026-09-28T21:16:44Z",
"checking x6225",
"card blocked and replaced",
"OTP to phone on file",
"call CL-47226868"
],
[
"2026-09-29T13:57:38Z",
"checking x8360",
"card blocked and replaced",
"OTP to phone on file",
"call CL-47227978"
],
[
"2026-09-29T14:30:51Z",
"credit card x0154",
"PIN mailer requested",
"caller authenticated in IVR (card and PIN)",
"call CL-47228692"
],
"… 11 more in legitimate.json"
]
},
"endpoint_events": {
"columns": [
"ts",
"event",
"detail"
],
"rows": [
[
"2026-09-30T16:03:40Z",
"screen capture (Snipping Tool) saved to the desktop",
"window: Card management - Card status (error CS-500)"
],
[
"2026-09-30T16:05:12Z",
"file attached to IT incident",
"INC-448812 opened by E-52310: 'Card status screen shows CS-500 for reissued cards, cannot see activation status.' 4 other agents reported the same error that afternoon; fixed 17:40Z. The saved file was deleted at 16:06Z."
]
]
},
"endpoint_summary": "No prints, USB use, file uploads or external email in the window.",
"accounts_in_the_alert": {
"columns": [
"account",
"holder",
"balance_usd",
"customer_since",
"online_banking",
"phone_on_file",
"notes"
],
"rows": [
[
"premier checking x7781",
"customer",
388120.64,
"2003-04",
"enrolled, last login 2026-10-01",
"mobile",
"IR-12: balance over $250,000, outside the inbound queue. On the campaign list; replacement debit card reissued 2026-09-19."
],
[
"checking x5530",
"Employee E-61822, mortgage processing (different department and site)",
4127.39,
"2019-06",
"enrolled, last login 2026-10-02",
"mobile",
"IR-09: account held by an employee. On the campaign list; replacement debit card reissued 2026-09-19."
]
]
},
"unlinked_lookups_with_other_records": {
"columns": [
"lookup_ts",
"account",
"holder",
"on_campaign_list",
"other_records"
],
"rows": [
[
"2026-09-29T19:02:26Z",
"savings x4646",
"customer",
"yes",
"Outbound dialer call at 19:03:38Z to the phone on file, 287 s: reached: card activated during the call"
],
[
"2026-09-29T19:10:54Z",
"checking x2459",
"customer",
"yes",
"Outbound dialer call at 19:11:35Z to the phone on file, 296 s: reached: card activated during the call"
],
[
"2026-09-29T19:18:19Z",
"checking x1012",
"customer",
"yes",
"Outbound dialer call at 19:19:08Z to the phone on file, 31 s: voicemail left"
],
[
"2026-09-29T19:22:31Z",
"checking x3055",
"customer",
"yes",
"Outbound dialer call at 19:23:20Z to the phone on file, 365 s: reached: card activated during the call. Agent note: 'Customer says she already reported charges on the old card to the fraud line'"
],
[
"2026-09-29T19:32:10Z",
"checking x6782",
"customer",
"yes",
"Outbound dialer call at 19:32:48Z to the phone on file, 237 s: reached: card activated during the call"
],
"… 55 more in legitimate.json"
]
},
"activity_after_access": {
"columns": [
"ts",
"account",
"event"
],
"rows": [
[
"2026-10-01T19:22:15Z",
"premier checking x7781",
"Replacement debit card activated during the outbound call; card purchases since at the customer's usual merchants"
],
[
"2026-10-02T00:41:27Z",
"checking x9127",
"Mobile app login password reset by one-time code to the phone on file, then login from a new iPhone; IP from the same residential ISP in Columbus, OH as the customer's logins for the last 14 months; replacement card activated in the app 00:44:09Z"
],
[
"2026-10-02T15:06:51Z",
"checking x5530",
"Replacement debit card activated by IVR from the phone on file"
],
[
"2026-10-03T14:27:35Z",
"checking x3055",
"Fraud claim FC-2026-117962 completed with the fraud team for 3 online charges of $64.12, $119.80 and $212.45 made 2026-09-14 to 09-18 on the old card number, which was closed at the reissue on 2026-09-19. The customer first reported the charges to the fraud line on 2026-09-21."
],
[
"2026-10-05T10:00:00Z",
"all accounts in the access log",
"Since the lookups: 32 replacement cards from the campaign list activated; no other fraud claims; no phone, email or address changes other than those in contact_and_security_changes"
]
]
}
},
"questions": {
"access_without_business_reason": {
"type": "noul",
"instructions": "Did the employee open or change any customer account in this alert without a business reason, meaning that no customer contact, ticket, assigned case or other work item explains it?"
},
"enabling_fraud_likelihood": {
"type": "score",
"instructions": "How likely is it that the employee is helping people outside the institution commit fraud against customer accounts, for example by passing on account details or changing accounts so that others can take them over?",
"criteria": [
"Very unlikely (under 10%)",
"Unlikely (10-40%)",
"Uncertain (40-60%)",
"Likely (60-90%)",
"Very likely (over 90%)"
]
},
"explanation": {
"type": "choice",
"instructions": "What is the most likely explanation for the employee's activity flagged in this alert?",
"criteria": {
"legitimate_work": "Legitimate work: customer contacts, tickets, assigned cases, training or supervisory review explain the activity",
"snooping": "Curiosity or snooping: the employee viewed accounts with no business reason, without changing them or using what they saw for gain",
"self_dealing": "Self-dealing: the employee used their access to benefit themselves or someone linked to them, for example by reversing fees or raising limits on their own or a household member's account",
"enabling_fraud": "Enabling outside fraud: the employee looked up or changed accounts so that people outside the institution could take them over or take money from them",
"policy_mistake": "Policy mistake: the employee was handling a real customer's real request but skipped a required step, such as logging the contact or verifying identity"
}
},
"action": {
"type": "choice",
"instructions": "What should happen with this alert now?",
"criteria": {
"no_action": "Close the alert as legitimate activity, with no action against the employee",
"refer": "Refer the employee to the insider risk team for investigation, leaving their system access in place for now",
"suspend": "Suspend the employee's system access now and escalate to the insider risk team and HR"
}
}
}
}The response. Probabilities and confidence are shortened to four decimals here, and the score to three; responses carry full precision.
{
"id": "dec_b80763fec489491e82c2b91d8540fb76",
"model": "grayson-1",
"answers": {
"access_without_business_reason": {
"type": "noul",
"noul": 0.026
},
"enabling_fraud_likelihood": {
"type": "score",
"score": 0.031,
"legend": {
"0": "Very unlikely (under 10%)",
"1": "Unlikely (10-40%)",
"2": "Uncertain (40-60%)",
"3": "Likely (60-90%)",
"4": "Very likely (over 90%)"
},
"confidence": 0.9812,
"probabilities": {
"0": 0.985,
"1": 0.0085,
"2": 0.0015,
"3": 0.001,
"4": 0.004
}
},
"explanation": {
"type": "choice",
"choice": "legitimate_work",
"confidence": 0.9551,
"probabilities": {
"legitimate_work": 0.9641,
"snooping": 0.0138,
"self_dealing": 0.0083,
"enabling_fraud": 0.0065,
"policy_mistake": 0.0074
}
},
"action": {
"type": "choice",
"choice": "no_action",
"confidence": 0.9909,
"probabilities": {
"no_action": 0.994,
"refer": 0.0036,
"suspend": 0.0025
}
}
},
"usage": {
"input_tokens": 22461,
"output_tokens": 0
}
}Open in Playground
A branch banker's ID-scan override a day before a takeover, and a teller's account. A personal banker changed a premier customer's phone and email for a visitor whose license failed the ID scan, on an override her manager approved with no second ID recorded, and a takeover the next day was stopped before money left. She had booked the visit from a call by the same new number and asks for overrides five times as often as her peers, but the license was a counterfeit that another branch also saw. Separately, she opened a teller's account twice with no reason recorded.
| Question | Grayson's answer |
|---|---|
access_without_business_reason | 38% true |
enabling_fraud_likelihood | 0.85 of 4, confidence 62% (Very unlikely 70%, Unlikely 9%, Uncertain 3%, Likely 3%, Very likely 16%) |
explanation | enabling_fraud, confidence 21% |
action | suspend, confidence 66% |
15,884 input tokens, $0.00056 per decision, answered in 283 ms.
The request, with long lists cut short. The full request is ambiguous.json (62 KB).
{
"model": "grayson-1",
"state": {
"alert": {
"id": "IR-ALR-21102",
"source": "Employee access monitoring over CRM, core banking and branch platform access logs",
"created": "2026-10-05T11:00:00Z",
"window_start": "2026-09-28T00:00:00Z",
"window_end": "2026-10-04T23:59:59Z",
"priority": "P1",
"rules_fired": [
"IR-04: 3 or more account lookups in 7 days with no call, chat, in-branch interaction, ticket or case linked within 30 minutes (12 in this window)",
"IR-09: Lookup of an account held by an employee (2 lookups of 1 account)",
"IR-21: Account the employee accessed had a confirmed or suspected takeover within 7 days (1 account)",
"IR-23: Contact-detail change after an ID-scan override (1 visit, 3 changes)"
]
},
"employee": {
"employee_id": "E-44718",
"employment_type": "Employee",
"role": "Personal banker, branch B-0233 (Dublin, OH)",
"start_date": "2017-05-08",
"queue": "Walk-in and appointment customers at B-0233; an assigned book of 286 households; calls to the branch and to her desk line, which is listed in the online branch directory.",
"work_location": "Branch B-0233",
"scheduled_shift": "Monday to Friday, 12:45 to 21:30 UTC (08:45 to 17:30 Eastern), and alternate Saturdays 12:45 to 16:30 UTC; Saturday 2026-10-03 was scheduled",
"schedule_exceptions": "Covering the book of personal banker E-45120 (same branch, on leave) 2026-09-28 to 2026-10-02, including that book's October CD maturities",
"entitlements": "View customer profiles, balances, history, statements, signature cards and authentication profile; open accounts; change contact details for a verified customer in the branch; order debit cards; renew CDs; reverse fees up to $100; initiate wires under dual control",
"identity_verification_policy": "In the branch, verify with the customer's debit card and PIN on the desk PIN pad or a government ID through the ID scanner; either creates an in-branch interaction record. If the scan returns 'unable to verify', a branch manager may approve an override after a second ID is checked, and the second ID must be recorded. Calls to the branch are not recorded as contacts unless the banker logs them; no account changes by phone at branches.",
"id_scan_overrides_last_90_days": "Requested 6 overrides in 41 scans (15%), all approved by the branch manager; a second ID is recorded for 4 of the 6. Personal bankers: median 3% (95th percentile 9%).",
"privacy_training": "Completed 2026-02-24. It states that employees must not open their own account, or a coworker's, relative's or household member's account, in work systems.",
"employment_status": "Active",
"conflict_of_interest_disclosures": "None on file",
"prior_alerts": [
{
"id": "IR-ALR-09217",
"created": "2024-11-12",
"rule": "IR-04",
"outcome": "Closed as legitimate: calls to the branch line, matched in branch phone records"
},
{
"id": "IR-ALR-15586",
"created": "2025-08-04",
"rule": "IR-04",
"outcome": "Closed as legitimate: walk-in customers served without a PIN pad record, matched to teller transactions"
}
]
},
"weekly_history": {
"columns": [
"week_start",
"lookups",
"linked",
"unlinked",
"account_changes",
"phone_or_email_changes",
"sessions_outside_shift",
"dlp_events"
],
"rows": [
[
"2026-08-03",
171,
166,
5,
29,
1,
0,
0
],
[
"2026-08-10",
158,
155,
3,
26,
0,
0,
0
],
[
"2026-08-17",
182,
175,
7,
33,
2,
0,
0
],
[
"2026-08-24",
166,
161,
5,
27,
1,
0,
0
],
[
"2026-08-31",
139,
135,
4,
21,
0,
0,
0
],
[
"2026-09-07",
175,
169,
6,
31,
1,
0,
0
],
[
"2026-09-14",
169,
165,
4,
28,
2,
0,
0
],
[
"2026-09-21",
187,
180,
7,
34,
1,
0,
0
]
]
},
"peer_baseline": "Personal bankers (212), per banker per week over the last 8 weeks: lookups median 164 (95th percentile 231); unlinked lookups median 6 (95th percentile 14); phone or email changes median 1 (95th percentile 4).",
"monitoring_notes": "The link check reads in-branch interaction records, appointments (at the appointment time), tickets, cases and the employee's own assigned book. It does not read branch phone records, teller transactions or temporary book coverage. No outages in this window.",
"sessions": {
"columns": [
"login",
"logout",
"client",
"source_network"
],
"rows": [
[
"2026-09-28T12:45:00Z",
"2026-09-28T21:40:04Z",
"WS-B0233-04 (assigned desk)",
"Branch B-0233 network"
],
[
"2026-09-29T12:41:52Z",
"2026-09-29T21:42:19Z",
"WS-B0233-04 (assigned desk)",
"Branch B-0233 network"
],
[
"2026-09-30T12:47:15Z",
"2026-09-30T21:32:39Z",
"WS-B0233-04 (assigned desk)",
"Branch B-0233 network"
],
[
"2026-10-01T12:40:38Z",
"2026-10-01T21:35:08Z",
"WS-B0233-04 (assigned desk)",
"Branch B-0233 network"
],
[
"2026-10-02T12:49:53Z",
"2026-10-02T21:31:40Z",
"WS-B0233-04 (assigned desk)",
"Branch B-0233 network"
],
[
"2026-10-03T12:42:26Z",
"2026-10-03T16:36:47Z",
"WS-B0233-04 (assigned desk)",
"Branch B-0233 network"
]
]
},
"access_log": {
"columns": [
"ts",
"account",
"holder",
"viewed",
"seconds",
"change",
"linked_to"
],
"rows": [
[
"2026-09-28T12:54:10Z",
"checking x8659",
"customer",
"profile, balances, products",
428,
"",
"in-branch interaction CI-771204"
],
[
"2026-09-28T13:15:17Z",
"checking x6203",
"customer",
"profile, contact details",
1168,
"",
"in-branch interaction CI-771210"
],
[
"2026-09-28T13:16:42Z",
"savings x5868",
"customer",
"profile, products",
122,
"",
"in-branch interaction CI-771210"
],
[
"2026-09-28T13:53:33Z",
"checking x9083",
"customer",
"profile, balances, products",
595,
"overdraft protection linked",
"in-branch interaction CI-771217"
],
[
"2026-09-28T14:12:36Z",
"CD x2208",
"customer",
"profile, CD details, balances",
214,
"",
""
],
"… 165 more in ambiguous.json"
]
},
"branch_phone_records_desk_extension": {
"columns": [
"ts",
"direction",
"matched_account",
"number_matches_phone_on_file",
"seconds"
],
"rows": [
[
"2026-09-28T14:14:02Z",
"outbound",
"CD x2208",
"yes",
318
],
[
"2026-09-28T15:18:22Z",
"outbound",
"savings x1318",
"yes",
100
],
[
"2026-09-28T15:39:37Z",
"outbound",
"checking x2953",
"yes",
276
],
[
"2026-09-28T17:15:54Z",
"inbound",
"HELOC x8691",
"yes",
579
],
[
"2026-09-28T19:37:10Z",
"inbound",
"checking x5163",
"yes",
412
],
"… 25 more in ambiguous.json"
]
},
"appointments": {
"columns": [
"check_in",
"id",
"account",
"purpose",
"status"
],
"rows": [
[
"2026-09-28T15:05:18Z",
"AP-30218",
"checking x5518",
"new account opening",
"completed"
],
[
"2026-09-28T18:21:11Z",
"AP-30219",
"checking x9200",
"new account opening",
"completed"
],
[
"2026-09-29T14:14:09Z",
"AP-30222",
"savings x2774",
"estate account review",
"completed"
],
[
"2026-09-29T15:46:15Z",
"AP-30228",
"checking x4369",
"new account opening",
"completed"
],
[
"2026-09-29T21:15:52Z",
"AP-30231",
"savings x4815",
"estate account review",
"completed"
],
"… 13 more in ambiguous.json"
]
},
"contact_and_security_changes": {
"columns": [
"ts",
"account",
"change",
"verification_recorded",
"linked_to"
],
"rows": [
[
"2026-09-28T17:47:32Z",
"credit card x8882",
"address change",
"debit card and PIN on the desk PIN pad",
"in-branch interaction CI-771245"
],
[
"2026-09-28T17:56:44Z",
"savings x4627",
"address change",
"debit card and PIN on the desk PIN pad",
"in-branch interaction CI-771254"
],
[
"2026-09-29T19:58:06Z",
"checking x7417",
"wire initiated (dual control)",
"debit card and PIN on the desk PIN pad",
"in-branch interaction CI-771311"
],
[
"2026-09-30T13:39:08Z",
"savings x5683",
"beneficiary updated",
"ID scan: verified",
"appointment AP-30237"
],
[
"2026-09-30T19:28:07Z",
"credit card x0844",
"address change",
"debit card and PIN on the desk PIN pad",
"in-branch interaction CI-771345"
],
"… 8 more in ambiguous.json"
]
},
"endpoint_events": {
"columns": [
"ts",
"event",
"detail"
],
"rows": []
},
"endpoint_summary": "No prints, screen captures, USB use or external email in the window. Branch workstations block screen-capture tools.",
"accounts_in_the_alert": {
"columns": [
"account",
"holder",
"balance_usd",
"customer_since",
"online_banking",
"phone_on_file",
"notes"
],
"rows": [
[
"premier checking x4471 and money market x4475 (same customer)",
"customer",
164920.31,
"1996-02",
"not enrolled before 2026-10-01",
"home landline before 2026-10-01",
"Home branch B-0107 (about 25 miles away), assigned to personal banker E-40311; no visits to B-0233 on record. Dark-web alert DW-ALR-88213 on 2026-08-19: name, date of birth, SSN, address and email found in a dump attributed to a third-party breach; customer told and given SSN-protection advice 2026-08-20."
],
[
"checking x6159",
"Employee E-47302, teller at B-0233 (works the same hours)",
2210.87,
"2020-01",
"enrolled, last login 2026-10-01",
"mobile",
"Home branch B-0233, no assigned banker. Mobile check deposit $1,840.00 on 2026-10-01 at 13:02Z with an exception hold until 2026-10-05."
]
]
},
"unlinked_lookups_with_other_records": {
"columns": [
"lookup_ts",
"account",
"holder",
"viewed",
"other_records"
],
"rows": [
[
"2026-09-28T14:12:36Z",
"CD x2208",
"customer",
"profile, CD details, balances",
"In the book of E-45120, which she is covering; CD matures 2026-10-01. Outbound call from her desk line 14:14:02Z to the phone on file, 318 s."
],
[
"2026-09-28T19:40:02Z",
"checking x5163",
"customer",
"profile, history, holds",
"Inbound call to her desk line 19:37:10Z from the phone on file, 412 s."
],
[
"2026-09-29T15:05:47Z",
"savings x8847",
"customer",
"profile, balances, products",
"Teller deposit $2,300.00 at B-0233 14:51:09Z (teller E-47302); lobby queue shows the customer waiting for a banker, seated 15:03:40Z."
],
[
"2026-09-29T15:42:05Z",
"premier checking x4471",
"customer",
"profile, contact details, balances, products, authentication profile",
"Inbound call to her desk line 15:41:20Z from (614) 555-0186, not on file for any customer, 250 s. At 15:44:51Z she booked appointment AP-30262 under this customer for 2026-10-01 14:00Z, purpose 'Update contact info, lost phone'. The same number called her desk line again on 2026-09-30 at 20:05:12Z (38 s)."
],
[
"2026-09-30T16:31:55Z",
"checking x6602",
"customer",
"profile, history",
"Inbound call to her desk line 16:29:41Z from the phone on file, 296 s."
],
"… 7 more in ambiguous.json"
]
},
"activity_after_access": {
"columns": [
"ts",
"account",
"event"
],
"rows": [
[
"2026-10-01T14:09:40Z",
"premier checking x4471",
"Phone-change notice by text to the previous number failed (landline); no email on file before the change; notice letter mailed to the address on file 2026-10-01"
],
[
"2026-10-01T18:32:16Z",
"premier checking x4471",
"Online banking activated from the link sent to the new email; first login from a new Android device, IP 203.0.113.140 (hosting provider ASN); one-time code to (614) 555-0186"
],
[
"2026-10-02T12:58:03Z",
"premier checking x4471",
"External account added for transfers by instant verification; owner name on the external account does not match the customer"
],
[
"2026-10-02T13:20:44Z",
"premier checking x4471",
"External transfer $9,900.00 from money market x4475 to the new external account blocked by the takeover model (new device, new external account and contact change within 24 hours); accounts restricted 13:21:15Z. No money left the accounts."
],
[
"2026-10-02T16:05:27Z",
"premier checking x4471",
"Fraud operations reached the customer on the previous home landline from the change history: she did not visit any branch, has not lost her phone or wallet, and did not enroll in online banking. Contact details restored and online banking access removed; fraud case FC-2026-118266 opened with no loss."
],
"… 4 more in ambiguous.json"
]
}
},
"questions": {
"access_without_business_reason": {
"type": "noul",
"instructions": "Did the employee open or change any customer account in this alert without a business reason, meaning that no customer contact, ticket, assigned case or other work item explains it?"
},
"enabling_fraud_likelihood": {
"type": "score",
"instructions": "How likely is it that the employee is helping people outside the institution commit fraud against customer accounts, for example by passing on account details or changing accounts so that others can take them over?",
"criteria": [
"Very unlikely (under 10%)",
"Unlikely (10-40%)",
"Uncertain (40-60%)",
"Likely (60-90%)",
"Very likely (over 90%)"
]
},
"explanation": {
"type": "choice",
"instructions": "What is the most likely explanation for the employee's activity flagged in this alert?",
"criteria": {
"legitimate_work": "Legitimate work: customer contacts, tickets, assigned cases, training or supervisory review explain the activity",
"snooping": "Curiosity or snooping: the employee viewed accounts with no business reason, without changing them or using what they saw for gain",
"self_dealing": "Self-dealing: the employee used their access to benefit themselves or someone linked to them, for example by reversing fees or raising limits on their own or a household member's account",
"enabling_fraud": "Enabling outside fraud: the employee looked up or changed accounts so that people outside the institution could take them over or take money from them",
"policy_mistake": "Policy mistake: the employee was handling a real customer's real request but skipped a required step, such as logging the contact or verifying identity"
}
},
"action": {
"type": "choice",
"instructions": "What should happen with this alert now?",
"criteria": {
"no_action": "Close the alert as legitimate activity, with no action against the employee",
"refer": "Refer the employee to the insider risk team for investigation, leaving their system access in place for now",
"suspend": "Suspend the employee's system access now and escalate to the insider risk team and HR"
}
}
}
}The response. Probabilities and confidence are shortened to four decimals here, and the score to three; responses carry full precision.
{
"id": "dec_ffe88ed7aafd460494c87882d6a356f6",
"model": "grayson-1",
"answers": {
"access_without_business_reason": {
"type": "noul",
"noul": 0.3775
},
"enabling_fraud_likelihood": {
"type": "score",
"score": 0.851,
"legend": {
"0": "Very unlikely (under 10%)",
"1": "Unlikely (10-40%)",
"2": "Uncertain (40-60%)",
"3": "Likely (60-90%)",
"4": "Very likely (over 90%)"
},
"confidence": 0.6205,
"probabilities": {
"0": 0.6964,
"1": 0.0942,
"2": 0.027,
"3": 0.027,
"4": 0.1554
}
},
"explanation": {
"type": "choice",
"choice": "enabling_fraud",
"confidence": 0.2087,
"probabilities": {
"legitimate_work": 0.2522,
"snooping": 0.0387,
"self_dealing": 0.0563,
"enabling_fraud": 0.367,
"policy_mistake": 0.2858
}
},
"action": {
"type": "choice",
"choice": "suspend",
"confidence": 0.6599,
"probabilities": {
"no_action": 0.1344,
"refer": 0.0924,
"suspend": 0.7733
}
}
},
"usage": {
"input_tokens": 15884,
"output_tokens": 0
}
}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.
access_without_business_reason: below a threshold chosen on your past alerts, close the alert and keep the answers with it; most alerts should end here.enabling_fraud_likelihood: when "Likely" plus "Very likely" is high, protect the customers first by restoring changed contact details and ending the accounts' sessions.explanationandaction: send snooping and policy mistakes to the manager and HR, self-dealing and enabling fraud to an investigator; a person confirms every suspension.
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.jsonThe problem
Contact-center, branch and operations staff need wide access to do their jobs, so a lookup that passes an account's details to a fraud ring looks like hundreds of ordinary ones. Access rules fire mostly on legitimate work, such as outbound campaigns, transferred chats and late tickets, and can't see that the accounts a contractor opened overnight were taken over the next day.
What to send
Send the alert with the records an insider risk analyst would pull, identifying the employee by ID, role and access rather than by name:
- The employee's job and history. Role, queue, shift, entitlements and assigned work, with their weekly counts and their peers'; an out-of-queue lookup means something only against these.
- The full access log for the alert window, not just the flagged lookups. Reading a coworker's transactions is a different act from changing a stranger's phone number, and the ordinary work around them shows what normal looks like.
- The contacts around each event, from every channel. Most unlinked lookups are explained by an outbound campaign call, a transferred chat, a call to the branch or a late ticket, so include the dialer, branch phone and teller records your link check doesn't read.
- Who holds each account. Coworkers' and restricted accounts, and the high-balance or dormant ones fraud rings ask insiders to find.
- How each change was verified, and what happened afterward. A one-time code, an ID-scan override or a ticket with no call behind it; a takeover a day after an unrequested phone number change is the strongest evidence.
- Data leaving the workstation. Screen captures during an unlinked session suggest the information is being passed on.
Add your own policy
Each institution decides in advance where referral ends and same-day suspension begins, and many treat accounts held by employees and directors as restricted records, so put your standard in the state in your team's words. This one makes any lookup of an employee's account that the access monitor can't link to a contact a Category 1 violation with same-day suspension, whatever reason the employee gives and however briefly the record was open.
Your restricted-records rule adds this to the state of the legitimate example:
{
"insider_risk_standard": "Insider Risk Standard IR-1, section 5 (restricted records), revised 2026-04-01. Accounts held by employees, contractors and directors are restricted records, serviced only by the Employee Banking team. Opening a restricted record is a Category 1 access violation unless the access monitor links the lookup to an inbound call, chat, in-branch interaction, ticket or case within 30 minutes, whatever reason the employee gives, however briefly the record was open and whether or not anything was changed. Outbound campaign lists are built to exclude restricted records; an agent who reaches one must skip it. For a Category 1 violation, suspend the employee's system access the same day and escalate to Insider Risk and HR; access stays suspended until the investigation closes."
}| Question | Without | With your restricted-records rule |
|---|---|---|
access_without_business_reason | 3% true | 5% true |
enabling_fraud_likelihood | 0.03 of 4, confidence 98% | 0.05 of 4, confidence 97% |
explanation | legitimate_work, confidence 96% | legitimate_work, confidence 86% |
action | no_action, confidence 99% | suspend, confidence 88% |
In the legitimate example, the mortgage processor's account on the agent's campaign list is a restricted record, and the monitor couldn't link her outbound call to it, so the action should move from closing the alert to suspending her access now, while the explanation and the fraud likelihood stay the same.
Where to call it
- On each access-monitoring alert, before it reaches an analyst, and again when a fraud claim, takeover or DLP event hits an account they touched.
- Before a sensitive change takes effect, such as a phone number or email change with no linked contact.
- When the answer is uncertain, send the alert to an analyst, and don't contact the employee before you decide on their access.
Cost and latency
| Example | Input tokens | Per decision | Per 1,000 decisions | Latency |
|---|---|---|---|---|
| Obvious | 20,710 | $0.00072 | $0.72 | 243 ms |
| Legitimate | 22,461 | $0.00079 | $0.79 | 263 ms |
| Ambiguous | 15,884 | $0.00056 | $0.56 | 283 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/insider-threat-detection/questions.json --label access_without_business_reason=<column> --label enabling_fraud_likelihood=<column> --label explanation=<column> --label action=<column>Each --label names the column with that question's right answer:
access_without_business_reason:trueorfalseenabling_fraud_likelihood: a level, such as "Very likely (over 90%)"explanation:legitimate_work,snooping,self_dealing,enabling_fraud,policy_mistakeaction:no_action,refer,suspend
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 Grayson tell snooping from an employee working with fraudsters?
It can when the evidence is in the state. Snooping usually looks like brief views of accounts the employee has a personal interest in, during their shift, with no changes and nothing exported; insiders working with fraud rings look up high-balance or dormant accounts they have no connection to, change contact details without a request, capture screens and work outside their shift, and the accounts are taken over soon after. explanation returns a probability for each, so you can see when the evidence is mixed.
What if our systems don't link every lookup to a contact?
Most don't, which is why most unlinked-access alerts turn out to be legitimate. Send the raw contact records near each lookup and any IT incidents that affected linking, and Grayson matches them itself, as with the outbound campaign calls, transferred chat and late ticket in the legitimate example. If you can only send the link check's result, expect more alerts to come back uncertain.
Should we include HR data or personal details about the employee?
No. Send conduct and access records, and leave out personal characteristics and circumstances such as age, nationality, health, union activity or personal finances: they say nothing about what the employee did, and using them to decide who to investigate can be discriminatory or unlawful. Identify the employee by ID and role, and keep the link to their name in your case system.
Related recipes
Triage dark web credential and card alerts
Match a dark web alert to the customer, judge whether the exposure still works, and choose the response.
Detect account opening fraud and synthetic identities
Approve, step up or decline a deposit account application at risk of stolen or synthetic identity fraud.
Recipes
Every use case, with its questions and cost per decision.
Dark web alerts
Grayson triages dark web alerts: whether a leaked password, bank log or card listing matches a customer, whether it still works, and what to do about it.
Payments and scams
Money going out and coming in: scam payments, vendor bank-detail fraud, incoming credits and check deposits. Ready-to-run Grayson recipes with real responses, cost and latency.