Triggers and notifications
How silent app events become proactive turns or notifications, and how delivery works when the app is in the background.
Your app already knows things the assistant should react to: the user walked into a store, a payment failed, an order shipped, a cart has been idle for an hour. Kletso turns those silent events into assistant behaviour, but only through rules you write.
The flow
- The app calls
track('geofence_entered', {'store': 'Shibuya'})(orscreen('checkout')). Nothing is posted in the chat. The event goes to the runtime over the open socket, or over HTTPS if none is open. The SDK also sends one event on its own:kletso.chat_openedwithmessages,userMessagesandconversationIdwheneveropen()shows the chat, which rules of kind opens the chat react to. - The runtime evaluates the project’s enabled rules. A rule matches on kind and name (
eventrules matchtracknames,screenandtimerules matchscreennames), is scoped to one environment or all, filters by audience (everyone, signed-in, anonymous), evaluates an optional condition overproperties,contextanduser, and applies a per-user frequency cap. A rule has one or more reactions. - Reactions:
- Notify: emit
app.notifywith a title, body, channel (banner,toast,alert,system,silent), and what a tap does (open the chat, run a local action, open a URL, send an agent value). - Turn: post a prepared assistant turn into the user’s conversation (for example a welcome with a store code and quick replies), so the chat has something to show when it opens.
- AI responds: run a hidden instruction through the agent loop, with the user’s context and all attached tools, so the model writes a personalised turn (for example recommendations when the chat opens). The instruction is never shown; the app sees only the assistant’s answer.
- Workflow: run a published workflow with the event as input (configurable today; dispatch from live events is not wired yet).
- Notify: emit
- The SDK shows the notification with
KletsoNotificationHost(banner or toast above your UI, alert dialog, or the OS tray through your notifier forsystem). A tap runs the configured target.
Delivery when the app is not open
If the notification’s channel is system, or the conversation has no live socket, the runtime looks for the user’s registered push token and delivers through your push account (Firebase Cloud Messaging today). The push carries the same app.notify envelope in its kletso data field; the app passes it to handlePushPayload, which shows it and deduplicates on notificationId, so a notification that arrives both live and by push renders once. For channels other than system the push is data-only and the app renders the banner, toast or alert itself.
APNs and Web Push are planned; see Roadmap.
Server-triggered notifications
Your backend can notify a user without any app event: POST /v1/notifications with the secret key, an end-user id and the notification. Same channels, same dedupe. See Notifications API.
Simulate before you ship
The dashboard’s Triggers page has a Simulate an app event tab: pick an event, edit the properties, fire it in the selected environment and watch the resulting app.notify and turn in the inspector.
Semantic conditions
An expression can only compare values the app sent. When the decision needs meaning (“is this message a complaint?”, “does this cart look like a gift?”), a rule can also carry a plain-language yes/no question judged by Jev, Kletso’s small decision model, with a probability threshold. It runs in a few hundred milliseconds on Kletso’s key and falls back to not firing when it cannot answer.
Things to keep in mind
- Rules run per environment, so a development build cannot spam production users.
- Prepared turns are scripted text and surfaces, streamed as if the model had answered; no model call is made and no tokens are spent.
- The delay field on a rule is stored but not applied yet.
silentnotifications run their target without any UI, which is how the server can pre-warm a conversation or navigate the app quietly (withallowServerCommands).