States
States represent distinct phases of a conversation. Each state contains tasks to complete and defines rules for transitioning to other states.
State Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
id | string | Yes | — | Unique identifier for this state |
title | string | Yes | — | Display name for the state |
type | string | No | "loose" | Execution mode (strict or loose) |
description | string | No | "" | Purpose of this state |
tasks | array | No | [] | Tasks to complete in this state |
transitions | array | No | [] | Rules for moving to other states |
Execution Modes
The type field determines how the agent processes tasks within the state.
STRICT Mode
Sequential task processing — one task at a time, in order.
{
"id": "medical-intake",
"title": "Medical Intake",
"type": "strict",
"tasks": [
{ "id": "symptoms", "description": "Collect symptoms" },
{ "id": "duration", "description": "Collect duration" },
{ "id": "medications", "description": "Collect medications" }
]
}
Characteristics:
- Tasks execute in array order (symptoms → duration → medications)
- Agent completes one task before moving to the next
- User cannot skip ahead
- Ensures all prerequisite information is collected
Best for:
- Medical or legal intake forms
- Step-by-step wizards
- Processes requiring specific order
- Compliance-sensitive workflows
LOOSE Mode
Flexible task processing — agent chooses naturally based on conversation flow.
{
"id": "general-inquiry",
"title": "General Inquiry",
"type": "loose",
"tasks": [
{ "id": "topic", "description": "Understand topic of interest" },
{ "id": "preferences", "description": "Learn user preferences" },
{ "id": "budget", "description": "Determine budget range" }
]
}
Characteristics:
- Agent can address tasks in any order
- Natural conversation flow
- User can provide information proactively
- Agent adapts to user's responses
Best for:
- Customer support conversations
- Sales discovery calls
- General information gathering
- Exploratory conversations
Comparison Table
| Aspect | STRICT | LOOSE |
|---|---|---|
| Task Order | Sequential | Flexible |
| User Control | Limited | High |
| Conversation Feel | Structured | Natural |
| Skip Tasks | Not allowed | Agent decides |
| Use Case | Forms, intake | Discovery, support |
State Transitions
Transitions define when and how to move from one state to another.
Transition Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
target_state_id | string | Yes | — | State to transition to |
condition_type | string | No | "all_tasks_complete" | Type of condition to evaluate |
priority | number | No | 1 | Lower = higher priority |
condition_config | object | No | {} | Additional condition parameters |
Condition Types
The state machine supports the following condition_type values:
| Condition Type | Purpose | Added In |
|---|---|---|
all_tasks_complete | Transition once every task in the current state has been addressed (completed or skipped) | Existing |
deliverable_exists | Transition when a deliverable key has been collected | Existing |
deliverable_value | Transition when a deliverable equals a specific value | Existing |
turn_count_exceeded | Guardrail transition based on turn count | Ticket 5 |
deliverable_value_in | Transition when a deliverable matches one of several values | Ticket 5 |
deliverable_value_numeric | Numeric comparison (gt, gte, lt, lte, eq, neq, between) | Ticket 5 |
all_of | Composite AND over nested child conditions | Ticket 5 |
any_of | Composite OR over nested child conditions | Ticket 5 |
compound | Composite with explicit operator (and or or) | Ticket 5 |
Existing Conditions
all_tasks_complete
Transitions once every task in the current state — required and optional — has been addressed (completed or skipped). A task with deliverables is addressed automatically when its required deliverables are collected (or, for an all-optional task, once every declared deliverable is collected); a deliverable-less task must be completed or skipped explicitly. A newly entered state is never vacuously complete. See Task Completion for the full rules.
{
"target_state_id": "review",
"condition_type": "all_tasks_complete",
"priority": 1
}
deliverable_exists
Transitions when a deliverable key has any collected value.
{
"target_state_id": "has_referral",
"condition_type": "deliverable_exists",
"priority": 1,
"condition_config": {
"key": "referral_code"
}
}
deliverable_value
Transitions when a deliverable equals a specific value.
{
"target_state_id": "premium_support",
"condition_type": "deliverable_value",
"priority": 1,
"condition_config": {
"key": "membership_type",
"value": "premium"
}
}
New Conditions from Ticket 5
turn_count_exceeded
Transitions when turn counters cross a threshold. Use this for fallback routing when users get stuck.
{
"target_state_id": "clarify_or_handoff",
"condition_type": "turn_count_exceeded",
"priority": 5,
"condition_config": {
"turns": 3,
"scope": "without_progress"
}
}
scope: "without_progress"tracks consecutive turns without completing workscope: "total"tracks total turns in the current state
deliverable_value_in
Transitions when a deliverable value is in an allowed set.
{
"target_state_id": "high_priority_queue",
"condition_type": "deliverable_value_in",
"priority": 2,
"condition_config": {
"key": "issue_category",
"values": ["billing_error", "payment_failed", "account_locked"]
}
}
deliverable_value_numeric
Transitions when a numeric deliverable satisfies a comparison rule.
Example 1: threshold check
{
"target_state_id": "urgent_path",
"condition_type": "deliverable_value_numeric",
"priority": 1,
"condition_config": {
"key": "risk_score",
"operator": "gte",
"value": 8
}
}
Example 2: range check
{
"target_state_id": "moderate_path",
"condition_type": "deliverable_value_numeric",
"priority": 2,
"condition_config": {
"key": "risk_score",
"operator": "between",
"min": 4,
"max": 7,
"inclusive": true
}
}
all_of
Transitions only when all child conditions are true.
{
"target_state_id": "eligible_fast_track",
"condition_type": "all_of",
"priority": 1,
"condition_config": {
"conditions": [
{
"condition_type": "deliverable_exists",
"condition_config": { "key": "consent" }
},
{
"condition_type": "deliverable_value",
"condition_config": { "key": "age_verified", "value": true }
}
]
}
}
any_of
Transitions when at least one child condition is true.
{
"target_state_id": "expedited_checkout",
"condition_type": "any_of",
"priority": 1,
"condition_config": {
"conditions": [
{
"condition_type": "deliverable_exists",
"condition_config": { "key": "express_checkout" }
},
{
"condition_type": "deliverable_exists",
"condition_config": { "key": "saved_payment_method" }
}
]
}
}
compound
Composite condition with explicit logical operator.
{
"target_state_id": "ready_to_close",
"condition_type": "compound",
"priority": 1,
"condition_config": {
"operator": "and",
"conditions": [
{
"condition_type": "deliverable_exists",
"condition_config": { "key": "summary_confirmed" }
},
{
"condition_type": "deliverable_value",
"condition_config": { "key": "approval_status", "value": "approved" }
}
]
}
}
UI and JSON Support
The visual Plan Builder currently exposes three condition types in the edge editor:
all_tasks_completedeliverable_existsdeliverable_value
Advanced conditions from Ticket 5 are supported in plan JSON and runtime evaluation. They can be authored directly in JSON today.
Transition Priority
When multiple transition conditions are satisfied, the transition with the lowest priority value wins.
{
"transitions": [
{
"target_state_id": "emergency",
"condition_type": "deliverable_value",
"priority": 1,
"condition_config": {
"key": "urgency",
"value": "emergency"
}
},
{
"target_state_id": "standard-flow",
"condition_type": "all_tasks_complete",
"priority": 10
}
]
}
In this example:
- If
urgencyequals"emergency", go toemergencystate (priority 1) - Otherwise, when all tasks complete, go to
standard-flow(priority 10)
Complete State Example
{
"id": "customer-intake",
"title": "Customer Intake",
"type": "strict",
"description": "Collect essential customer information before routing",
"tasks": [
{
"id": "identify",
"description": "Identify Customer",
"instruction": "Ask for the customer's name and account number",
"required": true,
"deliverables": [
{
"key": "customer_name",
"type": "string",
"required": true
},
{
"key": "account_number",
"type": "string",
"required": true
}
]
},
{
"id": "classify",
"description": "Classify Issue",
"instruction": "Determine the type of issue: billing, technical, or general",
"required": true,
"deliverables": [
{
"key": "issue_type",
"type": "enum",
"enum_values": ["billing", "technical", "general"],
"required": true
}
]
}
],
"transitions": [
{
"target_state_id": "billing-support",
"condition_type": "deliverable_value",
"priority": 1,
"condition_config": {
"key": "issue_type",
"value": "billing"
}
},
{
"target_state_id": "technical-support",
"condition_type": "deliverable_value",
"priority": 1,
"condition_config": {
"key": "issue_type",
"value": "technical"
}
},
{
"target_state_id": "general-support",
"condition_type": "all_tasks_complete",
"priority": 10
}
]
}
State Flow Diagram
A typical conversation flows through multiple states:
┌─────────────┐
│ Greeting │ (loose) - Welcome user, collect name
└──────┬──────┘
│ all_tasks_complete
▼
┌─────────────┐
│ Intake │ (strict) - Collect required information
└──────┬──────┘
│ deliverable_value (based on issue_type)
▼
┌─────────────────────────────────────┐
│ Billing │ Technical │ General │
└────┬─────┴─────┬─────┴──────┬──────┘
│ │ │
└───────────┼────────────┘
│ all_tasks_complete
▼
┌─────────────┐
│ Farewell │ (strict) - Close conversation
└─────────────┘
Next Steps
- Tasks — Learn about task configuration
- Deliverables — Configure data collection
- Examples — See complete plan examples