Skip to main content

Documentation Index

Fetch the complete documentation index at: https://developers.autoplay.ai/llms.txt

Use this file to discover all available pages before exploring further.

Use autoplay_sdk.agent_state.v2 (SessionState) as the only supported agent-state model.

SessionState v2

Overview

autoplay_sdk.agent_state.v2 provides the supported three-state FSM and enforces a clear timeout-only exit rule from active states. Timeouts and cooldowns are session-level settings rather than per-trigger values.

States

Wire valuePython enumMeaning
thinkingAgentStateV2.THINKINGIdle baseline. Proactive offers may fire — unless the cooldown period is still active.
proactive_assistanceAgentStateV2.PROACTIVEThe assistant surfaced an unsolicited quick-reply offer. User has not yet responded.
reactive_assistanceAgentStateV2.REACTIVEThe user opened the chatbot or sent a message; the session is in active dialogue.

Transition rules

FromToHowNotes
thinkingproactive_assistancetransition_to_proactive(trigger_id)Returns False (no state change) if cooldown_active is still True. Flushes any expired cooldown first.
thinkingreactive_assistancetransition_to_reactive()Always allowed from THINKING. Clears cooldown — user initiating a chat cancels the proactive backoff period.
proactive_assistancethinkingtick() only — automaticThe only exit. Triggered when now − last_interaction_at > interaction_timeout_s. Always starts the cooldown on arrival.
reactive_assistancethinkingtick() only — automaticThe only exit. Same timeout rule as above.
proactive_assistancereactive_assistance❌ NeverRaises InvalidTransitionError.
reactive_assistanceproactive_assistance❌ NeverRaises InvalidTransitionError.
any → proactive_assistance when not THINKING❌ NeverRaises InvalidTransitionError.
any → reactive_assistance when not THINKING❌ NeverRaises InvalidTransitionError.
_timeout_to_thinking() is a private method called exclusively by tick(). Never call it directly in your code — use tick() on every incoming event or background pulse instead.

Session-level timeout settings

FieldDefaultMeaning
interaction_timeout_s20 sHow long the user can go without interacting with the chatbot or visual guidance before returning to thinking. Applies in both proactive and reactive states.
cooldown_period_s60 sAfter returning to thinking from any active state, how long before proactive can fire again. Auto-clears when the period elapses.

Session-owned routing fields

These fields are persisted directly on SessionState and are the canonical delivery routing source:
FieldDefaultMeaning
conversation_linkedFalseWhether this session_id is currently linked to a conversation
conversation_idNoneDerived destination thread id used for hot-path send routing when linked
SessionState.on_conversation_linked(link) transition rules:
  • ConversationEventType.NEW: always set conversation_linked=True and overwrite conversation_id
  • ConversationEventType.REPLY_EXISTING: set link fields only when currently unlinked; keep existing conversation_id when already linked
  • invariant: during a live session, this path never flips conversation_linked back to False

State and flag matrix

StatePurposeKey fields typically read/updatedRouting implication
THINKINGBaseline idle statethinking.cooldown_active, last_interaction_atIf conversation_linked is true, route to conversation_id; otherwise create/link
PROACTIVEAssistant initiated offerproactive.user_clicked_option, last_interaction_at, visual_guidance_activeSame routing rule: state does not change session-owned conversation link
REACTIVEUser-initiated chatreactive.time_since_last_interaction_s, last_interaction_at, visual_guidance_activeSame routing rule: session-owned link remains the send target

Per-state sub-dataclasses

Each state carries a typed sub-object that tracks its own metrics. These are reset when the session enters that state. ThinkingState
FieldTypeMeaning
cooldown_activeboolTrue while the cooldown period is blocking a new proactive offer.
cooldown_started_atfloatMonotonic timestamp of when the cooldown began.
active_cooldown_period_sfloat | NoneTour-specific cooldown override. When set, this period is used instead of the session-level cooldown_period_s. None means use the session default.
can_go_proactivepropertyTrue when cooldown_active is False.
ProactiveState
FieldTypeMeaning
user_clicked_optionboolTrue once the user taps a quick-reply chip.
time_since_last_interaction_sfloatSeconds since the last interaction of any kind — chat message, option click, reaction, or tour step. Updated by tick().
ReactiveState
FieldTypeMeaning
time_since_last_interaction_sfloatSeconds since last user interaction. Updated by tick().

Public exports

from autoplay_sdk.agent_state.v2 import (
    AgentStateV2,
    InvalidTransitionError,
    SessionState,
    ThinkingState,
    ProactiveState,
    ReactiveState,
)
Import InvalidTransitionError from autoplay_sdk.agent_state.v2 with the rest of the v2 symbols.

Key methods

MethodDescription
tick()Evaluate all timeout rules. Call on every incoming event and on a background pulse (e.g. every 5 s) to catch silent timeouts.
can_deliver_proactive()Returns (allowed: bool, reason: str) — the canonical FSM gate check. Call tick() first. Returns (True, "ok") when THINKING with no active cooldown, (False, "v2_state_<state>") when not in THINKING, (False, "v2_cooldown_active") when cooldown is active. Do not replicate this check inline.
transition_to_proactive(trigger_id)Move to PROACTIVE. Returns False if cooldown is active; raises InvalidTransitionError if not in THINKING.
transition_to_reactive()Move to REACTIVE. Raises InvalidTransitionError if not in THINKING. Clears cooldown.
record_any_interaction()Reset last_interaction_at. Call on any chatbot or visual guidance activity.
record_user_interaction()User sent a chat message.
record_option_click()User clicked a quick-reply chip.
record_reaction()User added an emotional reaction.
record_tour_step()Any tour progress (page advance, step complete). Resets the interaction_timeout_s countdown even when the user has never opened the chat — visual guidance counts as interaction.
set_visual_guidance(active)Toggle visual_guidance_active on the current state. Starting a tour (active=True) also resets last_interaction_at. No-op in THINKING.
on_conversation_linked(link)Apply canonical NEW vs REPLY_EXISTING link semantics to conversation_linked / conversation_id.
to_dict() / from_dict(d)Round-trip JSON snapshot for Redis or any store. from_dict raises ValueError on wrong _v.

Persistence

# Save
await save_session(product_id, session_id, session)

# Load
session = await load_session(product_id, session_id)
session.tick()  # flush any elapsed timeouts before acting
Session scope is primary: persist/load by session_id, and treat conversation_id as derived session-owned routing state.

Example

from autoplay_sdk.agent_state.v2 import (
    AgentStateV2,
    InvalidTransitionError,
    SessionState,
)

# Start fresh
session = SessionState(interaction_timeout_s=20.0, cooldown_period_s=60.0)

# Proactive trigger fires
fired = session.transition_to_proactive("trig_001")
assert fired is True
assert session.current_state == AgentStateV2.PROACTIVE

# User clicks a chip
session.record_option_click()

# Background pulse — flush timeouts
session.tick()

# Simulate 25 s of silence → transitions back to thinking with cooldown
session.last_interaction_at -= 25.0
session.tick()
assert session.current_state == AgentStateV2.THINKING
assert session.thinking.cooldown_active is True

# During cooldown, proactive is blocked
assert session.transition_to_proactive("trig_002") is False

# After cooldown expires, proactive is allowed again
session.thinking.cooldown_started_at -= 70.0
session.tick()
assert session.thinking.can_go_proactive is True

# Persist
blob = session.to_dict()
restored = SessionState.from_dict(blob)

See also