Skip to main content
This guide walks you through building a proactive trigger end-to-end: assembling context from your event buffer, writing a trigger, registering it, evaluating it on each tick, and handing the result to your delivery layer.
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. Use PredicateProactiveTrigger when the rule is a single boolean on ctx (covers most cases):
Use a full 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 via integration_config.proactive_triggers.builtins JSON, without deploying code changes. Add a BuiltinTriggerCatalogEntry to BUILTIN_TRIGGER_CATALOG in builtin_catalog.py:
Every catalog entry must define 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 ships CanonicalPingPongTrigger 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 your builtins JSON config (see Intercom integration).
Tune 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.
Where each field comes from:
FieldTypical source
session_id, product_idYour session / tenant identifiers β€” required, must be non-empty
conversation_idIntercom (or other) thread ID β€” set when the user has an active chat
canonical_urls[a.canonical_url for a in actions] β€” chronological page URL list
recent_actionsLast N SlimAction objects from your merged ActionsPayload.actions
latest_summary_textOutput of your SessionSummarizer or latest SummaryPayload
prior_session_summariesPast session narratives from Redis, DB, etc.
context_extraArbitrary connector-specific blob; don’t share mutable dicts across ticks
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 a ProactiveTriggerRegistry. 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 that SessionState allows proactive assistance:
Delivery options:
  • Intercom quick_reply: use build_intercom_quick_reply_reply_payload(result) β€” see Intercom integration for headers and HTTP shape.
  • Modal / toast / other UI: use result.body and result.reply_option_labels directly.
Idle expiry β€” after the proactive message is shown, start an idle timer using result.interaction_timeout_s:
See Agent session states for SessionState and Proactive state helpers for idle-expiry integration references.

Default values reference

WhatConstantDefault
Idle window for proactive UIDEFAULT_INTERACTION_TIMEOUT_S10 s
Min gap before same trigger re-firesDEFAULT_COOLDOWN_S30 s
Action lookback window (factory)DEFAULT_PROACTIVE_CONTEXT_LOOKBACK_S120 s
Max actions loaded (factory)DEFAULT_PROACTIVE_CONTEXT_MAX_ACTIONS50
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/description to BUILTIN_TRIGGER_CATALOG, extend ProactiveTriggerIds, bump the SDK version, and note it in the changelog.

Complete example


  • Proactive triggers β€” Module reference: types, constants, built-in IDs, connector JSON schema.
  • Agent session states β€” SessionState v2 transitions, cooldown gating, and routing fields.
  • Intercom integration β€” quick_reply HTTP shape, delete-conversation helpers, connector LLM labels.
  • Typed payloads β€” SlimAction, ActionsPayload, SummaryPayload.