GenRulesEngine is a lightweight, generic rules-engine library designed to serve as a flexible skeleton for a wide range of rule-based use cases. It provides a consistent set of terminology and components—such as rules, conditions, and actions—to improve clarity and maintainability across different implementations.
Like all rules engines, the goal of GenRulesEngine is to cleanly separate business logic (“rules”) from application code. All rules are evaluated at runtime, and actions are triggered automatically when their conditions are met.
-
Rule
A rule represents a single piece of business logic made up of:- conditions: Boolean expressions that must evaluate to true
- actions: Functions or handlers when all conditions are satisfied
- depends_on: List of dependencies on other rules denoted by its unique, cap-insensitive label
-
Condition
A condition is predicate that tests one or more inputs, evaluating to True or FalseExamples:
userole == "admin"- `token.ttl = 400
order.total > 100 AND customer.age >= 18
-
Action
An action is an operation triggered when a rule's conditions passExamples:
- modifying a value
- appending to a list
- calling a callback
- returning a decision allow/deny
-
Context Data
Context are the runtime data objects passed into the engine during evaluation.Examples:
- a client-server's or server-server's request payload
- triggered transaction event
- a data record meant to be validated
-
Operator
An operator is a reusable comparison function used inside conditionsSupported Operators:
- Equality:
eq, ne - Comparison:
gt, gte, lt, lte - Membership:
in, contains
- Equality:
-
Core Engine
The core runtime engine that:- loads rules
- evaluates each rule’s conditions
- resolves matching rules
- executes corresponding actions
- aggregates results
- returns a list of RuleResult objects
Installation:
-
pip install -
Create an instance of the engine
-
Load rules, GenRulesEngine currently supports JSON documents
Supported JSON Rules Format
{
"rules": [
{
"id": 1,
"label": "Working Adult",
"conditions": {
"all": [
{
"field": "age",
"operator": ">",
"value": 18
},
{
"field": "age",
"operator": "<",
"value": 65
}
],
"any": [
{
"field": "occupation",
"operator": "=",
"value": "engineer"
},
{
"field": "location",
"operator": "=",
"value": "wa"
}
]
},
"actions": [
"approve"
]
},
{
"id": 2,
"label": "Acknowledge Active User",
"conditions": {
"all": [
{
"field": "account.status",
"operator": "=",
"value": "active"
}
],
"any": []
},
"actions": [
"login"
]
}
]
}
- Call engine.run(context), where context is your information to evaluate
Response:
200 OK:
Minimal Response:
{
"allow": true
}
Complex Response:
{
"ruleSet": "discountRules",
"evaluationId": "efb2c0c0-f509-4b16-9d8e-21d5a981be49",
"results": {
"triggeredRules": [
{
"id": "discount_10pct_large_order",
"description": "Apply 10% discount for orders over $100",
"conditionsPassed": true,
"actionResult": {
"discount": 0.10,
"newTotal": 135
}
},
{
"id": "member_bonus_discount",
"description": "Additional 5% off for members",
"conditionsPassed": true,
"actionResult": {
"discount": 0.05,
"newTotal": 128.25
}
}
],
"finalOutput": {
"totalDiscount": 0.15,
"finalAmount": 128.25
}
},
"metadata": {
"ruleCount": 2,
"evaluationTimeMs": 3
}
500 Server Error:
{
"error": {
"code": "RULESET_NOT_FOUND",
"message": "The specified ruleSet 'discountRules' does not exist.",
"details": {
"timestamp": "2025-02-14T12:45:30Z",
"path": "/api/evaluate",
"ruleSet": "discountRules",
"evaluationId": "b18e8805-8d33-4b05-8a72-0980cb2732b7"
}
}
}