relay

State Machine

Each conversation instance follows a defined set of state transitions. States ensure predictable behavior and full observability.

States

StateDescription
CREATEDInstance created, agent has not yet sent first message
ACTIVEAgent is actively processing the conversation
WAITING_FOR_REPLYMessage sent to contact, awaiting their response
WAITING_FOR_AGENTContact replied, awaiting agent processing
HEARTBEAT_SCHEDULEDFollow-up timer is pending
PAUSEDInstance suspended by operator command
QUEUEDWaiting for another instance on the same contact to complete
NEEDS_HUMAN_INTERVENTIONAgent has flagged for human review
COMPLETEDConversation finished successfully
ABANDONEDContact did not respond after max follow-ups
FAILEDUnrecoverable error or manual cancellation

Transitions

Normal Flow

CREATED → ACTIVE → WAITING_FOR_REPLY → WAITING_FOR_AGENT → ACTIVE → ...

The conversation cycles between ACTIVE, WAITING_FOR_REPLY, and WAITING_FOR_AGENT until the agent calls end_conversation().

  • ACTIVE → WAITING_FOR_REPLY — agent sends a message (message_sent)
  • WAITING_FOR_REPLY → WAITING_FOR_AGENT — contact replies (contact_replies)
  • WAITING_FOR_AGENT → ACTIVE — agent finishes processing (agent_processes_reply)
  • WAITING_FOR_AGENT → WAITING_FOR_REPLY — agent sends another message before finishing (message_sent)
  • ACTIVE → WAITING_FOR_AGENT — contact replies while agent is active (contact_replies)

Heartbeat Flow

WAITING_FOR_REPLY → HEARTBEAT_SCHEDULED → WAITING_FOR_REPLY

When a contact does not respond within the configured interval, the heartbeat fires. If max follow-ups are exceeded:

HEARTBEAT_SCHEDULED → ABANDONED

Queuing

Only one active instance per contact. Additional instances enter QUEUED:

QUEUED → CREATED  (when prior instance reaches terminal state)

Pause / Resume

Any non-terminal state can be paused. The previous state is recorded for resumption:

ACTIVE → PAUSED → ACTIVE
WAITING_FOR_REPLY → PAUSED → WAITING_FOR_REPLY

Human Intervention

The agent can flag a conversation for human review:

ACTIVE → NEEDS_HUMAN_INTERVENTION → ACTIVE  (via relay resume or relay send)

Error Handling

Unrecoverable errors transition to FAILED:

ACTIVE → FAILED  (unrecoverable_error)

Cancellation

Any non-terminal state can be cancelled:

(any non-terminal) → FAILED  (reason: "cancelled")

Complete Transition Table

From StateEventTo State
CREATEDagent_sends_first_messageACTIVE
CREATEDcontact_has_active_instanceQUEUED
CREATEDpausePAUSED
CREATEDcancelFAILED
QUEUEDprior_instance_terminalCREATED
QUEUEDpausePAUSED
QUEUEDcancelFAILED
ACTIVEmessage_sentWAITING_FOR_REPLY
ACTIVEcontact_repliesWAITING_FOR_AGENT
ACTIVEend_conversationCOMPLETED
ACTIVErequest_interventionNEEDS_HUMAN_INTERVENTION
ACTIVEunrecoverable_errorFAILED
ACTIVEpausePAUSED
ACTIVEcancelFAILED
WAITING_FOR_REPLYcontact_repliesWAITING_FOR_AGENT
WAITING_FOR_REPLYheartbeat_firesHEARTBEAT_SCHEDULED
WAITING_FOR_REPLYend_conversationCOMPLETED
WAITING_FOR_REPLYpausePAUSED
WAITING_FOR_REPLYcancelFAILED
WAITING_FOR_AGENTmessage_sentWAITING_FOR_REPLY
WAITING_FOR_AGENTagent_processes_replyACTIVE
WAITING_FOR_AGENTend_conversationCOMPLETED
WAITING_FOR_AGENTpausePAUSED
WAITING_FOR_AGENTcancelFAILED
HEARTBEAT_SCHEDULEDfollowup_sentWAITING_FOR_REPLY
HEARTBEAT_SCHEDULEDmax_followups_exceededABANDONED
HEARTBEAT_SCHEDULEDpausePAUSED
HEARTBEAT_SCHEDULEDcancelFAILED
PAUSEDresume(previous state)
PAUSEDcancelFAILED
NEEDS_HUMAN_INTERVENTIONresumeACTIVE
NEEDS_HUMAN_INTERVENTIONmanual_sendACTIVE
NEEDS_HUMAN_INTERVENTIONpausePAUSED
NEEDS_HUMAN_INTERVENTIONcancelFAILED

Terminal States

These states are final. No further transitions are possible:

  • COMPLETED — conversation ended successfully
  • ABANDONED — contact unresponsive after max follow-ups
  • FAILED — error or manual cancellation

On this page