See Proactive triggers for the module reference (types, constants, built-in IDs).
Overview: the full flow
Step 1 β Choose how to build your trigger
There are three paths. Pick the one that fits your situation:Path A: Code-defined trigger (most common)
Write your trigger in Python β no JSON config required. Use this for custom business logic, multi-condition rules, or anything the built-in catalog doesnβt cover. UsePredicateProactiveTrigger when the rule is a single boolean on ctx (covers most cases):
ProactiveTrigger subclass when you need stateful logic, multiple branches, or side-effect-free setup:
Path B: Add a built-in to the catalog (for connector-configurable triggers)
Use this when you want operators to enable/disable the trigger viaintegration_config.proactive_triggers.builtins JSON, without deploying code changes.
Add a BuiltinTriggerCatalogEntry to BUILTIN_TRIGGER_CATALOG in builtin_catalog.py:
id, name, and description as non-empty strings. After release, operators enable it with:
Path C: Use the built-in URL ping-pong (zero code)
The SDK shipsCanonicalPingPongTrigger out of the box β it fires when a user bounces between the same URLs, signalling hesitation. To use it, either:
- Call
default_proactive_trigger_registry()to get a registry pre-loaded with it, or - Include
"canonical_url_ping_pong"in yourbuiltinsJSON config (see Intercom integration).
min_cycles to control how many back-and-forth URL repeats count as hesitation.
Step 2 β Build context on each tick
ProactiveTriggerContext is a snapshot of session state. Build it from your event buffer on every evaluation tick.
Factory shortcut:
ProactiveTriggerContext.from_actions_payloads(payloads, session_id=..., product_id=...) builds context automatically, applying a 120 s lookback window and a 50-action cap by default. Pass lookback_seconds=None or max_actions=None to disable those filters.
Step 3 β Register and evaluate
Wrap your triggers in aProactiveTriggerRegistry. Order matters β evaluate_first returns the first matching trigger.
ProactiveTriggerEntity merges explicit timings onto the inner triggerβs result via dataclasses.replace. If you skip it, the result uses DEFAULT_INTERACTION_TIMEOUT_S (10 s) and DEFAULT_COOLDOWN_S (30 s).
Step 4 β Gate on FSM state and deliver
Before firing, check thatSessionState allows proactive assistance:
- Intercom
quick_reply: usebuild_intercom_quick_reply_reply_payload(result)β see Intercom integration for headers and HTTP shape. - Modal / toast / other UI: use
result.bodyandresult.reply_option_labelsdirectly.
result.interaction_timeout_s:
SessionState and Proactive state helpers for idle-expiry integration references.
Default values reference
All four constants live in
autoplay_sdk.proactive_triggers.types β the single source of truth. Catalog entries and ProactiveTriggerTimings() use them as fallbacks.
Stable trigger_id values
trigger_id strings are used as analytics keys and cooldown identifiers β they must be stable across deployments.
- For built-ins, use the constants from
ProactiveTriggerIds/defaults.py(e.g.TRIGGER_ID_CANONICAL_URL_PING_PONG). - For custom triggers, define your own string constants and donβt rename them after launch.
- When adding a first-party built-in to the connector: add
id/name/descriptiontoBUILTIN_TRIGGER_CATALOG, extendProactiveTriggerIds, bump the SDK version, and note it in the changelog.
Complete example
Related pages
- Proactive triggers β Module reference: types, constants, built-in IDs, connector JSON schema.
- Agent session states β
SessionStatev2 transitions, cooldown gating, and routing fields. - Intercom integration β
quick_replyHTTP shape, delete-conversation helpers, connector LLM labels. - Typed payloads β
SlimAction,ActionsPayload,SummaryPayload.