Conditions
A condition is a small logic expression on the task contract. It decides when an outcome confirms and when it fails.
Overview
Every task has a condition in its contract. You write it as text, in a small language built for outcomes. When an outcome opens, it snapshots the condition. Each event for that outcome applies to the condition and witn re-evaluates it.
A condition has one of three verdicts at any moment: true, false or unknown. An OPEN outcome becomes CONFIRMED the moment the condition locks true. It becomes FAILED the moment the condition becomes impossible, or when a time window closes without success.
Facts
The building block is a fact. A fact is the action of an event you submit. Written on its own, a fact is true once that event has been seen at least once.
ticket_resolvedFact names can contain letters, numbers, underscores and dots.
payment.capturedBoolean logic
Combine facts with AND, OR and NOT. Use parentheses to group. Keywords are case insensitive.
signed_by_buyer AND signed_by_sellerticket_resolved AND NOT reopenedNOT binds tighter than AND. AND binds tighter than OR. Parentheses override this.
paid AND (shipped OR picked_up)Counting
COUNT(fact) counts every occurrence of an event, then compares it to a number. Use >=, >, <=, < or ==.
COUNT(agent_reply) >= 2Comparisons
A comparison reads the latest properties.value for a fact and compares it to your value. Send the value on the event.
csat >= 4{ "outcome_key": "...", "action": "csat", "properties": { "value": 4.8 } }| Operator | Meaning | Value type |
|---|---|---|
== | equals | string or number |
>= | at least | number |
> | greater than | number |
<= | at most | number |
< | less than | number |
== works for text or numbers. The ordering operators need a number. A comparison is false when no value has been seen yet.
plan == "pro"Sets
IN checks the latest value against a list. It is a shorthand for several == branches joined by OR.
call_outcome IN ["Resolved by Agent", "Partially Resolved by Agent", "Store Visit"]The list holds quoted strings or numbers.
call_duration IN [15000, 30000]Time windows
Two operators reason about time. Both take a window written as (start, end] in durations and a body that holds facts.
G(start, end](body) is true when the body holds for the whole window. One violation fails it. Use it for "nothing bad happened".
G(0,24h](NOT customer_message AND NOT human_escalation)F(start, end](body) is true when the body holds at some point in the window. Use it for "this eventually happened".
F(0,1h](goal_reached)Windows are measured from the moment the outcome opens. A window cannot contain another window.
Durations use s, m, h and d. A bare number is seconds.
| Text | Meaning |
|---|---|
30s | 30 seconds |
5m | 5 minutes |
24h | 24 hours |
7d | 7 days |
Settlement windows
IDLE waits for a quiet gap, then settles the outcome. It is true once the window passes with no reset event. Each reset event pushes the deadline forward, so the outcome settles a fixed time after the last one. This is how you say "judge the outcome once things go quiet".
Three forms control which events reset the clock.
| Form | Resets on |
|---|---|
IDLE(5m) | any event |
IDLE(agent_turn, 5m) | one event |
IDLE([agent_turn, customer_message], 5m) | any event in the set |
Unlike G, a reset event does not fail an IDLE window. It restarts the clock. The longest an IDLE window can wait is 180 days.
Examples
A single event
downloadedBoth parties sign, nobody revokes
signed_by_buyer AND signed_by_seller AND NOT revokedA minimum score
csat >= 4Resolved and quiet for 24 hours
ticket_resolved
AND NOT reopened
AND G(0,24h](NOT customer_message AND NOT human_escalation)A resolved call, settled 5 minutes after the last turn
call_outcome IN ["Resolved by Agent", "Partially Resolved by Agent", "Store Visit"]
AND call_duration >= 15000
AND COUNT(agent_turn) >= 2
AND IDLE(agent_turn, 5m)How evaluation works
On every POST /v1/events, witn validates the request, then queues the event. In the background it applies the event to the outcome and re-evaluates the condition.
- The condition is checked against everything seen so far.
- For comparisons and sets, only the latest value for each fact is used. For counts, every occurrence is counted.
- If the condition locks true and the outcome is
OPEN, it becomesCONFIRMED. - If the condition can never become true again, the outcome becomes
FAILEDright away. This happens when aNOTfact arrives or a count ceiling is passed. A comparison never causes this on its own, because a later event can change the value. G,FandIDLEwindows set a deadline. When the deadline passes, witn evaluates the condition one last time. True confirms the outcome, anything else fails it.
A condition with no window and no lock stays OPEN. Add a window or an IDLE clause when you want the outcome to settle on its own.
Validation
The condition is checked when a task contract is created or updated. Invalid text returns a VALIDATION_ERROR with the position of the problem.
// missing a value
csat >=
// valid
csat >= 4