A gaming platform watches everything a player does. Every deposit. Every withdrawal. Every game round. Every login, logout, and session length. Every KYC document submission and every compliance threshold crossed. The platform has to watch all of this — and for each event, decide: does anything happen next?
That decision layer is called a behavior engine. In PAM, it's called BeAware. And building it correctly is harder than building the wallet, the payment integrations, or the KYC flows — because those systems are bounded. The behavior engine is, by design, unbounded. It has to handle any combination of events, conditions, brands, and jurisdictions that an operator can imagine.
What the rules look like
Here's a representative sample of behavior rules that a live gaming operation might need:
Each rule sounds simple in isolation. The combinations are not. A single player event might match multiple rules simultaneously — a large deposit might trigger both a SOW review and a bonus tier upgrade, each of which has its own action sequence, priority ordering, and failure mode. And every rule has jurisdiction and brand dimensions: the same deposit amount triggers different actions in Sweden than in Ontario.
Why hardcoded rules fail
The first generation of PAM's behavior logic was hardcoded. Not entirely — there were configuration flags — but the core logic was conditional branches in the business layer. When a player deposited above a threshold, the deposit completion code called the bonus evaluation service. When a player completed KYC, the KYC completion handler sent the confirmation email.
Adding a new operator meant a new deployment with a modified rule set. Changing a rule for one jurisdiction risked affecting other jurisdictions. Rules that should fire in sequence were difficult to reason about when they were scattered across different handlers. And operators couldn't change their own rules — every update was a development ticket, a code review, and a deployment. For an operator whose promotional calendar changes weekly, this wasn't sustainable.
BeAware: the configurable rule tree
BeAware was built to solve this. It's a dedicated background service — PAM.Service.Behave — that consumes events from RabbitMQ and evaluates a configurable rule tree against them. The platform publishes events: PlayerRegistered, DepositCompleted, GameRoundCompleted, KycApproved, SelfExclusionRequested, and dozens more. BeAware subscribes to the event stream and, for each event, evaluates every rule that might apply.
The rule tree is data, not code. A rule defines:
- Trigger: which event type activates the rule
- Conditions: filters that must be true (brand, jurisdiction, player segment, threshold values)
- Actions: an ordered sequence of steps to execute (send email, update segment, apply bonus, fire notification, etc.)
- Priority: when multiple rules match the same event, which fires first
- Timing constraints: some actions have delays or cooloff periods
Multiple rules can match a single event. BeAware evaluates all matching rules, respects priority ordering, and executes actions in sequence. Actions within a rule can be conditional on the result of previous actions.
The graph editor
Configuring a rule tree through a JSON editor or a form-based UI gets difficult quickly. Once rules have conditions, branching action sequences, and priority relationships, the structure becomes hard to reason about without a visual representation.
We built a visual rule editor — a node-based graph editor in vanilla JavaScript — that gives operators a drag-and-drop canvas for building rule trees. Each node in the graph represents a trigger, a condition, or an action. Connections between nodes define the flow. Branches represent conditional paths. Priority relationships are represented as ordered connections from a trigger node.
A compliance manager can build and modify a rule without opening a ticket to development. A marketing team can create a campaign-specific bonus trigger by connecting an event node to a condition node to an action sequence — visually, on a canvas, without writing configuration JSON. The graph editor validates the rule structure as it's built, prevents invalid connections, and produces the rule definition that BeAware evaluates at runtime.
The editor was built to be embedded in the PAM back office, running inside the operator's existing authenticated session. The same RBAC model that governs back-office access governs who can view, edit, and publish rules. An operator's compliance team can configure compliance rules. Their marketing team can configure bonus triggers. Neither can see the other's configuration unless explicitly permissioned.
How events flow through BeAware
When a player deposits:
- The deposit completes in the wallet service
- A
DepositCompletedevent is published to RabbitMQ - BeAware receives the event from the queue
- BeAware evaluates every rule with a
DepositCompletedtrigger against the event payload - Rules whose conditions match (brand, jurisdiction, deposit amount, player segment) are queued for execution in priority order
- Actions execute: bonus credit, email send, CRM update, SOW flag, responsible gaming check
- Every action is logged with the rule that triggered it, the event that fired, and the outcome
The entire sequence is async. The deposit completes in milliseconds. The rule evaluation and action execution happen immediately after, in the background, without blocking the player's session.
Cross-brand rules
One of BeAware's more complex capabilities is cross-brand rule evaluation. A player who self-excludes on Brand A under Operator X may need to be excluded from Brand B under the same operator — or from all brands across a jurisdiction, depending on the rule configuration. BeAware handles this through a rule scope that can target a specific brand, all brands under an operator, or all brands in a jurisdiction.
This is where the original templating system had a notable failure: cross-brand player blocks weren't triggering the expected notifications because the trigger type for the cross-brand propagation event was missing from the rule evaluation loop. We traced it, added the missing trigger type, and made the propagation scope a first-class configuration parameter. Adding a new cross-brand rule no longer requires a code change.
BeAware handles dozens of rule types across five jurisdictions and multiple brands, firing in parallel on a continuous event stream. Operators modify their rules through the visual editor without raising development tickets. The rule execution log gives operators and compliance teams a complete audit trail of what fired, when, and why. A decade of edge cases is encoded in the rule engine's evaluation logic — not in individual operator configurations.
The operator ownership question
The most valuable thing BeAware gives operators isn't flexibility — it's ownership. When a compliance rule changes in Sweden, the compliance manager updates it. When a new promotion campaign launches, the marketing team builds the trigger. When a responsible gaming intervention needs tuning, the RG team adjusts it.
A behavior engine that requires development involvement for every rule change isn't a behavior engine — it's a development backlog. The goal was to build a system where the people who understand the rules are the people who configure them. The graph editor is what makes that possible.