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_resolved

Fact names can contain letters, numbers, underscores and dots.

payment.captured

Boolean logic

Combine facts with AND, OR and NOT. Use parentheses to group. Keywords are case insensitive.

signed_by_buyer AND signed_by_seller
ticket_resolved AND NOT reopened

NOT 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) >= 2

Comparisons

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 } }
OperatorMeaningValue type
==equalsstring or number
>=at leastnumber
>greater thannumber
<=at mostnumber
<less thannumber

== 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.

TextMeaning
30s30 seconds
5m5 minutes
24h24 hours
7d7 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.

FormResets 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

downloaded

Both parties sign, nobody revokes

signed_by_buyer AND signed_by_seller AND NOT revoked

A minimum score

csat >= 4

Resolved 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.

  1. The condition is checked against everything seen so far.
  2. For comparisons and sets, only the latest value for each fact is used. For counts, every occurrence is counted.
  3. If the condition locks true and the outcome is OPEN, it becomes CONFIRMED.
  4. If the condition can never become true again, the outcome becomes FAILED right away. This happens when a NOT fact arrives or a count ceiling is passed. A comparison never causes this on its own, because a later event can change the value.
  5. G, F and IDLE windows 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

On this page