Flow Studio
Rule Evaluation Node
The RuleEvalNode — full config, field reference, the executor pattern, and how the outcome drives port-based routing.
Node Configuration
{
"nodeType": "RuleEval",
"name": "checkInvoicePolicy",
"config": {
"ruleSetId": "invoice-approval-policy-v2",
"inputMap": {
"amount": "$output.fetchInvoice.data.total",
"currency": "$output.fetchInvoice.data.currency",
"category": "$output.fetchInvoice.data.category",
"vendorTier": "$output.fetchVendor.data.tier",
"submittedBy": "$context.actorId",
"isFirstTimeVendor": "$output.fetchVendor.data.invoiceCount === 0"
},
"outcomePortMap": {
"approved": "approved",
"rejected": "rejected",
"manual-review": "review"
},
"storeAuditRecord": true
}
}
Configuration Fields
| Field | Type | Description |
|---|---|---|
ruleSetId | string / expr | The rule set to evaluate. Managed in the Rules admin. |
inputMap | object | Maps workflow data to the rule engine fact object. Values are expression-evaluated. |
outcomePortMap | object | Maps rule outcomes to port names. Outcome not in map routes to the main port. |
storeAuditRecord | bool | When true, stores a rule evaluation audit record with facts, outcome, and fired rules. Default: true. |
RuleEvalExecutor
protected override async Task<NodeExecutionResult> ExecuteAsync(
RuleEvalConfig config,
NodeDataContext ctx,
CancellationToken ct)
{
var facts = _evaluator.EvaluateObject(config.InputMap, ctx);
var ruleSetId = _evaluator.Evaluate<string>(config.RuleSetId, ctx);
var result = await _ruleEngine.EvaluateAsync(new RuleEvaluationRequest
{
RuleSetId = ruleSetId,
Facts = facts,
TenantId = ctx.TenantId
}, ct);
if (config.StoreAuditRecord)
await _auditLogger.LogRuleEvaluationAsync(result, ctx, ct);
// Determine output port from outcome map
var portKey = config.OutcomePortMap?.TryGetValue(result.Outcome, out var port) == true
? port
: "main";
return NodeExecutionResult.Success(new
{
result.Outcome,
result.FiredRules,
result.Explanation,
result.Score,
result.EvaluatedAt
}, portKey: portKey);
}