Skip to main content
Install the ZEN Engine and evaluate your first decision in Python.

Installation

Basic usage

Loader

Pass a loader option to ZenEngine to serve decisions by key. Use a declarative config for common backends, or a callback for custom ones.

Static

Register decisions in memory. Use this when your rules ship with the application or are already loaded:

File system

Load decisions from files under a root directory. Keys resolve to paths relative to path:

Zip archive

Pass the bytes of a zip archive. Every .json entry becomes a decision keyed by its path within the archive. This pairs naturally with BRMS release ZIPs - download the release from object storage and hand the bytes to the engine:

Custom loader

For any other backend, pass a callback that receives the decision key and returns its content:
The callback can also be an async function - see Async support.

Batch evaluation

Evaluate many requests in one call. Each result reports its own success or failure, so one bad input never fails the batch:

Async support

Use async_evaluate for non-blocking evaluation:

Error handling

Tracing

Enable tracing to inspect decision execution:

Expression utilities

Evaluate ZEN expressions outside of a decision context:
Compile expressions for repeated evaluation:

Spark integration

For distributed processing at scale, see PySpark and AWS Glue.

Best practices

Use ZenDecisionContent for caching. Pre-compiling decisions avoids repeated parsing overhead. Cache compiled content in a dict keyed by decision name. Initialize the engine once. Create a single ZenEngine instance at application startup and reuse it for all evaluations. Implement a loader for dynamic decisions. The loader pattern centralizes decision loading logic and enables caching at the source. Use async evaluation for concurrent workloads. When evaluating multiple decisions, use async_evaluate with asyncio.gather for better throughput.