Documentation Index Fetch the complete documentation index at: https://mintlify.com/Basit-Ali0/Yggdrasil/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Yggdrasil supports 12 core operators for building rule conditions. Each operator handles type coercion automatically for CSV string values.
Supported Operators
Operator Aliases Description Example >=greater_than_or_equal, gteGreater than or equal amount >= 10000>greater_than, gtGreater than amount > 5000<=less_than_or_equal, lteLess than or equal amount <= 1000<less_than, ltLess than amount < 10000==equals, eq, equalEquality (with type coercion) status == "approved"!=not_equals, neq, ne, not_equalInequality type != "CASH_OUT"IN— Set membership type IN ["DEBIT", "WIRE"]BETWEEN— Range check [min, max] amount BETWEEN [8000, 10000]exists— Field is present and non-empty email existsnot_exists— Field is missing or empty dpo_contact not_existscontainsincludesCase-insensitive substring match description contains "crypto"MATCHregexRegular expression test email MATCH "^[a-z]+@"
Operator Normalization
The engine normalizes operator aliases from LLM extraction to standard forms:
// From in-memory-backend.ts:223-244
private normalizeOperator ( op : string ): string {
const normalized = op . trim (). toLowerCase ();
const map : Record < string , string > = {
// Standard
'>=' : '>=' , '>' : '>' , '<=' : '<=' , '<' : '<' ,
'==' : '==' , '!=' : '!=' , 'in' : 'IN' , 'between' : 'BETWEEN' ,
// Gemini aliases
'equals' : '==' , 'equal' : '==' , 'eq' : '==' ,
'not_equals' : '!=' , 'not_equal' : '!=' , 'neq' : '!=' , 'ne' : '!=' ,
'greater_than' : '>' , 'gt' : '>' ,
'greater_than_or_equal' : '>=' , 'gte' : '>=' ,
'less_than' : '<' , 'lt' : '<' ,
'less_than_or_equal' : '<=' , 'lte' : '<=' ,
'exists' : 'EXISTS' , 'not_exists' : 'NOT_EXISTS' ,
'contains' : 'CONTAINS' , 'includes' : 'CONTAINS' ,
'match' : 'MATCH' , 'regex' : 'MATCH' ,
};
return map [ normalized ] || op ;
}
Numeric Comparisons
Operators : >=, >, <=, <
Numeric comparisons use parseFloat() on both sides to handle CSV string values:
// From in-memory-backend.ts:182-189
case '>=' :
return parseFloat ( leftValue ) >= parseFloat ( rightValue );
case '>' :
return parseFloat ( leftValue ) > parseFloat ( rightValue );
case '<=' :
return parseFloat ( leftValue ) <= parseFloat ( rightValue );
case '<' :
return parseFloat ( leftValue ) < parseFloat ( rightValue );
Example
{
"field" : "amount" ,
"operator" : ">=" ,
"value" : 10000
}
Matches records where amount >= 10000.
Equality Operators
Operators : ==, !=
Equality uses type coercion to handle CSV string values:
// From in-memory-backend.ts:59-84
function coerceEquals ( left : any , right : any ) : boolean {
// Same type — direct comparison
if ( typeof left === typeof right ) return left === right ;
// Rule value is boolean, CSV value is string
if ( typeof right === 'boolean' && typeof left === 'string' ) {
return ( left . toLowerCase () === 'true' ) === right ;
}
// Rule value is number, CSV value is string
if ( typeof right === 'number' && typeof left === 'string' ) {
return parseFloat ( left ) === right ;
}
// Rule value is string, CSV value is number/boolean
if ( typeof left === 'boolean' && typeof right === 'string' ) {
return left === ( right . toLowerCase () === 'true' );
}
if ( typeof left === 'number' && typeof right === 'string' ) {
return left === parseFloat ( right );
}
// Fallback: loose equality
return left == right ;
}
Type Coercion Examples
CSV Value Rule Value Match? "true"true✅ "false"false✅ "16"16✅ "10000"10000✅ "approved""approved"✅
Set Membership
Operator : IN
Checks if a value exists in an array:
// From in-memory-backend.ts:198-199
case 'IN' :
return Array . isArray ( rightValue ) && rightValue . includes ( leftValue );
Example
{
"field" : "transaction_type" ,
"operator" : "IN" ,
"value" : [ "DEBIT" , "WIRE" , "TRANSFER" ]
}
Matches records where transaction_type is one of the listed values.
Range Check
Operator : BETWEEN
Checks if a value is within a range (inclusive):
// From in-memory-backend.ts:200-205
case 'BETWEEN' :
return (
Array . isArray ( rightValue ) &&
( leftValue as number ) >= rightValue [ 0 ] &&
( leftValue as number ) <= rightValue [ 1 ]
);
Example
{
"field" : "amount" ,
"operator" : "BETWEEN" ,
"value" : [ 8000 , 10000 ]
}
Matches records where 8000 <= amount <= 10000.
Existence Operators
Operators : exists, not_exists
These operators test for field presence/absence before checking for null:
// From in-memory-backend.ts:162-167
if ( op === 'EXISTS' ) {
return leftValue !== undefined && leftValue !== null && leftValue !== '' ;
}
if ( op === 'NOT_EXISTS' ) {
return leftValue === undefined || leftValue === null || leftValue === '' ;
}
Example: Required Field
{
"field" : "dpo_contact" ,
"operator" : "exists"
}
Matches records where dpo_contact is present and non-empty.
Example: Missing Field
{
"field" : "consent_withdrawn" ,
"operator" : "not_exists"
}
Matches records where consent_withdrawn is missing or empty.
String Matching
Contains
Operator : contains (alias: includes)
Case-insensitive substring match:
// From in-memory-backend.ts:208-210
case 'CONTAINS' :
return typeof leftValue === 'string' && typeof rightValue === 'string' &&
leftValue . toLowerCase (). includes ( rightValue . toLowerCase ());
Example :
{
"field" : "description" ,
"operator" : "contains" ,
"value" : "crypto"
}
Matches “Cryptocurrency transaction”, “CRYPTO PURCHASE”, “crypto-related”.
Regex
Operator : MATCH (alias: regex)
Regular expression test:
// From in-memory-backend.ts:211-215
case 'MATCH' :
if ( typeof leftValue === 'string' && typeof rightValue === 'string' ) {
return new RegExp ( rightValue ). test ( leftValue );
}
return false ;
Example : Email validation
{
"field" : "email" ,
"operator" : "MATCH" ,
"value" : "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+ \\ .[a-zA-Z]{2,}$"
}
Cross-Field Comparison
You can compare two fields using value_type: "field":
// From in-memory-backend.ts:174-178
if ( cond . value_type === 'field' && typeof rightValue === 'string' ) {
rightValue = record [ rightValue ];
if ( rightValue === undefined || rightValue === null ) return false ;
}
Example: Balance Mismatch
{
"AND" : [
{
"field" : "newbalanceOrig" ,
"operator" : "!=" ,
"value" : "expectedBalance" ,
"value_type" : "field"
}
]
}
This compares newbalanceOrig to the expectedBalance field in the same record.
Sanity Checks
The engine includes safety guards to prevent false positives:
// From in-memory-backend.ts:169-172
if ( leftValue === undefined || leftValue === null ) {
return false ;
}
If a field is missing or undefined, the condition does not match (except for exists/not_exists).
Compound Conditions
Operators can be combined with AND/OR logic:
{
"AND" : [
{ "field" : "amount" , "operator" : ">=" , "value" : 8000 },
{ "field" : "amount" , "operator" : "<" , "value" : 10000 },
{ "field" : "type" , "operator" : "IN" , "value" : [ "DEBIT" , "WIRE" ] }
]
}
See Architecture for details on condition evaluation.
Type Coercion Summary
CSV Input Expected Type Coercion "true"booleantrue"false"booleanfalse"123"number123"10000.50"number10000.5"approved"string"approved"
Error Handling
Unknown operators are logged and return false:
// From in-memory-backend.ts:217-219
default :
console . warn ( `[ENGINE] Unknown operator: ' ${ cond . operator } ' in rule condition for field ' ${ cond . field } '` );
return false ;
Next Steps
Rule Types Learn when to use WINDOWED vs SINGLE-TX
Architecture Understand the execution flow