Quickstart: your first decision
This walks through modeling a small decision — a loan risk tiering rule —
and simulating it, without deploying anything. It uses the same shape as the
loan-approval example project.
The model
A decision has typed inputs, typed outputs, and a graph of nodes. The
simplest useful node is a decision_table: a set of rules, each row a
condition per input column and a value per output.
{
"id": "loan_risk",
"name": "Loan risk tiering",
"inputs": [
{ "name": "credit_score", "type": { "kind": "integer" }, "required": true },
{ "name": "debt_to_income", "type": { "kind": "number" }, "required": true }
],
"outputs": [{ "name": "risk_tier", "type": { "kind": "string" } }],
"nodes": [
{
"type": "decision_table",
"id": "risk",
"hit_policy": "first",
"inputs": [{ "expr": "credit_score" }, { "expr": "debt_to_income" }],
"outputs": [{ "name": "risk_tier" }],
"rules": [
{ "id": "prime", "when": ["[750..850]", "<= 0.35"], "then": [{ "value": "LOW" }] },
{ "id": "near_prime", "when": [">= 680", "<= 0.45"], "then": [{ "value": "MEDIUM" }] },
{ "id": "subprime", "when": ["-", "-"], "then": [{ "value": "HIGH" }] }
]
},
{
"type": "output",
"id": "out",
"bindings": [{ "output": "risk_tier", "value": { "expr": "risk_tier" } }]
}
]
}
A few things worth noticing:
hit_policy: "first"means the first matching rule wins, evaluated top to bottom.[750..850]is an inclusive range;<= 0.45is a comparator;-is a wildcard that always matches. See Expressions § decision-table cells for the full predicate syntax.- The
outputnode binds the table’s result to the decision’s declared output.
Simulate it
Simulation runs a decision against one set of inputs without storing anything — useful while authoring. Against a saved project artifact:
curl -sS -X POST \
"$RULEFLOW_API/api/projects/lending/decisions/<artifactId>/simulate" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "credit_score": 780, "debt_to_income": 0.2 }'
{ "risk_tier": "LOW" }
Or ad hoc, against a decision that has not been saved yet, via the engine proxy:
curl -sS -X POST "$RULEFLOW_API/api/engine/simulate" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "decision": <the decision JSON above>, "inputs": { "credit_score": 780, "debt_to_income": 0.2 } }'
Both paths run the identical engine — what you see in simulate is exactly
what a deployed workflow’s decision_task produces.
Save it as an artifact
curl -sS -X POST "$RULEFLOW_API/api/projects/lending/decisions" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "name": "loan_risk", "model": <the decision JSON above> }'
{ "id": "art_9f2c...", "tenant": "acme", "project": "lending", "kind": "decision", "name": "loan_risk", "model": { "...": "..." } }
The response is the stored Artifact — id is what you reference from
GET/PUT/DELETE .../decisions/{artifactId} and from a workflow’s
decision_task. Full request/response shapes are in
Projects & artifacts.
Next
Chain this decision into a workflow: Your first workflow.