Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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.45 is a comparator; - is a wildcard that always matches. See Expressions § decision-table cells for the full predicate syntax.
  • The output node 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 Artifactid 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.