The SDK ships three built-in triggers you can enable without writing any detection code. Each one is registered in the built-in catalog and selectable viaDocumentation Index
Fetch the complete documentation index at: https://developers.autoplay.ai/llms.txt
Use this file to discover all available pages before exploring further.
integration_config.proactive_triggers.builtins in your products.json.
Need to write your own trigger? See Authoring proactive triggers.
How to enable built-ins
Add abuiltins array to integration_config.proactive_triggers. Each row must include id, name, and description β these are required non-empty strings used in logs and admin UIs.
evaluate_first returns the first matching trigger. Put higher-priority triggers earlier in the list.
Two optional per-row overrides apply to any built-in:
| Field | Default | Meaning |
|---|---|---|
interaction_timeout_s | catalog default | How long the proactive UI stays open waiting for the user |
cooldown_s | catalog default | Minimum gap before this trigger can fire again |
id, missing required fields) raise SdkConfigError and log event=proactive_builtin_spec_invalid.
Built-in catalog
canonical_url_ping_pong β URL hesitation
canonical_url_ping_pong β URL hesitation
What it detects
The user is bouncing back and forth between the same canonical URLs β a strong signal of hesitation, confusion, or indecision. The trigger fires after the URL sequence shows at leastmin_cycles complete back-and-forth cycles between the same pages.Example pattern that fires (min_cycles=1):Stable ID
Default registry
This is the only trigger included indefault_proactive_trigger_registry(). If you omit builtins entirely from your config, ping-pong is active by default.Tuning
| Parameter | Default | Meaning |
|---|---|---|
min_cycles | 1 | Number of complete back-and-forth URL repeats required before the trigger fires. Raise this to require stronger hesitation signals before firing. |
min_cycles is set at catalog instantiation time via the JSON row β it is not a runtime context_extra key.Result
| Field | Value |
|---|---|
trigger_id | "canonical_url_ping_pong" |
body | Default proactive copy (from DEFAULT_PROACTIVE_QUICK_REPLY_BODY) |
metadata.min_cycles | The min_cycles value used for this evaluation |
JSON config example
Scoping to a URL prefix
To limit ping-pong detection to a specific area of your product (e.g. only the/projects section), use ScopedCanonicalPingPongTrigger in code β this is not configurable from JSON.user_page_dwell β Page linger detection
user_page_dwell β Page linger detection
What it detects
The user has been on the same canonical URL for longer thandwell_threshold_seconds and has performed fewer than user_page_dwell_max_actions actions during that time. This distinguishes passive lingering (stuck, confused, reading carefully) from active exploration (clicking around, filling forms).The trigger only looks at the trailing run of recent_actions that share the same canonical_url as the latest action β it ignores earlier visits to the same page.Fires when:- The trailing URL streak spans β₯
dwell_threshold_seconds - The streak contains β€
user_page_dwell_max_actionsactions
Stable ID
Tuning
All tuning keys can be set inintegration_config.proactive_triggers (stock connector copies them into context_extra automatically) or passed directly in context_extra when building ProactiveTriggerContext in code.| Key | Default | Meaning |
|---|---|---|
dwell_threshold_seconds | 60 | Minimum seconds on the same canonical URL streak before the trigger can fire. Must be > 0. |
user_page_dwell_max_actions | 5 | Maximum number of actions allowed on the trailing URL streak. More actions than this β trigger does not fire. Invalid or β€ 0 values fall back to 5. |
dwell_proactive_body | (built-in short message) | Optional override for the proactive message body. Falls back to "Still on this page β want a quick tip?" if empty or omitted. |
eval_now (Unix timestamp as float) β fixes the definition of βnowβ during unit tests so dwell duration is deterministic.Result
| Field | Value |
|---|---|
trigger_id | "user_page_dwell" |
body | dwell_proactive_body override, or "Still on this page β want a quick tip?" |
metadata.user_page_dwell_seconds | Measured dwell duration of the trailing URL streak (rounded to 3 dp) |
metadata.user_page_dwell_action_count | Number of actions in the trailing streak |
metadata.user_page_dwell_max_actions | The effective user_page_dwell_max_actions used for this evaluation |
metadata.dwell_threshold_seconds | The effective dwell_threshold_seconds used for this evaluation |
metadata.user_page_dwell_canonical_url | The canonical URL of the trailing streak (truncated to 512 chars) |
JSON config example
section_playbook_match β Section-level guidance
section_playbook_match β Section-level guidance
What it detects
The user is in a part of your product (a βsectionβ) that has a matching entry in a guidance playbook you define. The trigger resolves which section the user is currently in, looks up the playbook, and fires with the section-specific copy if a match is found.This is the most configurable built-in β it lets you define custom proactive messages for different areas of your product without writing Python code.Stable ID
Configuration inputs
All inputs are passed viacontext_extra (or integration_config.proactive_triggers when using the stock event connector, which copies the keys automatically).section_url_rules β Map URLs to sections
An ordered array of { prefix, section_id } objects. The first prefix that matches the userβs current canonical URL wins. Put longer / more specific prefixes first.section_url_fallback_id (optional) β bucket ID for URLs that match no prefix. Defaults internally to "other" when resolving unmapped paths.section_playbook β Guidance copy per section
A dict mapping section_id to either a plain body string or a structured row:| Row format | Fields |
|---|---|
| Plain string | Used directly as the body |
| Dict | body or proactive_body for the message; reply_option_labels or quick_reply_labels for chips |
product_section_playbook β Section activity data (auto-computed)
When section_url_rules is non-empty, the stock event connector computes this automatically and attaches it to context_extra. It contains:runtime.current_section_idβ the section ID resolved from the userβs latest actionsections[section_id].visit_countβ number of times the user visited this sectionsections[section_id].dwell_seconds_per_visitβ list of floats, one per visitsections[section_id].first_visited_at/last_visited_atβ ISO 8601 UTC timestamps
Resolution order
When multiple sections could match, the trigger picks the section to use in this order:runtime.current_section_idif it exists insection_playbook(current page takes priority)- The section with the highest total dwell time across all visits, among sections that appear in both
product_section_playbook.sectionsandsection_playbook(tie-break:visit_count) runtime.current_section_idif it has a playbook row (fallback)
Result
| Field | Value |
|---|---|
trigger_id | "section_playbook_match" |
body | Body string from the matching playbook row |
reply_option_labels | Chip labels from the playbook row (empty tuple if not defined) |
metadata.section_id | The section ID that matched |
JSON config example
Quick comparison
| Trigger | Fires when | Key inputs | Zero-config? |
|---|---|---|---|
canonical_url_ping_pong | User bounces between same URLs | canonical_urls list | Yes β active by default |
user_page_dwell | User lingers on one URL with few actions | recent_actions, dwell_threshold_seconds | No β must add to builtins |
section_playbook_match | User is in a section with a playbook entry | section_url_rules, section_playbook | No β must add to builtins + configure playbook |
Related pages
- Proactive triggers β Module reference: types, constants, registry API, connector JSON schema.
- Authoring proactive triggers β Build custom triggers in code.
- Agent session states β FSM gating (
can_show_proactive_with_reason, idle expiry).











