Skip to main content
The canonical changelog for releases and PyPI sdists also lives in the repository as 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_sync now register against the AWS activity connector. DEFAULT_CONNECTOR_URL is https://connector.autoplay.ai (was the legacy Render connector). The POST /products request body now carries provider + optional ingest_secret + force (replacing webhook_secret / integration_type=event_stream / force_reregister), and the response is read from credentials.{ingest_secret, mcp_key} + setup.{ingest_url, ingest_auth, mcp_url, mcp_auth}.
  • OnboardProductResult reshaped 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_payload and post_aws_register_product in autoplay_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_product keyword args webhook_secret and force_reregister (replaced by ingest_secret and force); user_activity_provider is 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 of UserAdoptionState plus frozen per-session snapshots, behind a pluggable adapter interface.
    • AutoplayStorageAdapter β€” a @runtime_checkable Protocol (mirrors BufferBackend) with async save_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 lazy redis.asyncio pool with graceful degradation (mirrors RedisSessionStateStore), SET NX write-once for snapshots. Needs the redis extra.
    • InMemoryStorageAdapter β€” tests/dev adapter with write-once snapshot semantics.
    • Product-scoped key builders β€” user_state_key(product_id, user_id) and session_key(product_id, user_id, session_id).
    • Session lifecycle helpers β€” init_user_state, on_session_start, on_session_end, build_agent_context. on_session_end resolves the onboarding summary via an injected summarizer callable or a pre-computed summary= β€” the SDK never calls an LLM.
  • Write-only analytics sinks β€” AmplitudeStorageAdapter / PostHogStorageAdapter (deep-import from autoplay_sdk.storage.adapters.{amplitude,posthog}), gated behind a new autoplay-sdk[analytics] extra. They save_* (with optional property_prefix=) and return None from get_*; failures are best-effort (logged, never raised).
  • SessionSnapshot β€” a new frozen, write-once per-session model with to_dict / from_dict (defensive) and a SessionSnapshot.from_adoption_state(...) helper that builds the snapshot from a live UserAdoptionState (reusing the model’s derived helpers β€” no hand-rolled mapping).
  • SessionIndexEntry + a bounded sessions index on UserAdoptionState β€” sessions_count (monotonic lifetime total), current_session_id, and sessions_index (capped to the most recent 50 via record_session), plus set_current_session.
  • OnboardingState.summary and OnboardingState.completion_rate β€” cross-session briefing + cached completion snapshot.
  • ONBOARDING_SUMMARY_PROMPT (v0.1, plain-text output) in autoplay_sdk.prompts and a pure build_onboarding_summary_input(snapshot) builder in autoplay_sdk.user_adoption_state.
  • Exports β€” storage symbols re-exported from top-level autoplay_sdk; SessionSnapshot, SessionIndexEntry, COMPLETION_RATE_DENOMINATOR_*, and build_onboarding_summary_input from autoplay_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 calls report_error at 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 new UserAdoptionState 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 OnboardingWorkflow can now declare an ordered list of **WorkflowStep**s (step_id, name, description, required), configured per product under integration_config.onboarding_workflows[].steps. Steps are context/signal for the LLM (what β€œdone” looks like) and for explainability β€” they are not a checklist gate. required is a hint, not a hard gate. Helper OnboardingWorkflow.required_step_ids.
  • StepProgress β€” the agent’s per-step belief (step_id, status reusing WorkflowStatus, confidence, evidence, completed_at, last_evaluated_at), a deliberate parallel to WorkflowProgress one level down.
  • WorkflowProgress.steps β€” a dict[str, StepProgress] map of per-step beliefs, with a completed_step_ids helper and an upsert_step_progress(step_id, *, status, confidence, evidence="", now=None) mutation (write-once completed_at, mirroring upsert_workflow_progress).
  • is_plan_complete(plan, workflow_progress) β€” thin convenience wrapper over split_workflows (True when no outstanding workflows; an empty plan is never complete). Completion stays the LLM’s call via WorkflowProgress.status β€” steps never gate it.
  • step_completion_ratio(workflow, wp) β€” fraction of a workflow’s declared steps the LLM believes are completed. For display/telemetry only; never used to decide completion.
  • Exports β€” WorkflowStep, StepProgress, is_plan_complete, step_completion_ratio added to autoplay_sdk.user_adoption_state.

Documentation

  • User adoption state updated with the steps data model, the product-config steps schema, 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-command autoplay-setup onboarding flow (plumbing runs as tested code, not via an agent).

Changed

  • activity-posthog skill is now the single source (modular: SKILL.md + references/ + examples/), replacing the forked posthog-setup skill 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-session SessionState FSM and keyed by user_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), and WorkflowStatus (not_started / in_progress / completed).
  • UserAdoptionState β€” top-level per-user record: a fully dynamic, schema-less metadata bag (with a role convenience property), journey_state, mastery, discovered_features, and an onboarding sub-object. Mandatory non-empty user_id (raises otherwise, like SessionState); to_dict() / from_dict() with _v snapshot versioning and defensive enum coercion; transition helpers (set_journey_state, set_mastery, record_discovered_features, mark_welcomed, mark_judged) that log structured events; and to_prompt_block() for compact prompt injection.
  • Mastery (0-10 rating, clamped, + MasteryLevel + reason), WorkflowProgress (per-flow status / confidence / evidence / timestamps β€” the agent’s evolving belief from the live activity stream), StepInAssessment (latest β€œshould I step in?” decision + timing rationale), and OnboardingState (welcome lifecycle, workflow_progress map, derived completed / in_progress / outstanding helpers, 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 via for_role) + pure split_workflows() β†’ (completed, in_progress, outstanding).
  • Query β†’ tour matching primitive β€” build_tour_match_input() and parse_tour_match_output() (validates ids against a role-filtered catalog, safe fallback on malformed JSON), plus TourCatalogEntry and TourMatchResult.
  • Versioned prompts in autoplay_sdk.prompts (each a dict with name / 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_llm runners are integration-owned.

Breaking changes

None β€” the module and exports are purely additive.

[0.7.9] β€” 2026-05-25

Breaking changes

  • SessionState.session_id is now a required field β€” no default. SessionState() raises TypeError. Use SessionState(session_id="...") or InMemorySessionStateStore.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 call tick() before this method. Replaces any inline current_state == THINKING and not thinking.cooldown_active pattern.
  • SessionState now holds session_id: str (the only mandatory scope key) and metadata: dict[str, Any] (open bag for optional identity context β€” user_id, email, any future fields). Both fields are persisted via to_dict() / from_dict() and default to empty for backward compatibility.
  • RedisSessionStateStore β€” Redis-backed SessionState store for production use. Key pattern autoplay:session_state:{session_id}, configurable TTL (default 24 h), graceful fallback on Redis errors. Requires pip install "autoplay-sdk[redis]".
  • AutoplayChatbotManager β€” high-level wrapper that handles all session lifecycle automatically. Developers implement only _post_note and call two methods: on_actions(payload) from the Autoplay stream and on_chatbot_event(session_id, conversation_id) from the chatbot webhook.
  • AutoplayChatbotManager(session_store=...) β€” optional parameter to inject a custom store. Defaults to InMemorySessionStateStore(). Pass RedisSessionStateStore(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_actions and on_chatbot_event call this automatically; use save_state only for mutations that happen outside those entry points.
  • InMemorySessionStateStore β€” canonical store for SessionState objects. get_or_create(session_id) is the first call in every handler. async interface for drop-in Redis-backed replacement.
  • BaseChatbotWriter.__init_subclass__ enforcement β€” raises TypeError at class-definition time (module import) when a subclass sets SESSION_LINK_WEBHOOK_TOPICS without overriding _parse_session_link_webhook_payload. Converts a silent production crash into a startup error caught by tests and local runs. Subclasses that leave SESSION_LINK_WEBHOOK_TOPICS = () are unaffected.
  • link_conversation now auto-detects ConversationEventType.NEW vs REPLY_EXISTING from the store when event is not passed β€” removes the last manual determination from integration authors.
  • link_conversation now infers session_id from state.session_id when not passed explicitly. Existing callers that pass session_id are unaffected.
  • link_conversation raises ValueError if session_id is empty after resolution, with a clear message pointing to InMemorySessionStateStore.get_or_create.
  • AutoplayChatbotManager and InMemorySessionStateStore exported from top-level autoplay_sdk.
  • AutoplayChatbotManager.on_chatbot_event now persists the updated SessionState back to RedisSessionStateStore after linking so the conversation link survives restarts.
  • redis optional extra added to pyproject.toml: pip install "autoplay-sdk[redis]".

Changed

  • ConversationEvent renamed to ConversationEventType β€” the old name was misleading because it read as a data container rather than a type discriminator. A deprecated backward-compat alias ConversationEvent = ConversationEventType is exported from both autoplay_sdk and autoplay_sdk.chat; it will be removed in the next major version. Update any import of ConversationEvent to ConversationEventType.
  • proactive_fsm_gate_for_session delivery invariant clarified β€” no linked conversation β†’ first proactive β†’ always allowed (a new conversation will be created and linked). A linked conversation β†’ check FSM via can_deliver_proactive(). The fallback_conversation_id parameter 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 known conversation_id, then call can_deliver_proactive() on the already-loaded session. They no longer go through proactive_fsm_gate_for_session (which has delivery-specific semantics).
  • AutoplayChatbotManager.on_chatbot_event removes the isinstance(store, RedisSessionStateStore) guard β€” save is always called regardless of which store is wired. on_actions does not save (no state mutation occurs during action delivery; first-creation is already persisted by get_or_create).
  • InMemorySessionStateStore gains a no-op save(state) method so all call sites are uniform.

Documentation

  • BaseChatbotWriter: rewritten to lead with AutoplayChatbotManager as the recommended path, updated session-first linking section to show InMemorySessionStateStore + get_or_create pattern, added Production persistence section with RedisSessionStateStore one-line swap.
  • autoplay-core skill: 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 use can_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.
  • SessionState class docstring now lists conversation_linked and conversation_id in its Fields section.
  • Agent session states Key Methods table now includes can_deliver_proactive(); ThinkingState table now includes active_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.intercom and autoplay_sdk.proactive.triggers by moving proactive_trigger_canonical_url_ping_pong and proactive_trigger_canonical_url_ping_pong_projects_either_leg into autoplay_sdk.proactive.triggers._url_predicates. intercom.py re-exports both for backward compatibility.

[0.7.6] β€” 2026-05-18

Fixed

  • autoplay_sdk/skills/autoplay-migrate-imports/SKILL.md β€” tightened the discovery rg filter 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 runtime DeprecationWarning messages to discover new paths.

Documentation

  • Updated BaseChatbotWriter with a new session-first linking section covering:
    • ConversationEventType.NEW vs ConversationEventType.REPLY_EXISTING
    • canonical dual-write flow via link_conversation(...) (ConversationLinkStore write, then SessionState.on_conversation_linked(...))
    • hot-path routing with resolve_linked_conversation_id(state) from session-owned state.
  • Expanded Agent session states v2 docs with:
    • explicit SessionState link fields (conversation_linked, conversation_id)
    • on_conversation_linked(link) overwrite/no-op semantics and invariants
    • a state/flag matrix for THINKING, PROACTIVE, and REACTIVE.
  • 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 test optional dependency extra to include async/runtime test dependencies (pytest-asyncio, fakeredis, respx) so pip 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 in 0.7.4 and emit DeprecationWarning; they are removed in 1.0.0.

Added

  • autoplay_sdk.compat shim registry and helper.
  • tests/compat/test_import_compat.py import 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-skills now supports --migrate.

Deprecated paths (remove in 1.0.0)

autoplay_sdk.rag remains a stable alias in 0.7.4 (no deprecation warning).
OldNew
autoplay_sdk.serveautoplay_sdk.api
autoplay_sdk.serve.fastapiautoplay_sdk.api.fastapi
autoplay_sdk.agent_statesautoplay_sdk.agent_state.v1.states
autoplay_sdk.agent_states.state_machineautoplay_sdk.agent_state.v1.state_machine
autoplay_sdk.agent_states.typesautoplay_sdk.agent_state.v1.types
autoplay_sdk.agent_states.proactive_idle_expiryautoplay_sdk.proactive.state.idle_expiry
autoplay_sdk.agent_state_v2autoplay_sdk.agent_state.v2.states
autoplay_sdk.agent_state_v2.session_stateautoplay_sdk.agent_state.v2.session_state
autoplay_sdk.agent_state_v2.typesautoplay_sdk.agent_state.v2.types
autoplay_sdk.rag_queryautoplay_sdk.rag.query
autoplay_sdk.rag_query.assemblyautoplay_sdk.rag.query.assembly
autoplay_sdk.rag_query.formattersautoplay_sdk.rag.query.formatters
autoplay_sdk.rag_query.pipelineautoplay_sdk.rag.query.pipeline
autoplay_sdk.rag_query.watermarkautoplay_sdk.rag.query.watermark
autoplay_sdk.proactive_resilienceautoplay_sdk.proactive.resilience.resilience
autoplay_sdk.proactive_resilience.circuitautoplay_sdk.proactive.resilience.circuit
autoplay_sdk.proactive_resilience.configautoplay_sdk.proactive.resilience.config
autoplay_sdk.proactive_resilience.keysautoplay_sdk.proactive.resilience.keys
autoplay_sdk.proactive_resilience.outcomesautoplay_sdk.proactive.resilience.outcomes
autoplay_sdk.proactive_resilience.protocolautoplay_sdk.proactive.resilience.protocol
autoplay_sdk.chatbotautoplay_sdk.chat.chatbot
autoplay_sdk.chat_pipelineautoplay_sdk.chat.chat_pipeline
autoplay_sdk.context_storeautoplay_sdk.context.context_store
autoplay_sdk.agent_contextautoplay_sdk.context.agent_context
autoplay_sdk.user_indexautoplay_sdk.context.user_index
autoplay_sdk.summarizerautoplay_sdk.context.summarizer
autoplay_sdk.modelsautoplay_sdk.core.models
autoplay_sdk.exceptionsautoplay_sdk.core.exceptions
autoplay_sdk.metricsautoplay_sdk.core.metrics
autoplay_sdk.onboardingautoplay_sdk.admin.onboarding
autoplay_sdk.proactive_idle_expiryautoplay_sdk.proactive.state.idle_expiry
autoplay_sdk.proactive_triggersautoplay_sdk.proactive.triggers
autoplay_sdk.proactive_triggers.builtin_catalogautoplay_sdk.proactive.triggers.builtin_catalog
autoplay_sdk.proactive_triggers.context_sourceautoplay_sdk.proactive.triggers.context_source
autoplay_sdk.proactive_triggers.defaultsautoplay_sdk.proactive.triggers.defaults
autoplay_sdk.proactive_triggers.entityautoplay_sdk.proactive.triggers.entity
autoplay_sdk.proactive_triggers.judgeautoplay_sdk.proactive.triggers.judge
autoplay_sdk.proactive_triggers.pending_tour_offerautoplay_sdk.proactive.triggers.pending_tour_offer
autoplay_sdk.proactive_triggers.predicate_triggerautoplay_sdk.proactive.triggers.predicate_trigger
autoplay_sdk.proactive_triggers.proactive_intercom_configautoplay_sdk.proactive.triggers.proactive_intercom_config
autoplay_sdk.proactive_triggers.quick_reply_matchautoplay_sdk.proactive.triggers.quick_reply_match
autoplay_sdk.proactive_triggers.registryautoplay_sdk.proactive.triggers.registry
autoplay_sdk.proactive_triggers.scopeautoplay_sdk.proactive.triggers.scope
autoplay_sdk.proactive_triggers.section_activityautoplay_sdk.proactive.triggers.section_activity
autoplay_sdk.proactive_triggers.tour_registryautoplay_sdk.proactive.triggers.tour_registry
autoplay_sdk.proactive_triggers.trigger_configautoplay_sdk.proactive.triggers.trigger_config
autoplay_sdk.proactive_triggers.triggersautoplay_sdk.proactive.triggers.triggers
autoplay_sdk.proactive_triggers.triggers.canonical_ping_pongautoplay_sdk.proactive.triggers.triggers.canonical_ping_pong
autoplay_sdk.proactive_triggers.triggers.scoped_canonical_ping_pongautoplay_sdk.proactive.triggers.triggers.scoped_canonical_ping_pong
autoplay_sdk.proactive_triggers.triggers.section_playbookautoplay_sdk.proactive.triggers.triggers.section_playbook
autoplay_sdk.proactive_triggers.triggers.user_page_dwellautoplay_sdk.proactive.triggers.triggers.user_page_dwell
autoplay_sdk.proactive_triggers.typesautoplay_sdk.proactive.triggers.types
autoplay_sdk.proactive_triggers.url_scopeautoplay_sdk.proactive.triggers.url_scope
See Migration 0.7.4 for upgrade steps.

[0.7.3] β€” 2026-05-14

Documentation

  • Added dedicated references for UserSessionIndex, compose_chat_pipeline(...), and build_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, and autoplay_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 common 404/identity/product-scope failure modes.

[0.7.2] β€” 2026-05-14

Removed

  • TourDefinition.label and TourDefinition.user_tour_exists β€” these fields belong to proactive_intercom.messages, not the tour registry. Removed from the dataclass, to_dict, and from_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; reads integration_config.tour_offer_body for product-level overrides, falls back to the constant. Call this after resolve_tour_offer_for_inbound returns a non-None flow id. Both symbols exported from autoplay_sdk.proactive_triggers.

[0.7.1] β€” 2026-05-13

Added

  • autoplay_sdk.install_skills β€” CLI command autoplay-install-skills that copies bundled Cursor/Claude agent skills into the current project. Supports --chatbot and --user-activity flags.
  • 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 quickstart autoplay-install-skills tip block.

[0.7.0] β€” 2026-05-12

Added

  • autoplay_sdk.agent_state_v2 β€” SessionState FSM with THINKING / PROACTIVE / REACTIVE states, timeout-only exit rules, and InvalidTransitionError. Coexists with v1 AgentStateMachine.
  • autoplay_sdk.proactive_triggers.trigger_config β€” ProactiveTriggerConfig, TriggerMessage, and recursive ProactiveCriteria for config-driven proactive triggers.
  • autoplay_sdk.proactive_triggers.tour_registry β€” TourDefinition and TourRegistry; per-tour interaction_timeout_s / cooldown_period_s overrides; 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 in proactive_intercom_config.

Changed

  • integration_config.proactive_intercom β€” now a list of ProactiveTriggerConfig objects (was a single dict).
  • TriggerMessage β€” renamed offers_tour β†’ user_tour_exists, flow_id β†’ user_tour_id; backward-compatible properties retained.

Documentation


[0.6.8] β€” 2026-05-05

  • SDK branch release tag/version for current branch cut.
  • AgentStateMachine.enter_reactive_from_user_message docs + behavior notes now include rejection logging and preserved InvalidTransitionError semantics.

[0.6.7] β€” 2026-04-30

Agent FSM, Intercom proactive quick_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 β€” use autoplay_sdk.proactive_triggers (import paths 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_reply helpers, INTERCOM_PROACTIVE_QUICK_REPLY_DEFAULT_BODY, proactive_trigger_canonical_url_ping_pong, connector helpers for POST /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, optional product_id on get, enrich, reset; composite _actions keys when ActionsPayload.product_id is set.

Changed

  • autoplay_sdk.integrations.intercom β€” INTERCOM_PROACTIVE_QUICK_REPLY_DEFAULT_BODY aliases proactive_triggers.defaults.
  • ProactiveTriggerContext β€” optional recent_actions, summaries, context_extra.
  • from_slim_actions / from_actions_payloads β€” default scope_policy=STRICT (use LENIENT to relax).
  • POST /intercom/proactive/{product_id} documented as always-on when authenticated (ENABLE_INTERCOM_PROACTIVE_PROMPTS removed).

Documentation

Breaking changes

  • expire_proactive_to_thinking_if_idle β€” returns ProactiveIdleExpiryResult (use if result: / result.transitioned, not is True on the return value). See CHANGELOG.md.
  • Migrate imports from autoplay_sdk.integrations.proactive to autoplay_sdk.proactive_triggers.
  • Strict scope defaults; LENIENT for old permissive behaviour.
  • Match product_id on context-store reads when payloads carry product_id.

[0.6.6] β€” 2026-04-23

Added

  • SlimAction / ActionsPayload β€” optional conversation_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 β€” shared INTERCOM_READABILITY_RULES fragment for Messenger replies.

Changed

  • Root __all__ documents query-time RAG vs ingestion RagPipeline.
  • RAG_SYSTEM_PROMPT / RESPONSE_PROMPT (1.2) and connector INTERCOM_CHAT_PROMPT (5) β€” readability + guidance framing for product how-to questions.
  • assemble_rag_chat_context β€” structured DEBUG / WARNING logging.

Documentation

Breaking changes

None for JSON consumers β€” new fields remain optional.

[0.6.4] β€” 2026-04-23

Added

  • SlimAction β€” optional per-action session_id, user_id, and email (aligned with batch-level payload identity). Present on each entry in actions for 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 /products terminal feedback β€” TTY-only Rich stderr spinner and stdout success/failure lines in post_register_product_payload; no output when stdout is not a TTY.

Changed

  • run_product_onboarding β€” single POST /products; connector performs Redis + Render when configured. render_sync_performed reflects connector dual_write in the JSON response.
  • unkey.py is now a default dependency β€” plain pip install autoplay-sdk includes operator onboarding (autoplay_sdk.admin / Unkey).

Removed

  • autoplay-sdk[admin] extra β€” install autoplay-sdk only.

[0.6.1] β€” 2026-04-14

Added

  • ConversationEventType (autoplay_sdk.chatbot) β€” enum for chatbot session-link event semantics (NEW / REPLY_EXISTING).
  • BaseChatbotWriter session-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(), optional format_reactive_session_link_script (no logging from this subpackage).

Removed

  • format_proactive_session_start_script and the proactive /sessions/start snippet β€” use Intercom webhooks to POST /chatbot-webhook/{product_id}; optional format_reactive_session_link_script remains for POST /sessions/link.

Documentation

  • Logging β€” logger hierarchy, app-owned logging configuration, 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_script removed from autoplay_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_note bodies (header via format_chatbot_note_header, sorted 1-based action lines, binning vs post-link, empty list, summary notes). _format_note docstring points to that page as the single source of truth.
  • Logging β€” New Logging reference page (module loggers, % formatting, exc_info, structured extra, secrets guidance including HTTP bodies, common logging mistakes). Quickstart links to it for discoverability.

Bug fixes / observability

  • BaseChatbotWriter β€” pre-link flush failure warning now includes structured extra (session_id, product_id, conversation_id).
  • BaseChatbotWriter β€” post-link debounced flush: if _post_note returns no part id after the debounce buffer was popped, logs a warning with the same extra shape 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 of ActionsPayload objects for the same session into one. Actions are concatenated and re-indexed from 0; user_id/email resolved from the first non-None value; forwarded_at set to the latest timestamp. Raises ValueError on empty input.
  • AsyncAgentContextWriter(debounce_ms=N) β€” new optional constructor parameter for a per-session trailing-edge accumulation window. When > 0, multiple add() calls arriving within the window are merged via ActionsPayload.merge() before write_actions is called, reducing destination API calls during event bursts. Default is 0 (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_note and _redact_part; pre-link buffering (sliding window), at-link flush (binned note), and post-link debouncing are all included. IntercomChatbot in the event connector already extends this class.

Breaking changes

None. All changes are additive:
  • AsyncAgentContextWriter.__init__ gains debounce_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.
  • BaseChatbotWriter is 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 same conversation_id is 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_note confirms success (returns a non-None part 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_map entry is rolled back so the next on_session_linked call retries automatically.
  • BaseChatbotWriter.write_actions: the post-link debounce asyncio.Task now has a done_callback that logs any unhandled exception at ERROR level with structured extra (previously silent β€” Python only emitted a DEBUG-level β€œTask exception was never retrieved”).
  • AsyncAgentContextWriter._flush_session done-callback: now includes product_id in the log message and extra dict 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):
Use 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 with asyncio.Lock and double-checked locking.
  • Fixed AsyncSessionSummarizer.flush() cancellation safety: replaced sequential for q in queues: await q.join() with asyncio.gather(*[asyncio.shield(q.join()) for q in queues]) so all queues are drained even when the caller is cancelled.

Other

  • Added CHANGELOG.md to document breaking changes and new features going forward.

[0.3.0] β€” 2026-04-09

Breaking changes

  • AsyncSessionSummarizer.get_context(session_id) is now async β€” callers must await it.
  • AsyncSessionSummarizer.reset(session_id) is now async β€” callers must await it.
  • AsyncSessionSummarizer.active_sessions is now an async property β€” callers must await it.
  • 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 time await add() returned must call await summarizer.flush() before inspecting state.

New features

  • AsyncSessionSummarizer.flush() β€” waits for all queued payloads to be fully processed; cancellation-safe via asyncio.gather + asyncio.shield.
  • SdkMetricsHook protocol (autoplay_sdk.metrics) β€” a @runtime_checkable Protocol that 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 on ConnectorClient, AsyncConnectorClient, AsyncSessionSummarizer, and RedisEventBuffer.
  • initial_backoff_s, max_backoff_s, max_retries constructor 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 own asyncio.Queue + background asyncio.Task worker, ensuring that concurrent add() calls for the same session are always processed in arrival order, even if an earlier LLM call fails.
  • py.typed marker β€” 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 AsyncSessionSummarizer ordering bug: concurrent adds during an LLM failure could produce out-of-order on_summary callbacks (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 with asyncio.Lock and double-checked locking.
  • Replaced asyncio.Semaphore._value (private API, breaks across CPython minor versions) with an explicit _TrackedSemaphore counter.
  • Replaced asyncio.get_event_loop() (deprecated) with asyncio.get_running_loop() in app.py and async_client.py.
  • Replaced asyncio.ensure_future() with loop.create_task() in async_client.py.
  • Added done_callback on fire-and-forget asyncio.Tasks to log unhandled exceptions instead of silently swallowing them.
Error handling
  • RedisEventBuffer._payload_from_json() now wraps json.loads in try/except json.JSONDecodeError; corrupt ZSET members no longer crash the drain loop.
  • ConnectorClient now sets self._running = False on KeyboardInterrupt so callers can inspect the state after shutdown.
  • All except clauses that were swallowing exceptions now pass exc_info=True to the logger so tracebacks appear in structured logs.
Data structures
  • RedisEventBuffer ZSET members now carry a unique UUID prefix, preventing silent deduplication when two events arrive at the same millisecond timestamp.
  • SessionSummarizer now deletes _history[session_id] and _counts[session_id] after summarisation to prevent unbounded memory growth.
  • AsyncConnectorClient._session_semaphores changed from plain dict to collections.OrderedDict with LRU eviction to cap memory when many short-lived sessions are processed.
Redis connection management
  • Extracted LazyRedisClient helper (storage/_redis.py) so all storage modules share one lazily-initialised, thread-safe Redis client instead of each implementing the same racy pattern.
  • session_store now uses LazyRedisClient and exposes a SessionState.from_redis_link() classmethod that owns the full reconstruction logic (preventing silent field omissions on restore).
  • SessionState gains an error: Optional[str] field to surface last-known error reason through the API.
Logging & observability
  • Replaced custom _JsonFormatter in app.py that ignored extra={} 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.
Package hygiene
  • Added __all__ exports to __init__.py so from autoplay_sdk import * is well-defined.
  • Added __version__ = "0.3.0" to __init__.py.
  • Added py.typed marker for PEP 561 compliance.
  • Removed dead _dropped_count / _total_count metrics fields that were incremented but never surfaced.
  • Standardised public API: on_drop callback signature is now consistent across ConnectorClient, AsyncConnectorClient, and RedisEventBuffer.

[0.2.0] β€” prior

Initial internal release. No changelog maintained at this version.