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.
Auto-generated from
autoplay_sdk/skills/. Edit the source SKILL.md and run python scripts/sync_skill_docs.py..md · Open raw file · Install via CLI: autoplay-install-skills
Autoplay Core
Install
onboard_product:
CONNECTOR_URL— stream URL:https://your-connector.onrender.com/stream/YOUR_PRODUCT_IDAPI_TOKEN— Bearer token (Unkey key)
⚠️ Critical: Session scoping & conversation scoping
This is the most important concept. Get this wrong and context will be empty, mixed between users, or silently dropped.Recommended path — AutoplayChatbotManager
AutoplayChatbotManager handles all session lifecycle automatically. Use it unless you need custom Redis-backed stores or non-standard delivery logic.
- Creating
SessionStatethe moment asession_idis first seen (PostHog is the ground truth) - Buffering actions before a conversation is linked
- Auto-detecting
NEWvsREPLY_EXISTINGfrom the link store - Flushing buffered actions the moment the link is established
- Routing all future delivery to
conversation_idpermanently
session_id comes from PostHog. conversation_id comes from the chatbot platform. They are married together by on_chatbot_event. After that call, all proactive triggers, reactive notes, and future actions route to that conversation for the lifetime of the session.
Low-level building blocks (advanced use)
Use these directly only when you need custom Redis-backed stores or non-standard delivery.SessionState fields:
state.session_id— mandatory required field;SessionState(session_id=...)— construction without it is aTypeErrorstate.metadata— optional extras (user_id,email, any future fields)state.conversation_linked/state.conversation_id— linked chatbot conversationstate.current_state— FSM (THINKING / PROACTIVE / REACTIVE)
InMemorySessionStateStore loses all state on restart. For production, use RedisSessionStateStore — sessions survive restarts and scale across instances. It is a drop-in replacement:
autoplay:session_state:{session_id}. Default TTL: 24 h (configurable via ttl_s). On Redis errors, falls back gracefully and logs a warning — never crashes.
What breaks without correct scoping:
- Wrong user’s events delivered to wrong conversation
- Empty context because retrieval key doesn’t match storage key
- Pre-link actions silently dropped
Fastest SDK-native path (recommended)
If you skipWhen your chatbot gets acompose_chat_pipeline, summaries are never produced. Theon_summary/overwrite_with_summarycallback requires the pipeline’s summarizer to be wired into the stream. There is no implicit fallback — omitting this call meansoverwrite_with_summarynever fires, regardless of thethresholdvalue.
user_id, call:
user_id -> session_id indexing and keeps product_id-aware lookups correct.
Analytics-only recipe (no chatbot)
If you only need to receive enriched events and forward them to your own pipeline — no chatbot, no notes, no session linking — you need none of the chatbot-shaped machinery above. Just the client:BaseChatbotWriter, no compose_chat_pipeline, no session store required.
Optional one-line HTTP bridge
If your chatbot runtime is in another process (Rasa/Botpress/Twilio/custom webhook), prefer the built-in FastAPI factory:GET /healthzGET /context/{user_id}?query=...GET /reply/{user_id}?query=...POST /admin/reset/{user_id}
LLM guardrails
Use versioned prompt metadata with your provider client. The SDK does not currently ship acall_llm(...) helper.
src/llm/ only. Each exports:
Integration Self-Reasoning Checklist
Run through this checklist before considering any chatbot integration complete. Reason through each question — do not skip.1. Session identity
- Is
session_idthe first thing set inSessionState?state = SessionState(session_id=...)—SessionState()withoutsession_idis aTypeError. - Is PostHog the ground truth for
session_id? It must come fromActionsPayload.session_id, never from the chatbot platform. - Is
await session_store.get_or_create(session_id)the very firstawaitin every handler — before any processing, delivery, or API call? - Does
state.metadatacarry all optional identity context (user_id,email, etc.)? Nothing important should live outsideSessionState.
2. Race conditions
- Webhook fires before stream:
get_or_createhandles this — it creates the state withsession_idset. Actions that arrive later from the stream route correctly because the state already exists. - Stream fires before webhook: Actions buffer in
BaseChatbotWriter._pendinguntilon_session_linkedis called. Nothing is dropped. - Concurrent webhooks for the same session:
InMemorySessionStateStore.get_or_createis a synchronous dict operation — race-safe.RedisSessionStateStoredoes a GET-before-SET — acceptable for session context (last writer wins on the rare collision). - Session state missing after restart: If using
InMemorySessionStateStorein production, state is lost. Switch toRedisSessionStateStore.
3. Chatbot linking
- Is
link_conversation(state=state, store=store, conversation_id=conv_id)called with noevent=argument? Let it auto-detectNEWvsREPLY_EXISTINGfrom the store. - Is
await writer.on_session_linked(session_id, conversation_id)called immediately afterlink_conversation? This is the flush trigger — without it, buffered actions are never delivered. - Is the link sticky? Once
state.conversation_linked == True, the same session must not be re-linked to a differentconversation_id. TheREPLY_EXISTINGsemantics handle this automatically — but verify the webhook handler is not callinglink_conversationagain on subsequent replies. - If using
RedisSessionStateStore: isawait session_store.save(state)called after linking?AutoplayChatbotManager.on_chatbot_eventdoes this automatically — verify if using the low-level path.
4. Proactive triggers
- Are proactive triggers reading
state.conversation_idas the delivery target? - Is there a guard:
if not state.conversation_linked: returnbefore calling the chatbot API? A trigger that fires before the conversation is linked has nowhere to deliver. - Does the FSM gate the trigger correctly? Call
state.tick()first, thenallowed, reason = state.can_deliver_proactive(). This is the canonical check — it verifies bothTHINKINGstate and cooldown simultaneously. Do not replicate this logic inline. - After delivering a proactive trigger, is the FSM transitioned?
state.transition_to_proactive(trigger_id)must be called or the session stays in THINKING and the trigger may re-fire. - After any FSM transition (
to_proactive,to_reactive,tick,start_cooldown), isawait manager.save_state(state)called?on_actionsandon_chatbot_eventauto-save — but external FSM mutations require an explicitsave_statecall:
5. Persistence (production)
- On first
session_idarrival,get_or_createcreates and immediately persistsSessionStateto Redis. This is the ground truth — everything else builds on it. on_actionsdoes NOT save state — it only readsstate.conversation_idfor routing and passes actions to the writer.SessionStateis not mutated by action delivery.on_chatbot_eventalways saves after linking —conversation_linkedandconversation_idare the mutations that need persistence there.- For any FSM mutation that happens outside
on_chatbot_event, callawait manager.save_state(state). This covers:to_proactive,to_reactive,tick,start_cooldown,record_user_interaction, and anymetadataupdate. - Is
InMemorySessionStateStorereplaced withRedisSessionStateStorein production? - Is
REDIS_URLset in the production environment? - Is the TTL appropriate? Default is 24 h (
ttl_s=86400). Sessions longer than the TTL will lose state.
Smoke test — verify the full hop before going to production
session_id is empty at this stage, PostHog identify() has not fired yet —
see activity-posthog Step 2.
Reference
- Quickstart: https://developers.autoplay.ai/quickstart
- SDK overview: https://developers.autoplay.ai/sdk/overview
- Chatbot tutorials: https://developers.autoplay.ai/recipes/intercom-tutorial