Introduction
airules is a small, typed, declarative rules engine for Python.
You describe the shape of your input as a Fact, write rules as predicates over
that fact, and let the KnowledgeEngine pick the first matching rule and run
its action. Predicates are plain Python objects - they compose with & | ~,
serialize to dictionaries, and reload cleanly - making rule sets easy to store,
audit, and visualize.
Why a rules engine?
Most "if/elif" decision code in production is really a rule set in disguise: a list of conditions, each with an associated action, evaluated in priority order. Once that list grows past a handful of branches it gets hard to read, test, and reason about.
There is a second, practical reason: AI inference is expensive, and programmatic evaluation is not. Every LLM call adds latency and API cost. A rules engine running in-process costs microseconds and zero budget per decision.
The key insight is that most decisions are already known. If you can write down the right answer for a given input pattern, that knowledge belongs in a rule - deterministic, auditable, testable, and free to run. AI earns its cost on the genuinely unknown tail: inputs that fall outside every rule. The rules engine acts as a cheap first-pass filter; only unmatched facts escalate to a model.
Install
pip install ai-rules-engine
Python 3.11+ is required. The only runtime dependency is typing_extensions.
Minimal example
from airules import Fact, KnowledgeEngine, NumberField, Rule, Default
class Order(Fact):
total: NumberField[int]
class Discount(KnowledgeEngine[Order, str]):
@Rule(Order.total.ge(100))
def big(self, order: Order):
return "10% off"
@Default
def small(self, order: Order):
return "no discount"
Discount().run(Order(total=120)) # -> "10% off"
Discount().run(Order(total=20)) # -> "no discount"
The engine is Generic[FactType, ReturnType], so your editor and type checker
know that run returns str | None here.