Writing decisions
A decision answers one question, like "is this loan approved?", from a few facts. You write it as a table of rules. Your apps send the facts and get the answer back.
Parts of a decision
Decisions live in projects. Each has a name, a description and a table with three parts:
- Inputs: the facts the decision needs, such as a credit score or a country.
- Outputs: what it answers, such as approved or rejected, or a discount rate.
- Rules: which outputs to return for which input values.
Start one with New decision. You have three options:
- Describe a policy: the AI drafts the table from your text.
- Start from a template: a ready-made set of rules you adapt.
- Blank decision: an empty table you fill in yourself.
Drafting from a policy
Write the policy the way you would explain it to a colleague, then create the decision. The AI drafts its inputs, outputs and rules in the background, and the decision shows as pending until the draft is ready.
For example:
Approve the loan if the credit score is 700 or higher and the applicant is at least 21. Scores from 650 to 699 go to manual review. Reject everything else.
The AI drafts best from a short, concrete policy that:
- names every fact the decision depends on,
- states each threshold as a number,
- names every possible outcome,
- spells categories the way your systems send them.
Treat the result as a draft. Read the rules, add a few tests, and fix what the AI got wrong before any app uses the decision.
If a draft fails, the decision shows why in its project:
- The policy needs a larger table than can be generated in one go. Split it into smaller policies, for example one per product, region or step, and create a decision for each.
- The generated rules were not valid. Rephrase the policy with concrete values and try again.
If Describe a policy is turned off, the AI can't be reached. See AI is unavailable.
Inputs and outputs
Every input and output has a name, a key and a type.
- The name is the label people read, like "Credit score".
-
The key is what your apps use: the field they send for an input, and the field they read in
the response for an output. Keys use lowercase letters, digits,
-and_, likecredit_score.
Until you first save the decision, a key follows its name. After that, renaming changes only the label. Changing a key is a separate step, and your apps must change with it. See Versions.
Types
The type decides how values are compared and what a valid value looks like.
| Type | Key | Values | Compared as |
|---|---|---|---|
| Text | string | Any text, like gold | Exact text. Case matters: Gold is not gold. |
| Number | number | 700, 2.5, -10 | Numbers |
| True/False | boolean | true or false. Also accepted: 1/0,
t/f, TRUE/FALSE, True/False | True or false |
| Date | date | 2026-10-13 (YYYY-MM-DD) | Text, in order |
| Time | time | 14:30 or 14:30:00 | Text, in order |
| Date Time | datetime | 2026-10-13T14:30 or 2026-10-13T14:30:00 | Text, in order |
Dates and times are compared as text, character by character. That orders correctly only when both sides use the same format. Send dates and times from your apps in exactly the formats above, with no time zone suffix.
Rules
A rule reads as if these conditions hold, then return these outputs. A condition compares one input with a value, like "Credit score is at least 700".
- And: all conditions in a rule must hold for the rule to match.
- Or: a rule can have alternative sets of conditions that share one outcome. SmartDecision saves each alternative as its own rule, next to the others.
- Any value: an input a rule doesn't mention matches any value. In the table this shows as
*. - Otherwise: a last rule with no conditions catches everything the rules above it didn't.
The loan policy above becomes three rules:
| # | credit_score | age | decision |
|---|---|---|---|
| 1 | is at least 700 | is at least 21 | approved |
| 2 | is between 650...699 | * | manual_review |
| 3 | * | * | rejected |
Operators
| Operator | In the editor | Matches when the input | Types |
|---|---|---|---|
eq | is | equals the value | All |
ne | is not | does not equal the value | All |
gt | is above | is greater than the value | Number, date, time, date time |
ge | is at least | is greater than or equal to the value | Number, date, time, date time |
lt | is below | is less than the value | Number, date, time, date time |
le | is at most | is less than or equal to the value | Number, date, time, date time |
in | is between | is inside a range, both ends included | Text, number, date, time, date time |
nin | is not between | is outside a range | Text, number, date, time, date time |
* | any value | has any value | All |
Ranges
Write a range as two values joined by three dots: 650...699, 2026-01-01...2026-03-31,
09:00...17:00. Both ends are included, so 650...699 matches 650 and 699. The start
must not be after the end. Text ranges compare alphabetically.
in and nin test a range, not a list. To match one of several values, like
gold or platinum, use an Or rule with one condition per value.
Rule order
Rules are checked from top to bottom, and the first rule that matches wins. Its outputs are the answer, and the response says which rule it was by its position. Rules below it are not checked.
- Put specific rules above general ones. A broad rule near the top hides the rules under it.
- Keep the Otherwise rule last.
-
If no rule matches, the answer is
No rules matchedand no outputs. An Otherwise rule avoids that.
The editor marks a rule that can never run because a rule above it always matches first, and a value that doesn't fit its input's type.
Tests
A test is a set of input values and the outputs you expect for them. Running it resolves the decision with those inputs and compares the answer with your expectation. Add tests for the cases that matter most, and for each edge of a threshold.
- Run tests one by one or all at once from the decision page.
- While you edit, SmartDecision checks your unsaved changes against the saved tests and shows how many would fail, before you save.
- Tests run against the current version of the decision and don't count as API calls.
- Tests can still be run while the workspace is read-only.
A failing test says why:
- The test has no value for an input. Callers must send every input, so tests must too.
- No rule matched these inputs.
- A rule returned a different value than expected, with the rule's position.
- A rule value can't be compared with the test's inputs, so a real request would get an error.
- A rule refers to an input that no longer exists.
Active and inactive
A decision is active or inactive. Change it in the decision's details. Only active decisions answer Resolve
API requests. An inactive one answers 403 Inactive decision, and so does a decision whose AI draft
is still pending or failed.