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:
Invalid rows (unknown
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
min_cycles is set at catalog instantiation time via the JSON row β it is not a runtime context_extra key.Result
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.Test-only key:
eval_now (Unix timestamp as float) β fixes the definition of βnowβ during unit tests so dwell duration is deterministic.Result
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: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
JSON config example
Quick comparison
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).