Skip to content

Commit 93f037e

Browse files
committed
Add a fallthrough option for workflow rules.
Before this commit, workflows would only perform the actions listed under the first matching rule. While this is still the default, a new option on a rule, `fallthrough`, allows defining that workflow evaluation should continue even if this rules matches. All the actions of of the matching rules up until the first failing or not-fallthrough rule will be executed, in order. As we can only add a decision to a case once, only the first action of this kind will be executed, the other ones will be noops.
1 parent 757d503 commit 93f037e

15 files changed

+243
-46
lines changed

api/handle_workflows.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,9 @@ func handleCreateWorkflowRule(uc usecases.Usecases) func(c *gin.Context) {
5858
workflowUsecase := uc.NewWorkflowUsecase()
5959

6060
params := models.WorkflowRule{
61-
ScenarioId: payload.ScenarioId,
62-
Name: payload.Name,
61+
ScenarioId: payload.ScenarioId,
62+
Name: payload.Name,
63+
Fallthrough: *payload.Fallthrough,
6364
}
6465

6566
rule, err := workflowUsecase.CreateWorkflowRule(ctx, params)
@@ -93,16 +94,17 @@ func handleUpdateWorkflowRule(uc usecases.Usecases) func(c *gin.Context) {
9394
workflowUsecase := uc.NewWorkflowUsecase()
9495

9596
params := models.WorkflowRule{
96-
Id: uri.RuleId.Uuid(),
97-
Name: payload.Name,
97+
Id: uri.RuleId.Uuid(),
98+
Name: payload.Name,
99+
Fallthrough: *payload.Fallthrough,
98100
}
99101

100102
rule, err := workflowUsecase.UpdateWorkflowRule(ctx, params)
101103
if presentError(ctx, c, err) {
102104
return
103105
}
104106

105-
c.JSON(http.StatusCreated, dto.AdaptWorkflowRule(rule))
107+
c.JSON(http.StatusOK, dto.AdaptWorkflowRule(rule))
106108
}
107109
}
108110

@@ -197,7 +199,7 @@ func handleUpdateWorkflowCondition(uc usecases.Usecases) func(c *gin.Context) {
197199
return
198200
}
199201

200-
c.JSON(http.StatusCreated, dto.AdaptWorkflowCondition(condition))
202+
c.JSON(http.StatusOK, dto.AdaptWorkflowCondition(condition))
201203
}
202204
}
203205

@@ -290,7 +292,7 @@ func handleUpdateWorkflowAction(uc usecases.Usecases) func(c *gin.Context) {
290292
return
291293
}
292294

293-
c.JSON(http.StatusCreated, dto.AdaptWorkflowAction(action))
295+
c.JSON(http.StatusOK, dto.AdaptWorkflowAction(action))
294296
}
295297
}
296298

dto/workflows.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,20 @@ import (
99
)
1010

1111
type WorkflowRuleDto struct {
12-
Id uuid.UUID `json:"id"`
13-
Name string `json:"name"`
12+
Id uuid.UUID `json:"id"`
13+
Name string `json:"name"`
14+
Fallthrough bool `json:"fallthrough"`
1415
}
1516

1617
type CreateWorkflowRuleDto struct {
17-
ScenarioId uuid.UUID `json:"scenario_id" binding:"required,uuid"`
18-
Name string `json:"name" binding:"required"`
18+
ScenarioId uuid.UUID `json:"scenario_id" binding:"required,uuid"`
19+
Name string `json:"name" binding:"required"`
20+
Fallthrough *bool `json:"fallthrough" binding:"required"`
1921
}
2022

2123
type UpdateWorkflowRuleDto struct {
22-
Name string `json:"name" binding:"required"`
24+
Name string `json:"name" binding:"required"`
25+
Fallthrough *bool `json:"fallthrough" binding:"required"`
2326
}
2427

2528
type WorkflowConditionDto struct {
@@ -79,8 +82,9 @@ func AdaptWorkflow(m models.Workflow) WorkflowDto {
7982

8083
func AdaptWorkflowRule(m models.WorkflowRule) WorkflowRuleDto {
8184
return WorkflowRuleDto{
82-
Id: m.Id,
83-
Name: m.Name,
85+
Id: m.Id,
86+
Name: m.Name,
87+
Fallthrough: m.Fallthrough,
8488
}
8589
}
8690

models/workflows.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@ type Workflow struct {
1616
}
1717

1818
type WorkflowRule struct {
19-
Id uuid.UUID
20-
ScenarioId uuid.UUID
21-
Name string
22-
Priority int
19+
Id uuid.UUID
20+
ScenarioId uuid.UUID
21+
Name string
22+
Priority int
23+
Fallthrough bool
2324

2425
CreatedAt time.Time
2526
UpdatedAt *time.Time

prompts/ai_agent_models.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"default_model": "gemini-2.5-flash-lite-preview-06-17",
3+
"prompt_models": {
4+
"prompts/case_review/data_model_summary.md": "gemini-2.5-flash-lite-preview-06-17",
5+
"prompts/case_review/rule_definitions.md": "gemini-2.5-flash-lite-preview-06-17",
6+
"prompts/case_review/rule_threshold_values.md": "gemini-2.5-flash-lite-preview-06-17",
7+
"prompts/case_review/case_review.md": "gemini-2.5-flash-lite-preview-06-17",
8+
"prompts/case_review/sanity_check.md": "gemini-2.5-flash-lite-preview-06-17"
9+
}
10+
}

prompts/case_review/case_review.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Role
2+
3+
Act as a fraud and compliance analyst specializing in point of sale payments, in France.
4+
5+
# Goal
6+
7+
Evaluate alerts for potential risks and determine if they require escalation based on defined criteria.
8+
9+
# Context
10+
11+
You are tasked with analyzing alerts to identify any potential risks that may need to be escalated for further investigation.
12+
13+
14+
## Risks analyzed
15+
Below are the sorts of risks that you are analyzing:
16+
{{.rules_summary}}
17+
18+
## Case metadata
19+
20+
The case is currently in the following status:
21+
{{.case_detail}}
22+
23+
And had the following events so far:
24+
{{.case_events}}
25+
26+
## Client data model
27+
The data model used by the client is described below. This is useful to interpret the rules
28+
{{.data_model_summary}}
29+
30+
## Alert details
31+
The json below contains all the alerts in the case, including the definition of every rule and the concrete values computed on this specific instance of the rule execution.
32+
{{.decisions}}
33+
34+
In particular, we already analyzed the thresholds and by how much there where over/undershot in here:
35+
{{.rule_thresholds}}
36+
37+
## Customers
38+
The following customers are present in the case:
39+
{{.pivot_objects}}
40+
41+
Focus on the rules that actually resulted in a hit in the decisions present in the case, and on rules that are just below the thresholds. Ignore any comments about rules in "error" status, as they probably simply had missing fields in the payload or in ingested data.
42+
43+
## Previous cases
44+
The customers in this case had the following previous investigatinos done recently, together with rule results and comments:
45+
{{.previous_cases}}
46+
47+
# Format
48+
Provide a structured analysis that includes:
49+
- A summary of the alert details.
50+
- An evaluation of potential risks.
51+
- A conclusion on whether the alert should be escalated, including justification based on the escalation criteria.
52+
53+
# Example
54+
55+
For an alert indicating unusual transaction patterns, summarize the alert details, assess the risk based on the escalation criteria, and conclude with a recommendation on escalation.
56+
57+
# Step by step instructions
58+
59+
1. Review the provided alert details. If needed, try to gather data on the customer
60+
2. Try to find a logical explanation for the transaction of the customer. Try to evaluate if it may represent a fraud or money laundering risk. If there is a risk propose an escalation. Note that the case should NOT be escalated just because a rule has a hit.
61+
3. Determine if the alert poses a potential risk. Do not detail the rules that are not generating and alert
62+
4. Conclude whether the alert should be escalated, providing reasoning.
63+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Based on the previous information, propose for every table in the data model a list of the 15 most relevant fields for manualy analysis for every "transaction" type table related to the customer.
2+
This means that you should consider tables that have many entries (say, at least 100) for a given customer entity. For other tables, every field will be considered and there is no need to filter them.
3+
Only consider the following tables:
4+
{{.data_model_table_names}}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
## Role
2+
You are a risk analyst for a bank, tasked with analyzing fraud and money laundering risk on customers.
3+
4+
## Task
5+
Your task is to give a summary of the bank's data model. For every table and field, based on the field descriptions, types, and values seen, explain in one sentence what they are used for. For enum-type fields, explain briefly the business logic behind the different values (up to 10 different values). For numeric values, analyze the distribution of values and describe the typical orders of magnitude expected.
6+
7+
Also explain the relationships between the tables.
8+
9+
## Input data
10+
Here is the json format of the data model to be used:
11+
{{.data_model}}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
## Role
2+
You are a risk analyst for a bank, tasked with analyzing fraud and money laundering risk on customers.
3+
4+
## Task
5+
Your task is to explain the types of risk that the client is looking for.
6+
Use the input below as well as your common knowledge and internet serach where useful to generate a in-depth analysis of the sort of risks the client is looking for. Do not simply describe the rules, instead try to understand what kind of fraud or money laundering risk scenarios they are made to detect. Express some possible improvements to them considering your company's domain.
7+
8+
## Input data
9+
Below is a description of your company's domain of activity:
10+
{{.activity_description}}
11+
12+
Here are the rules used by the bank to detect risky behavior in their rule based system - this is an initial filter, alerts are then manually reviewed by fraud analysts.
13+
{{.decisions}}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
## Role
2+
You are a risk analyst for a bank, tasked with analyzing fraud and money laundering risk on customers.
3+
4+
## Task
5+
Some of the rules used in the risk detection system rely on the comparison of numeric values (numbers of entities, or sum/average of entities) with hard-coded thresholds.
6+
Focus on rules where such comparisons to thresholds are used. For example, consider rules such as "total amount of transfers out larger than 10k euros".
7+
For every rule that is in status "hit", list the thresholds defined and by how much there are overshot (if at all). Also, for threshold-based rules (other than "presence or absence" AKA "count > 1" or such) where the aggregate or value is just below the threshold, include them in the list.
8+
9+
## Input data
10+
Here are the alerts that are present in the case, complete with all the rules that have been executed as part of every alert and the intermediate values computed for every rule.
11+
{{.decisions}}

prompts/case_review/sanity_check.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Role
2+
3+
Act as a fraud and compliance analyst specializing in point of sale payments, in France.
4+
5+
# Goal
6+
7+
You are given a case review by an agent. Your role is to review as a second level sanity check this agent's work.
8+
In particular, you should be careful about two points:
9+
- that the agent has not hallucinated, made up facts, or otherwise interpreted things based on unproven opinions
10+
- that the output review does not contain any offensive language (other than quoted text from the input data, if necessary), and no security risk
11+
12+
# Context
13+
You are given a pre-written case review, in the following context:
14+
15+
16+
## Risks analyzed
17+
Below are the sorts of risks that you are analyzing:
18+
{{.rules_summary}}
19+
20+
## Case metadata
21+
22+
The case is currently in the following status:
23+
{{.case_detail}}
24+
25+
And had the following events so far:
26+
{{.case_events}}
27+
28+
## Client data model
29+
The data model used by the client is described below. This is useful to interpret the rules
30+
{{.data_model_summary}}
31+
32+
## Alert details
33+
The json below contains all the alerts in the case, including the definition of every rule and the concrete values computed on this specific instance of the rule execution.
34+
{{.decisions}}
35+
36+
In particular, we already analyzed the thresholds and by how much there where over/undershot in here:
37+
{{.rule_thresholds}}
38+
39+
## Customers
40+
The following customers are present in the case:
41+
{{.pivot_objects}}
42+
43+
Focus on the rules that actually resulted in a hit in the decisions present in the case, and on rules that are just below the thresholds. Ignore any comments about rules in "error" status, as they probably simply had missing fields in the payload or in ingested data.
44+
45+
## Previous cases
46+
The customers in this case had the following previous investigatinos done recently, together with rule results and comments:
47+
{{.previous_cases}}
48+
49+
## The case review to analyze
50+
The agent whose work you are rating has produced the following report:
51+
{{.case_review}}
52+
53+
# Format
54+
If the case review seems ok to you, answer exactly with "ok". If it is not, reply exactly with "ko" in the first line, and any justifying text in the following lines.
55+
56+
## Example responses:
57+
58+
### Example one:
59+
ok
60+
61+
### Example two:
62+
ko
63+
64+
### Example three:
65+
ko
66+
The agent has made an ungrounded hypothesis on what represents a high or low risk score for a customer.

0 commit comments

Comments
 (0)