CHANGELOG.md. This page mirrors that file for the documentation site, with links pointed at these docs.
[0.11.0] β 2026-07-02
Changed
onboard_product/onboard_product_syncnow register against the AWS activity connector.DEFAULT_CONNECTOR_URLishttps://connector.autoplay.ai(was the legacy Render connector). ThePOST /productsrequest body now carriesprovider+ optionalingest_secret+force(replacingwebhook_secret/integration_type=event_stream/force_reregister), and the response is read fromcredentials.{ingest_secret, mcp_key}+setup.{ingest_url, ingest_auth, mcp_url, mcp_auth}.OnboardProductResultreshaped to the AWS model:product_id,provider,ingest_url,ingest_secret,ingest_auth,mcp_url,mcp_key,mcp_auth,connector_response.
Added
build_aws_register_payloadandpost_aws_register_productinautoplay_sdk.admin.connector_registration_http.
Removed
- Render/SSE-shaped fields from
OnboardProductResult:webhook_url,stream_url,webhook_secret,unkey_key,unkey_key_id,integration_type,render_sync_performed. onboard_productkeyword argswebhook_secretandforce_reregister(replaced byingest_secretandforce);user_activity_provideris now required.
Breaking changes
onboard_product targets a different connector with a different request/response contract. Existing Render customers are unaffected β they stay on their pinned SDK version and the legacy connector; only new onboarding is routed to AWS. If you call onboard_product, use result.ingest_url + result.ingest_secret to configure your providerβs webhook, and result.mcp_url + result.mcp_key for the agentβs MCP read, instead of the old webhook_url / stream_url / unkey_key. The legacy Render onboarding flow remains available in autoplay_sdk.admin.product_onboarding / autoplay_sdk.admin.onboard for internal Render tooling.
[0.10.0] β 2026-06-21
Added
autoplay_sdk.storageβ a new, self-contained subsystem for cross-session persistence ofUserAdoptionStateplus frozen per-session snapshots, behind a pluggable adapter interface.AutoplayStorageAdapterβ a@runtime_checkable Protocol(mirrorsBufferBackend) with asyncsave_user_state/get_user_state/save_session_snapshot/get_session_snapshot. The wire boundary is plain JSON dicts, so custom adapters stay decoupled from the SDKβs model classes.StorageManagerβ fans writes out to every adapter (one failing sink never blocks the others) and reads from the first adapter that returns a value (list the readable primary first).RedisStorageAdapter(redis_url=...)β primary read+write adapter; owns a lazyredis.asynciopool with graceful degradation (mirrorsRedisSessionStateStore),SET NXwrite-once for snapshots. Needs theredisextra.InMemoryStorageAdapterβ tests/dev adapter with write-once snapshot semantics.- Product-scoped key builders β
user_state_key(product_id, user_id)andsession_key(product_id, user_id, session_id). - Session lifecycle helpers β
init_user_state,on_session_start,on_session_end,build_agent_context.on_session_endresolves the onboarding summary via an injectedsummarizercallable or a pre-computedsummary=β the SDK never calls an LLM.
- Write-only analytics sinks β
AmplitudeStorageAdapter/PostHogStorageAdapter(deep-import fromautoplay_sdk.storage.adapters.{amplitude,posthog}), gated behind a newautoplay-sdk[analytics]extra. Theysave_*(with optionalproperty_prefix=) and returnNonefromget_*; failures are best-effort (logged, never raised). SessionSnapshotβ a new frozen, write-once per-session model withto_dict/from_dict(defensive) and aSessionSnapshot.from_adoption_state(...)helper that builds the snapshot from a liveUserAdoptionState(reusing the modelβs derived helpers β no hand-rolled mapping).SessionIndexEntry+ a bounded sessions index onUserAdoptionStateβsessions_count(monotonic lifetime total),current_session_id, andsessions_index(capped to the most recent 50 viarecord_session), plusset_current_session.OnboardingState.summaryandOnboardingState.completion_rateβ cross-session briefing + cached completion snapshot.ONBOARDING_SUMMARY_PROMPT(v0.1, plain-text output) inautoplay_sdk.promptsand a purebuild_onboarding_summary_input(snapshot)builder inautoplay_sdk.user_adoption_state.- Exports β storage symbols re-exported from top-level
autoplay_sdk;SessionSnapshot,SessionIndexEntry,COMPLETION_RATE_DENOMINATOR_*, andbuild_onboarding_summary_inputfromautoplay_sdk.user_adoption_state. Sink adapters stay deep-import only. autoplay_sdk.observabilityβ a pluggable error-reporter seam (set_error_reporter/report_error) so a host application can forward SDK-internal failures to its own sink (Slack, Bugsnag, logs, β¦). The SDK callsreport_errorat its swallow points β RAG embed/upsert, Redis state/snapshot writes, and event-buffer overflow drops β so those otherwise-silent failures become observable. Best-effort and a no-op until a reporter is registered; reporting never raises into SDK logic.
Documentation
- New page State storage & session capture covering the three-step integration flow, the adapter/manager model, Redis key schema, write-only sinks, and the injected-summarizer pattern.
- User adoption state persistence note updated to point at the new storage adapters.
Breaking changes
None β purely additive. The newUserAdoptionState fields (sessions, onboarding.summary, onboarding.completion_rate) read with safe defaults, so existing snapshots load unchanged and the _v snapshot version is unchanged.
[0.9.2] β 2026-06-21
Added
- Onboarding workflow steps β each
OnboardingWorkflowcan now declare an ordered list of **WorkflowStep**s (step_id,name,description,required), configured per product underintegration_config.onboarding_workflows[].steps. Steps are context/signal for the LLM (what βdoneβ looks like) and for explainability β they are not a checklist gate.requiredis a hint, not a hard gate. HelperOnboardingWorkflow.required_step_ids. StepProgressβ the agentβs per-step belief (step_id,statusreusingWorkflowStatus,confidence,evidence,completed_at,last_evaluated_at), a deliberate parallel toWorkflowProgressone level down.WorkflowProgress.stepsβ adict[str, StepProgress]map of per-step beliefs, with acompleted_step_idshelper and anupsert_step_progress(step_id, *, status, confidence, evidence="", now=None)mutation (write-oncecompleted_at, mirroringupsert_workflow_progress).is_plan_complete(plan, workflow_progress)β thin convenience wrapper oversplit_workflows(Truewhen no outstanding workflows; an empty plan is never complete). Completion stays the LLMβs call viaWorkflowProgress.statusβ steps never gate it.step_completion_ratio(workflow, wp)β fraction of a workflowβs declared steps the LLM believes arecompleted. For display/telemetry only; never used to decide completion.- Exports β
WorkflowStep,StepProgress,is_plan_complete,step_completion_ratioadded toautoplay_sdk.user_adoption_state.
Documentation
- User adoption state updated with the steps data model, the product-config
stepsschema, and the completion semantics (LLM-authoritative; steps are signal, not a gate).
Breaking changes
None β purely additive.steps is read with safe defaults, so existing snapshots (no steps key) load unchanged and the _v snapshot version is unchanged.
[0.9.1] β 2026-06-16
Added
- Amplitude activity provider support β adds the SDK provider wiring and activity skill needed to configure Amplitude as an event source.
Documentation
- Expanded the setup and quickstart docs for activity providers, agent skills, MCP server setup, and Intercom tutorial assets.
[0.9.0] β 2026-06-12
Added
PostHogProvider.create_destination()+.verify()β deterministic, idempotent creation (and verification) of the PostHog β Autoplay βAutoplay Event Streamβ hog_function destination, built on the provider abstraction. Powers the one-commandautoplay-setuponboarding flow (plumbing runs as tested code, not via an agent).
Changed
activity-posthogskill is now the single source (modular:SKILL.md+references/+examples/), replacing the forkedposthog-setupskill the setup bundle used to ship. Scoped to frontend code only (the CLI now owns destination create/verify and the end-to-end event check). Identify uses the appβs stable user id on login (never the anonymous id) +reset()on logout.
[0.8.0] β 2026-06-09
Added
autoplay_sdk.user_adoption_stateβ a new per-user adoption-state module, orthogonal to the per-sessionSessionStateFSM and keyed byuser_id. Tracks where a user is in their product lifecycle and how proficient they are, decided by an LLM judge and fed back into chat / proactive prompts.- Enums β
JourneyState(onboarding/onboarded),MasteryLevel(noviceβbeginnerβintermediateβproficientβpower_user), andWorkflowStatus(not_started/in_progress/completed). UserAdoptionStateβ top-level per-user record: a fully dynamic, schema-lessmetadatabag (with aroleconvenience property),journey_state,mastery,discovered_features, and anonboardingsub-object. Mandatory non-emptyuser_id(raises otherwise, likeSessionState);to_dict()/from_dict()with_vsnapshot versioning and defensive enum coercion; transition helpers (set_journey_state,set_mastery,record_discovered_features,mark_welcomed,mark_judged) that log structured events; andto_prompt_block()for compact prompt injection.Mastery(0-10 rating, clamped, +MasteryLevel+ reason),WorkflowProgress(per-flowstatus/confidence/evidence/ timestamps β the agentβs evolving belief from the live activity stream),StepInAssessment(latest βshould I step in?β decision + timing rationale), andOnboardingState(welcome lifecycle,workflow_progressmap, derivedcompleted/in_progress/outstandinghelpers,upsert_workflow_progress,record_step_in).ExplorationGateConfig+evaluate_hard_gate()β pure, side-effect-free βlet the user explore firstβ floor (role allowlist, min time on app, min distinct features, welcome cooldown, nudge cap). Returns(passed, reason); the LLM owns timing on top of the floor.OnboardingWorkflow/OnboardingPlan(parsed from config, role-filterable viafor_role) + puresplit_workflows()β(completed, in_progress, outstanding).- Query β tour matching primitive β
build_tour_match_input()andparse_tour_match_output()(validates ids against a role-filtered catalog, safe fallback on malformed JSON), plusTourCatalogEntryandTourMatchResult. - Versioned prompts in
autoplay_sdk.prompts(each adictwithname/description/version/content, JSON-object output):ADOPTION_STATE_JUDGE_PROMPT,TOUR_MATCH_PROMPT,ONBOARDING_WELCOME_PROMPT(all v0.1). - Top-level exports from
autoplay_sdk:user_adoption_state,UserAdoptionState,JourneyState,MasteryLevel,WorkflowStatus.
Documentation
- New User adoption state reference page covering the two axes (journey vs mastery), the full state model, the explore-first gate, onboarding plans, and the query β tour matcher. The SDK ships pure logic + prompt definitions only; persistence and
acall_llmrunners are integration-owned.
Breaking changes
None β the module and exports are purely additive.[0.7.9] β 2026-05-25
Breaking changes
SessionState.session_idis now a required field β no default.SessionState()raisesTypeError. UseSessionState(session_id="...")orInMemorySessionStateStore.get_or_create(session_id).from_dict()still handles old snapshots gracefully via.get("session_id", "").
Added
SessionState.can_deliver_proactive() -> tuple[bool, str]β canonical FSM gate check. Returns(True, "ok")when the session is THINKING with no active cooldown;(False, reason)otherwise. Callers must calltick()before this method. Replaces any inlinecurrent_state == THINKING and not thinking.cooldown_activepattern.SessionStatenow holdssession_id: str(the only mandatory scope key) andmetadata: dict[str, Any](open bag for optional identity context βuser_id,email, any future fields). Both fields are persisted viato_dict()/from_dict()and default to empty for backward compatibility.RedisSessionStateStoreβ Redis-backedSessionStatestore for production use. Key patternautoplay:session_state:{session_id}, configurable TTL (default 24 h), graceful fallback on Redis errors. Requirespip install "autoplay-sdk[redis]".AutoplayChatbotManagerβ high-level wrapper that handles all session lifecycle automatically. Developers implement only_post_noteand call two methods:on_actions(payload)from the Autoplay stream andon_chatbot_event(session_id, conversation_id)from the chatbot webhook.AutoplayChatbotManager(session_store=...)β optional parameter to inject a custom store. Defaults toInMemorySessionStateStore(). PassRedisSessionStateStore(redis_url=...)for production.AutoplayChatbotManager.save_state(state)β public method for persisting state after external FSM transitions (transition_to_proactive,transition_to_reactive,tick,start_cooldown, interaction recorders).on_actionsandon_chatbot_eventcall this automatically; usesave_stateonly for mutations that happen outside those entry points.InMemorySessionStateStoreβ canonical store forSessionStateobjects.get_or_create(session_id)is the first call in every handler.asyncinterface for drop-in Redis-backed replacement.BaseChatbotWriter.__init_subclass__enforcement β raisesTypeErrorat class-definition time (module import) when a subclass setsSESSION_LINK_WEBHOOK_TOPICSwithout overriding_parse_session_link_webhook_payload. Converts a silent production crash into a startup error caught by tests and local runs. Subclasses that leaveSESSION_LINK_WEBHOOK_TOPICS = ()are unaffected.link_conversationnow auto-detectsConversationEventType.NEWvsREPLY_EXISTINGfrom the store wheneventis not passed β removes the last manual determination from integration authors.link_conversationnow inferssession_idfromstate.session_idwhen not passed explicitly. Existing callers that passsession_idare unaffected.link_conversationraisesValueErrorifsession_idis empty after resolution, with a clear message pointing toInMemorySessionStateStore.get_or_create.AutoplayChatbotManagerandInMemorySessionStateStoreexported from top-levelautoplay_sdk.AutoplayChatbotManager.on_chatbot_eventnow persists the updatedSessionStateback toRedisSessionStateStoreafter linking so the conversation link survives restarts.redisoptional extra added topyproject.toml:pip install "autoplay-sdk[redis]".
Changed
ConversationEventrenamed toConversationEventTypeβ the old name was misleading because it read as a data container rather than a type discriminator. A deprecated backward-compat aliasConversationEvent = ConversationEventTypeis exported from bothautoplay_sdkandautoplay_sdk.chat; it will be removed in the next major version. Update any import ofConversationEventtoConversationEventType.proactive_fsm_gate_for_sessiondelivery invariant clarified β no linked conversation β first proactive β always allowed (a new conversation will be created and linked). A linked conversation β check FSM viacan_deliver_proactive(). Thefallback_conversation_idparameter has been removed.- Polling gates use
session.can_deliver_proactive()directly β polling paths (context_payload.py,routes.py) load and tick the session for the knownconversation_id, then callcan_deliver_proactive()on the already-loaded session. They no longer go throughproactive_fsm_gate_for_session(which has delivery-specific semantics). AutoplayChatbotManager.on_chatbot_eventremoves theisinstance(store, RedisSessionStateStore)guard βsaveis always called regardless of which store is wired.on_actionsdoes not save (no state mutation occurs during action delivery; first-creation is already persisted byget_or_create).InMemorySessionStateStoregains a no-opsave(state)method so all call sites are uniform.
Documentation
- BaseChatbotWriter: rewritten to lead with
AutoplayChatbotManageras the recommended path, updated session-first linking section to showInMemorySessionStateStore+get_or_createpattern, added Production persistence section withRedisSessionStateStoreone-line swap. autoplay-coreskill: added Integration Self-Reasoning Checklist β 5 categories agents must reason through before an integration is complete: session identity, race conditions, chatbot linking, proactive triggers, and production persistence. Section 4 updated to usecan_deliver_proactive()as the canonical gate check and fixes a stale method reference (to_proactiveβtransition_to_proactive). Added Universal Scoping Pattern β the canonical 4-step flow (scope β parse webhook β link β deliver) that applies identically to every chatbot integration.SessionStateclass docstring now listsconversation_linkedandconversation_idin its Fields section.- Agent session states Key Methods table now includes
can_deliver_proactive();ThinkingStatetable now includesactive_cooldown_period_s.
[0.7.8] β 2026-05-21
Changed
- Bumped package version to
0.7.8.
[0.7.7] β 2026-05-21
Changed
- Bumped package version to
0.7.7. - Fixed circular import between
autoplay_sdk.integrations.intercomandautoplay_sdk.proactive.triggersby movingproactive_trigger_canonical_url_ping_pongandproactive_trigger_canonical_url_ping_pong_projects_either_legintoautoplay_sdk.proactive.triggers._url_predicates.intercom.pyre-exports both for backward compatibility.
[0.7.6] β 2026-05-18
Fixed
autoplay_sdk/skills/autoplay-migrate-imports/SKILL.mdβ tightened the discoveryrgfilter to require a word boundary ((\.|\s)) after the canonical-domain alternation group. Without it, deprecated sub-modules whose names start with a canonical prefix (context_store,proactive_triggers,agent_state_v2,rag_query) were silently excluded from results, leaving 4 of 6 legacy imports unflagged.
Changed
autoplay_sdk/skills/autoplay-migrate-imports/SKILL.mdβ inlined the full legacyβcanonical path mapping table directly in the skill file. The previous wording (βsee the changelog mapping tableβ) referenced a doc that does not ship inside the wheel, so agents had no static replacement guidance and had to rely on runtimeDeprecationWarningmessages to discover new paths.
Documentation
- Updated BaseChatbotWriter with a new session-first linking section covering:
ConversationEventType.NEWvsConversationEventType.REPLY_EXISTING- canonical dual-write flow via
link_conversation(...)(ConversationLinkStorewrite, thenSessionState.on_conversation_linked(...)) - hot-path routing with
resolve_linked_conversation_id(state)from session-owned state.
- Expanded Agent session states v2 docs with:
- explicit
SessionStatelink fields (conversation_linked,conversation_id) on_conversation_linked(link)overwrite/no-op semantics and invariants- a state/flag matrix for
THINKING,PROACTIVE, andREACTIVE.
- explicit
- Added cross-SDK data-structure mapping in Typed payloads and Payload schema, clarifying boundaries between session state, link state, webhook parse models, and stream payloads.
[0.7.5] β 2026-05-17
Changed
- Bumped package version to
0.7.5. - Expanded the
testoptional dependency extra to include async/runtime test dependencies (pytest-asyncio,fakeredis,respx) sopip install -e ".[serve,test]"is enough for SDK CI and local test runs. - Enabled
asyncio_mode = "auto"in pytest config so async tests are discovered consistently without requiring explicit per-test markers.
[0.7.4] β 2026-05-16
Summary
Domain-oriented internal reorganization with one-release compatibility shims. Old import paths still work in0.7.4 and emit DeprecationWarning; they are removed in 1.0.0.
Added
autoplay_sdk.compatshim registry and helper.tests/compat/test_import_compat.pyimport parity tests.- CI workflow for import compatibility across Python 3.10/3.11/3.12.
- Migration skill:
autoplay-migrate-imports.
Changed
- Canonical import domains now use
core,chat,context,proactive,agent_state,api,rag. autoplay-install-skillsnow supports--migrate.
Deprecated paths (remove in 1.0.0)
autoplay_sdk.rag remains a stable alias in 0.7.4 (no deprecation warning).
| Old | New |
|---|---|
autoplay_sdk.serve | autoplay_sdk.api |
autoplay_sdk.serve.fastapi | autoplay_sdk.api.fastapi |
autoplay_sdk.agent_states | autoplay_sdk.agent_state.v1.states |
autoplay_sdk.agent_states.state_machine | autoplay_sdk.agent_state.v1.state_machine |
autoplay_sdk.agent_states.types | autoplay_sdk.agent_state.v1.types |
autoplay_sdk.agent_states.proactive_idle_expiry | autoplay_sdk.proactive.state.idle_expiry |
autoplay_sdk.agent_state_v2 | autoplay_sdk.agent_state.v2.states |
autoplay_sdk.agent_state_v2.session_state | autoplay_sdk.agent_state.v2.session_state |
autoplay_sdk.agent_state_v2.types | autoplay_sdk.agent_state.v2.types |
autoplay_sdk.rag_query | autoplay_sdk.rag.query |
autoplay_sdk.rag_query.assembly | autoplay_sdk.rag.query.assembly |
autoplay_sdk.rag_query.formatters | autoplay_sdk.rag.query.formatters |
autoplay_sdk.rag_query.pipeline | autoplay_sdk.rag.query.pipeline |
autoplay_sdk.rag_query.watermark | autoplay_sdk.rag.query.watermark |
autoplay_sdk.proactive_resilience | autoplay_sdk.proactive.resilience.resilience |
autoplay_sdk.proactive_resilience.circuit | autoplay_sdk.proactive.resilience.circuit |
autoplay_sdk.proactive_resilience.config | autoplay_sdk.proactive.resilience.config |
autoplay_sdk.proactive_resilience.keys | autoplay_sdk.proactive.resilience.keys |
autoplay_sdk.proactive_resilience.outcomes | autoplay_sdk.proactive.resilience.outcomes |
autoplay_sdk.proactive_resilience.protocol | autoplay_sdk.proactive.resilience.protocol |
autoplay_sdk.chatbot | autoplay_sdk.chat.chatbot |
autoplay_sdk.chat_pipeline | autoplay_sdk.chat.chat_pipeline |
autoplay_sdk.context_store | autoplay_sdk.context.context_store |
autoplay_sdk.agent_context | autoplay_sdk.context.agent_context |
autoplay_sdk.user_index | autoplay_sdk.context.user_index |
autoplay_sdk.summarizer | autoplay_sdk.context.summarizer |
autoplay_sdk.models | autoplay_sdk.core.models |
autoplay_sdk.exceptions | autoplay_sdk.core.exceptions |
autoplay_sdk.metrics | autoplay_sdk.core.metrics |
autoplay_sdk.onboarding | autoplay_sdk.admin.onboarding |
autoplay_sdk.proactive_idle_expiry | autoplay_sdk.proactive.state.idle_expiry |
autoplay_sdk.proactive_triggers | autoplay_sdk.proactive.triggers |
autoplay_sdk.proactive_triggers.builtin_catalog | autoplay_sdk.proactive.triggers.builtin_catalog |
autoplay_sdk.proactive_triggers.context_source | autoplay_sdk.proactive.triggers.context_source |
autoplay_sdk.proactive_triggers.defaults | autoplay_sdk.proactive.triggers.defaults |
autoplay_sdk.proactive_triggers.entity | autoplay_sdk.proactive.triggers.entity |
autoplay_sdk.proactive_triggers.judge | autoplay_sdk.proactive.triggers.judge |
autoplay_sdk.proactive_triggers.pending_tour_offer | autoplay_sdk.proactive.triggers.pending_tour_offer |
autoplay_sdk.proactive_triggers.predicate_trigger | autoplay_sdk.proactive.triggers.predicate_trigger |
autoplay_sdk.proactive_triggers.proactive_intercom_config | autoplay_sdk.proactive.triggers.proactive_intercom_config |
autoplay_sdk.proactive_triggers.quick_reply_match | autoplay_sdk.proactive.triggers.quick_reply_match |
autoplay_sdk.proactive_triggers.registry | autoplay_sdk.proactive.triggers.registry |
autoplay_sdk.proactive_triggers.scope | autoplay_sdk.proactive.triggers.scope |
autoplay_sdk.proactive_triggers.section_activity | autoplay_sdk.proactive.triggers.section_activity |
autoplay_sdk.proactive_triggers.tour_registry | autoplay_sdk.proactive.triggers.tour_registry |
autoplay_sdk.proactive_triggers.trigger_config | autoplay_sdk.proactive.triggers.trigger_config |
autoplay_sdk.proactive_triggers.triggers | autoplay_sdk.proactive.triggers.triggers |
autoplay_sdk.proactive_triggers.triggers.canonical_ping_pong | autoplay_sdk.proactive.triggers.triggers.canonical_ping_pong |
autoplay_sdk.proactive_triggers.triggers.scoped_canonical_ping_pong | autoplay_sdk.proactive.triggers.triggers.scoped_canonical_ping_pong |
autoplay_sdk.proactive_triggers.triggers.section_playbook | autoplay_sdk.proactive.triggers.triggers.section_playbook |
autoplay_sdk.proactive_triggers.triggers.user_page_dwell | autoplay_sdk.proactive.triggers.triggers.user_page_dwell |
autoplay_sdk.proactive_triggers.types | autoplay_sdk.proactive.triggers.types |
autoplay_sdk.proactive_triggers.url_scope | autoplay_sdk.proactive.triggers.url_scope |
[0.7.3] β 2026-05-14
Documentation
- Added dedicated references for
UserSessionIndex,compose_chat_pipeline(...), andbuild_copilot_app(...), including lifecycle details, endpoint status semantics, and failure troubleshooting. - Updated Logging with explicit observability guidance for
autoplay_sdk.chat_pipeline,autoplay_sdk.user_index, andautoplay_sdk.serve.fastapi, including recommended app-layer log points for self-hosted bridges. - Added a clearer self-hosted quick-reference and troubleshooting section in
README.md(repository package docs), covering primitive selection and common404/identity/product-scope failure modes.
[0.7.2] β 2026-05-14
Removed
TourDefinition.labelandTourDefinition.user_tour_existsβ these fields belong toproactive_intercom.messages, not the tour registry. Removed from the dataclass,to_dict, andfrom_dict. Legacy configs that still include these keys are silently ignored on parse.
Added
TOUR_OFFER_QUICK_REPLY_BODYβ constant ("Would you like me to show you?"); default body for the tour-offer Yes/No quick reply.tour_offer_quick_reply_body(integration_config)β single SDK source-of-truth for the tour-offer message body; readsintegration_config.tour_offer_bodyfor product-level overrides, falls back to the constant. Call this afterresolve_tour_offer_for_inboundreturns a non-Noneflow id. Both symbols exported fromautoplay_sdk.proactive_triggers.
[0.7.1] β 2026-05-13
Added
autoplay_sdk.install_skillsβ CLI commandautoplay-install-skillsthat copies bundled Cursor/Claude agent skills into the current project. Supports--chatbotand--user-activityflags.autoplay_sdk/skills/β 10 agent skill files shipped inside the wheel:autoplay-core,chatbot-ada,chatbot-intercom,chatbot-botpress,chatbot-dify,chatbot-crisp,chatbot-landbot,chatbot-tidio,activity-fullstory,activity-posthog.
Documentation
- Ada tutorial (
docs/recipes/ada/), FullStory Streams tutorial (docs/recipes/fullstory/how-to-setup.mdx), and quickstartautoplay-install-skillstip block.
[0.7.0] β 2026-05-12
Added
autoplay_sdk.agent_state_v2βSessionStateFSM withTHINKING/PROACTIVE/REACTIVEstates, timeout-only exit rules, andInvalidTransitionError. Coexists with v1AgentStateMachine.autoplay_sdk.proactive_triggers.trigger_configβProactiveTriggerConfig,TriggerMessage, and recursiveProactiveCriteriafor config-driven proactive triggers.autoplay_sdk.proactive_triggers.tour_registryβTourDefinitionandTourRegistry; per-tourinteraction_timeout_s/cooldown_period_soverrides;get_by_user_tour_id().SessionState.record_tour_step(),SessionState.set_visual_guidance(),SessionState.tick(tour_registry=None).parse_tour_registry(integration_config, product_id)helper inproactive_intercom_config.
Changed
integration_config.proactive_intercomβ now a list ofProactiveTriggerConfigobjects (was a single dict).TriggerMessageβ renamedoffers_tourβuser_tour_exists,flow_idβuser_tour_id; backward-compatible properties retained.
Documentation
- Intercom proactive triggers step 2, Agent session states β agent state v2 accordion.
[0.6.8] β 2026-05-05
- SDK branch release tag/version for current branch cut.
AgentStateMachine.enter_reactive_from_user_messagedocs + behavior notes now include rejection logging and preservedInvalidTransitionErrorsemantics.
[0.6.7] β 2026-04-30
Agent FSM, Intercom proactivequick_reply, autoplay_sdk.proactive_triggers (replaces integrations.proactive), registry timings/entity, context builders, scope validation, product-scoped context-store buckets, and proactive idle teardown for chat: run_proactive_idle_expiry, ProactiveIdleExpiryHooks, ProactiveIdleExpiryResult, Intercom DELETE /conversations/{id} helpers (build_intercom_delete_conversation_request, etc.).
For full Added / Changed / Breaking detail, see the same version in the repository CHANGELOG.md.
Removed
autoplay_sdk.integrations.proactiveβ useautoplay_sdk.proactive_triggers(importpaths and submodules mirror the old layout).
Added
autoplay_sdk.agent_statesβAgentState,AgentStateMachine,TaskProgress,SessionMetrics,InvalidTransitionError,InvalidSnapshotError; five-state FSM;transition_on_disengagement();to_snapshot()/from_snapshot();can_show_proactive_with_reason().autoplay_sdk.agent_states.AgentStateMachineβexpire_proactive_to_thinking_if_idle.autoplay_sdk.integrations.intercomβquick_replyhelpers,INTERCOM_PROACTIVE_QUICK_REPLY_DEFAULT_BODY,proactive_trigger_canonical_url_ping_pong, connector helpers forPOST /intercom/proactive/{product_id},IntercomProactivePolicyConfig.autoplay_sdk.proactive_triggersβProactiveTriggerContext,ProactiveTriggerResult, registry,CanonicalPingPongTrigger,default_proactive_trigger_registry, timings (ProactiveTriggerTimings,ProactiveTriggerEntity,interaction_timeout_s,cooldown_s).autoplay_sdk.proactive_triggers.defaultsβProactiveTriggerIds,get_proactive_trigger_ids(),DEFAULT_PROACTIVE_QUICK_REPLY_BODY.PredicateProactiveTrigger;from_actions_payloads/from_slim_actions;DEFAULT_PROACTIVE_CONTEXT_*exports;scope(ScopePolicy, validation helpers);validate_scope(require_conversation).autoplay_sdk.context_storeβactions_bucket_id, optionalproduct_idonget,enrich,reset; composite_actionskeys whenActionsPayload.product_idis set.
Changed
autoplay_sdk.integrations.intercomβINTERCOM_PROACTIVE_QUICK_REPLY_DEFAULT_BODYaliasesproactive_triggers.defaults.ProactiveTriggerContextβ optionalrecent_actions, summaries,context_extra.from_slim_actions/from_actions_payloadsβ defaultscope_policy=STRICT(useLENIENTto relax).POST /intercom/proactive/{product_id}documented as always-on when authenticated (ENABLE_INTERCOM_PROACTIVE_PROMPTSremoved).
Documentation
Breaking changes
expire_proactive_to_thinking_if_idleβ returnsProactiveIdleExpiryResult(useif result:/result.transitioned, notis Trueon the return value). SeeCHANGELOG.md.- Migrate imports from
autoplay_sdk.integrations.proactivetoautoplay_sdk.proactive_triggers. - Strict scope defaults;
LENIENTfor old permissive behaviour. - Match
product_idon context-store reads when payloads carryproduct_id.
[0.6.6] β 2026-04-23
Added
-
SlimAction/ActionsPayloadβ optionalconversation_id(Intercom thread when linked); merge semantics unchanged at batch level. -
autoplay_sdk.rag_queryβ query-time RAG assembly (assemble_rag_chat_context, providers,ChatContextAssembly, formatters). -
autoplay_sdk.promptsβ versioned Adoption Copilot defaults (RAG_SYSTEM_PROMPT,REASONING_PROMPT,RESPONSE_PROMPT). -
autoplay_sdk.rag_query.watermarkβ delta activity watermarks for Intercom / connector chat. -
autoplay_sdk.prompts.intercom_readabilityβ sharedINTERCOM_READABILITY_RULESfragment for Messenger replies.
Changed
-
Root
__all__documents query-time RAG vs ingestionRagPipeline. -
RAG_SYSTEM_PROMPT/RESPONSE_PROMPT(1.2) and connectorINTERCOM_CHAT_PROMPT(5) β readability + guidance framing for product how-to questions. -
assemble_rag_chat_contextβ structured DEBUG / WARNING logging.
Documentation
- Support AI agent context assembly β delta activity and observability cross-links.
Breaking changes
None for JSON consumers β new fields remain optional.[0.6.4] β 2026-04-23
Added
-
SlimActionβ optional per-actionsession_id,user_id, andemail(aligned with batch-level payload identity). Present on each entry inactionsfor SSE, push webhooks, and typed parsing. -
RedisEventBufferβ serialized JSON now includes those fields per action so buffered events round-trip cleanly.
Documentation
- Payload schema and Typed payloads β document per-action identity fields; payload schema clarifies shared shape for SSE and push webhooks.
Breaking changes
None β new fields are optional (None when omitted).
[0.6.2] β 2026-04-16
Added
POST /productsterminal feedback β TTY-only Rich stderr spinner and stdout success/failure lines inpost_register_product_payload; no output when stdout is not a TTY.
Changed
run_product_onboardingβ singlePOST /products; connector performs Redis + Render when configured.render_sync_performedreflects connectordual_writein the JSON response.unkey.pyis now a default dependency β plainpip install autoplay-sdkincludes operator onboarding (autoplay_sdk.admin/ Unkey).
Removed
autoplay-sdk[admin]extra β installautoplay-sdkonly.
[0.6.1] β 2026-04-14
Added
ConversationEventType(autoplay_sdk.chatbot) β enum for chatbot session-link event semantics (NEW/REPLY_EXISTING).BaseChatbotWritersession-link webhook flow βSESSION_LINK_WEBHOOK_TOPICS,extract_conversation_event(),_parse_session_link_webhook_payload()(subclasses override parse only).autoplay_sdk.integrations.intercomβ webhook topic constants,intercom_chatbot_webhook_url(), optionalformat_reactive_session_link_script(no logging from this subpackage).
Removed
format_proactive_session_start_scriptand the proactive/sessions/startsnippet β use Intercom webhooks toPOST /chatbot-webhook/{product_id}; optionalformat_reactive_session_link_scriptremains forPOST /sessions/link.
Documentation
- Logging β logger hierarchy, app-owned
loggingconfiguration, third-party subclass guidance, changelog cross-link. - README β logging section aligned with the above; metrics pointer (
SdkMetricsHook). - Intercom integration β SDK helpers and connector mapping (webhooks, optional snippet, inbox UX).
Breaking changes
format_proactive_session_start_scriptremoved fromautoplay_sdk.integrations.intercom.
Deprecations
None.[0.6.0] β 2026-04-13
Documentation
-
BaseChatbotWriter β Note body format β BaseChatbotWriter now documents the full plain-text contract for
_post_notebodies (header viaformat_chatbot_note_header, sorted 1-based action lines, binning vs post-link, empty list, summary notes)._format_notedocstring points to that page as the single source of truth. -
Logging β New Logging reference page (module loggers,
%formatting,exc_info, structuredextra, secrets guidance including HTTP bodies, common logging mistakes). Quickstart links to it for discoverability.
Bug fixes / observability
-
BaseChatbotWriterβ pre-link flush failurewarningnow includes structuredextra(session_id,product_id,conversation_id). -
BaseChatbotWriterβ post-link debounced flush: if_post_notereturns no part id after the debounce buffer was popped, logs awarningwith the sameextrashape and explains that this flush is not retried automatically.
Breaking changes
None.Deprecations
None.[0.5.0] β 2026-04-10
New features
-
ActionsPayload.merge(payloads)β class method that merges a non-empty list ofActionsPayloadobjects for the same session into one. Actions are concatenated and re-indexed from0;user_id/emailresolved from the first non-Nonevalue;forwarded_atset to the latest timestamp. RaisesValueErroron empty input. -
AsyncAgentContextWriter(debounce_ms=N)β new optional constructor parameter for a per-session trailing-edge accumulation window. When> 0, multipleadd()calls arriving within the window are merged viaActionsPayload.merge()beforewrite_actionsis called, reducing destination API calls during event bursts. Default is0(no debounce β existing behaviour unchanged). -
BaseChatbotWriter(autoplay_sdk.chatbot) β new public base class providing the complete pre-link/post-link delivery policy for building chatbot destinations. Subclass it and implement_post_noteand_redact_part; pre-link buffering (sliding window), at-link flush (binned note), and post-link debouncing are all included.IntercomChatbotin the event connector already extends this class.
Breaking changes
None. All changes are additive:AsyncAgentContextWriter.__init__gainsdebounce_ms: int = 0β existing code passing positional or keyword arguments is unaffected.ActionsPayload.merge()is a new class method; no existing method is renamed or removed.BaseChatbotWriteris a new public export; no existing symbols are removed.
Deprecations
None.Bug fixes / error handling improvements
-
BaseChatbotWriter.on_session_linkedβ now no-ops when the sameconversation_idis passed again (idempotent guard). The product worker includes the conv_id on every batch for already-linked sessions; without this guard, each batch would cancel the in-flight 150ms post-link debounce task and restart the window, causing notes to be delayed indefinitely during fast user interactions. -
BaseChatbotWriter.on_session_linkedβ pre-link buffer (_pending) is now only cleared after_post_noteconfirms success (returns a non-Nonepart id). Previously the buffer was popped before the API call; a transient Intercom failure would permanently lose those events. On failure the buffer is now preserved and the_conv_mapentry is rolled back so the nexton_session_linkedcall retries automatically. -
BaseChatbotWriter.write_actions: the post-link debounceasyncio.Tasknow has adone_callbackthat logs any unhandled exception atERRORlevel with structuredextra(previously silent β Python only emitted aDEBUG-level βTask exception was never retrievedβ). -
AsyncAgentContextWriter._flush_sessiondone-callback: now includesproduct_idin the log message andextradict for structured log filtering.
Migration notes
AsyncAgentContextWriter + BaseChatbotWriter β avoid double-debouncing
BaseChatbotWriter already coalesces rapid write_actions() calls via its post_link_debounce_s window (default 150 ms). When wiring an AsyncAgentContextWriter to a BaseChatbotWriter subclass, keep debounce_ms=0 (the default):
debounce_ms > 0 only when write_actions points to a raw destination with no internal coalescing (e.g. a direct Zendesk or Salesforce API call).
[0.4.0] β 2026-04-09
Bug fixes
- Fixed TOCTOU race in
RedisEventBuffer._get_redis(): concurrent callers could each create their own connection pool; now serialised withasyncio.Lockand double-checked locking. - Fixed
AsyncSessionSummarizer.flush()cancellation safety: replaced sequentialfor q in queues: await q.join()withasyncio.gather(*[asyncio.shield(q.join()) for q in queues])so all queues are drained even when the caller is cancelled.
Other
- Added
CHANGELOG.mdto document breaking changes and new features going forward.
[0.3.0] β 2026-04-09
Breaking changes
AsyncSessionSummarizer.get_context(session_id)is nowasyncβ callers mustawaitit.AsyncSessionSummarizer.reset(session_id)is nowasyncβ callers mustawaitit.AsyncSessionSummarizer.active_sessionsis now anasyncproperty β callers mustawaitit.AsyncSessionSummarizer.add()now returns immediately β the LLM call is dispatched to a background worker queue rather than awaited inline. Code that relied on the LLM having completed by the timeawait add()returned must callawait summarizer.flush()before inspecting state.
New features
AsyncSessionSummarizer.flush()β waits for all queued payloads to be fully processed; cancellation-safe viaasyncio.gather+asyncio.shield.SdkMetricsHookprotocol (autoplay_sdk.metrics) β a@runtime_checkable Protocolthat customers can implement to receive Prometheus / Datadog / OTEL counters for: dropped events, summarizer latency, Redis operation latency, queue depth, and semaphore timeouts.metrics=constructor parameter onConnectorClient,AsyncConnectorClient,AsyncSessionSummarizer, andRedisEventBuffer.initial_backoff_s,max_backoff_s,max_retriesconstructor parameters on both SSE clients β exposes and documents the reconnect policy with configurable jitter-backed exponential backoff.- Per-session ordering guarantee in
AsyncSessionSummarizerβ each session now has its ownasyncio.Queue+ backgroundasyncio.Taskworker, ensuring that concurrentadd()calls for the same session are always processed in arrival order, even if an earlier LLM call fails. py.typedmarker β the package is now PEP 561-compliant; static type-checkers will find type stubs automatically.
Bug fixes (v0.2.x β v0.3.0)
The following 24 items were addressed across two audit passes: Concurrency & correctness- Fixed
AsyncSessionSummarizerordering bug: concurrent adds during an LLM failure could produce out-of-orderon_summarycallbacks (replaced single lock with per-session queue). - Fixed TOCTOU race in
RedisEventBuffer._get_redis(): concurrent callers could each create their own connection pool; now serialised withasyncio.Lockand double-checked locking. - Replaced
asyncio.Semaphore._value(private API, breaks across CPython minor versions) with an explicit_TrackedSemaphorecounter. - Replaced
asyncio.get_event_loop()(deprecated) withasyncio.get_running_loop()inapp.pyandasync_client.py. - Replaced
asyncio.ensure_future()withloop.create_task()inasync_client.py. - Added
done_callbackon fire-and-forgetasyncio.Tasks to log unhandled exceptions instead of silently swallowing them.
RedisEventBuffer._payload_from_json()now wrapsjson.loadsintry/except json.JSONDecodeError; corrupt ZSET members no longer crash the drain loop.ConnectorClientnow setsself._running = FalseonKeyboardInterruptso callers can inspect the state after shutdown.- All
exceptclauses that were swallowing exceptions now passexc_info=Trueto the logger so tracebacks appear in structured logs.
RedisEventBufferZSET members now carry a unique UUID prefix, preventing silent deduplication when two events arrive at the same millisecond timestamp.SessionSummarizernow deletes_history[session_id]and_counts[session_id]after summarisation to prevent unbounded memory growth.AsyncConnectorClient._session_semaphoreschanged from plaindicttocollections.OrderedDictwith LRU eviction to cap memory when many short-lived sessions are processed.
- Extracted
LazyRedisClienthelper (storage/_redis.py) so all storage modules share one lazily-initialised, thread-safe Redis client instead of each implementing the same racy pattern. session_storenow usesLazyRedisClientand exposes aSessionState.from_redis_link()classmethod that owns the full reconstruction logic (preventing silent field omissions on restore).SessionStategains anerror: Optional[str]field to surface last-known error reason through the API.
- Replaced custom
_JsonFormatterinapp.pythat ignoredextra={}fields with a correct implementation that merges them into the JSON line. - All structured log calls now use
extra={}dicts consistently. - Metrics instrumentation added at every observability-relevant site: event drops, queue depth, semaphore timeouts, summarizer latency, Redis add/drain latency.
- Added
__all__exports to__init__.pysofrom autoplay_sdk import *is well-defined. - Added
__version__ = "0.3.0"to__init__.py. - Added
py.typedmarker for PEP 561 compliance. - Removed dead
_dropped_count/_total_countmetrics fields that were incremented but never surfaced. - Standardised public API:
on_dropcallback signature is now consistent acrossConnectorClient,AsyncConnectorClient, andRedisEventBuffer.