The implementation-level design for §3 of Live personas: how a persona may move first. Assembled from the products that ship it (Nomi's tiers and backoff, verbatim; Kindroid's judgment model and directives; Character.ai's away messages and their complaints; Replika's check-ins; 星野's 30-minute rule; Inworld's goal triggers), the research that measured it (ProactiveAgent's false-alarm metric, PaRT's 30-day A/B, Inner Thoughts, the proactive-dialogue taxonomy), the notification practice of the apps that live or die by it (Duolingo's published bandit, Braze/OneSignal caps), the plumbing limits (iOS web push), and one regulation that now governs it in China. Status: design — nothing built. Written 2026-08-18.
| Product | Mechanism, verbatim where possible | What we take |
|---|---|---|
| Nomi launched 2024-09-09 | Per-Nomi on/off + a tier: Very Frequent "if it has been over an hour since your last message" · Frequent "about 3 hours" · Normal "about a day" · Infrequent "about 4 days". Backoff: "if you do not respond, they will wait about double the time before they send you another message … longer times between each subsequent message." Quiet hours: "will not message you proactively between your local hours of 10pm and 8am." Notice: "will only mention that you have a message … will not display the message itself until you enter the app." Groups: "cannot yet proactively message you or each other." Content: "zero scripts … based on what they are actually thinking about or doing." | the dial's four notches, the ×2 backoff, quiet hours, content-free notice, never in groups — verbatim |
| Kindroid | "Away Proactive Actions" toggle (paid; ≤ 10 Kins; default ON at creation if < 3 AIs). The Kin will "analyze conversation patterns to determine appropriate outreach timing", choose message / voice / selfie / call, and "display thought bubbles showing their decision-making process" — purple bubbles also when it "decides to leave you alone for a while, but did so thoughtfully"; "appears at least after ~20 minutes of inactivity"; individual chats only. Free-text proactive directives "formatted as commands" — "Check in after calendar events when appropriate", "Do not send messages from 10pm to 8am". "Timing is approximate, not fixed"; "back-to-back messages decrease in frequency if unacknowledged"; SMS proactives stop "if you haven't texted your Kindroid in a while … too many AI sends will cause lines to be marked as spam." | a judgment model in front of the send (with a visible "decided not to" — honest and cheap); directives = our dial + the persona's own manner; the stop-when-ignored rule |
| Character.ai | "Receive messages while you're away" under Notifications; mobile; beta; "triggered by bots you've chatted with before"; no official article. Complaints: a bot with "no search history, no chat history, no warning" messaged first; messages "in unfamiliar languages from unrecognized characters". | the anti-pattern: a ping with no relationship and no reason |
| Replika | Notifications = "a message following up on a past conversation or just a check-in"; "Replika will remember what you talked about and keep the conversation going"; morning/evening preference; a Diary written about your chats. | "following up on a past conversation" — the proven content of a good first message |
| 星野 / 豆包 | 星野: leave mid-chat and "过了半小时没回复他,就会主动发消息" — off switch 头像 → 设置 → 关闭"智能体主动发消息". 豆包 companions took "作息" reminders ("最晚十一点左右提醒睡觉") before the 2025-07 takedown. 猫箱: characters "capable of initiating topics". | the 30-minute in-session nudge is the after-silence line, not a follow-up |
| Inworld (NPCs) | A goal's activation_condition = an intent and/or a trigger; repeatable; a client-sent trigger (e.g. initconvo) makes "the character start the conversation with the player first"; actions = an instruction or say_verbatim. No timed triggers, cooldowns or probabilities documented. | the shape of our cue: an instruction to the mind ("write one line to Dan about X"), never the words |
| Duolingo KDD 2020 | A bandit over reminder templates; reward = 1 iff a lesson is completed within 2 h of the reminder; per-template eligibility ("must have a 3+ day streak"); recency penalty ŝ − 0.017·0.5^(d/15 days) so the same copy isn't reused; softmax τ = 0.0025; sent at the hour you last practised. Result: DAU +0.5%, new-user retention +2%. Auto-stop copy: "These reminders don't seem to be working. We'll stop sending them for now." | a reward we can measure (a reply within 24 h), send at the human's usual hour, and the honest auto-stop |
| Work | Finding | Use |
|---|---|---|
| ProactiveAgent Tsinghua 2024 | Frames "should the agent offer help now?" as prediction from events + user activity + system state, judged by a reward model that reaches 91.8% F1 vs humans. Confusion matrix: TP proposed & accepted · FP proposed & rejected · TN silent & nothing needed · FN silent but needed; false-alarm rate = FP / (FP + TN). GPT-4o F1 64.6; GPT-4o-mini recall 100% at precision 35% — over-proposing is the default failure. | the exam metric for follow-ups: count TP/FP/TN/FN over a month; the false-alarm rate is the number that decides the dial's default |
| PaRT 30-day A/B, 2025 | Detects waning interest, retrieves personalised content, shifts topic; dialogue duration 296.9 s → 361.5 s (+21.8%). All in-conversation; nothing about pushing while away. | in-session initiative is worth something; it is a different feature (the after-silence line), measured separately |
| Inner Thoughts CHI 2025 | Triggers on_new_message and on_pause (~10 s); a motivation score over eight criteria with a silence-growth term 1.02^(turns quiet); speak only above a threshold; preferred 82% over next-speaker prediction. | the after-silence line's decision (see Many minds) |
| Generative Agents | Daily plan → hourly → 5–15-min chunks; each observation asks "should John react?"; a party invitation reached 13 of 25 agents and 5 came. | initiative comes from a plan + a memory of the other person — our open loop is the smallest such plan |
| Deng et al. IJCAI'23 · TOIS 2025 | Proactivity = "leading the conversation towards pre-defined targets": target-guided (topic shift), prosocial, non-collaborative, clarification, preference elicitation. | vocabulary; our follow-up is target-guided with a target the human set |
| Frequency practice Braze · OneSignal | Example caps "no more than one push per day and no more than three pushes per week"; quiet hours hold and deliver after the window; "more than a few messages per week can erode trust." | our caps: ≤ 1 per persona per human per day, ≤ 3 per human per day across personas, ≤ 7 per week |
| Acceptance vs annoyance | A controlled study of proactive chat messages welcome vs unwelcome: not found. The only data are the complaints (Character.ai) and the products' own dials. | we measure it ourselves (the false-alarm rate, the reply-within-24h reward) |
_world_cue() into the private chat between that persona and that human (the solo room the persona page opens; if none exists yet, one is created silently): "[FOLLOW-UP · Dan asked you on Thu to ask how the interview went. It is Fri evening; Dan is not here. Write ONE short line to Dan that says why you're writing, then stop.]" — the cue rides both channels like every world cue, so the producer and the prop master read it.followup=True — the one flag that lets it through someone_to_hear(). The presence gate exists so a room doesn't narrate to nobody; a follow-up is for the absent person by construction. Every other guard stays: the producer may HOLD (the null ends the cascade — a real veto), the fuse and the wake budget still count, kits are irrelevant (no kit in a private chat).userVisibleOnly means something must show), tag = the room so repeats collapse. Tapping opens the private chat.answered, the loop closes on the next reflection (the reward = 1). Silence → unanswered += 1, next wait doubles; three in a row → the persona stops until the human writes, and the memory page says so in Duolingo's words: "Warren has stopped following up for now."| Control | What we build | Borrowed from |
|---|---|---|
| the dial | On the persona's page, per persona: Follow-ups: off · rare (~4 days) · normal (~1 day) · often (~3 h). Default normal — but a follow-up needs an open loop, so a human who never leaves one never gets a ping. (Character.ai's default-on pinged people with no relationship; ours can't.) | Nomi tiers · Kindroid default-on-if-few |
| the account switch | Personas may message me first — on; turning it off zeroes every dial. Sits beside Personas remember me. | Character.ai "Receive messages while you're away" |
| quiet hours | 22:00–08:00 in the human's timezone (from the account locale; UTC if unknown); a due loop inside them waits for 08:00. | Nomi verbatim · Braze hold-and-deliver |
| the ledger | On the memory page, per persona: follow-ups sent, answered, held ("decided not to: …"), stopped. The judgment's why is the text. | Kindroid purple bubbles · Duolingo auto-stop copy |
| never into a group | v1: private chats only. A loop formed in a group is followed up in the private chat with its subject, never in the group. | Nomi · Kindroid (individual chats only) |
| Rule | Value | Source |
|---|---|---|
| a reason, or nothing | an open loop the human left or a promise the persona made; the line names it | ours — the market's #1 complaint inverted |
| the dial | off · rare ~4 d · normal ~1 d · often ~3 h; default normal | Nomi |
| backoff | wait ×2 per unanswered; 3 unanswered → stop until the human writes | Nomi · Kindroid · Duolingo |
| quiet hours | 22:00–08:00 local; hold, deliver after | Nomi · Braze |
| caps | ≤ 1 / persona / human / day · ≤ 3 / human / day · ≤ 7 / human / week | Braze/OneSignal examples |
| notice content | none — "left you a message" | Nomi |
| groups | never; the private chat only | Nomi · Kindroid |
| presence | not while the human is in the app (a room handles that); not to a human who has never talked to this persona | ours · Character.ai's complaint |
| judgment | a flash call, default hold, logged and shown | Kindroid · ProactiveAgent |
_world_cue → the drain → producer → panel), the 15-minute scheduler heartbeat, the presence gate, the private-chat solo room. New code: the scheduler's gates, the followup flag, the judgment call, the dial rows, the ledger on the memory page.userVisibleOnly: true — a push must show something, or the browser shows "this site has been updated in the background". Our content-free notice satisfies it.| Failure (where seen) | Guard |
|---|---|
| a ping with no relationship (Character.ai) | a follow-up needs an open loop → needs a memory → needs a prior conversation. Structural. |
| a ping with no reason ("hey, you there?") | the cue tells the panel to say why; the exam counts lines that don't |
| over-proposing (ProactiveAgent: 100% recall at 35% precision) | default hold in the judgment; the false-alarm rate on the dashboard; the dial's default is re-set from it |
| a loop already resolved ("how did the interview go?" — they told Nolan yesterday in a group) | the judgment reads the room's recent lines and the store; a closed loop never becomes a candidate |
| a wrong hour | quiet hours + the human's usual hour; timezone from the account |
| a persona that keeps going | ×2 backoff · 3-strike stop · daily/weekly caps · the account switch |
| a private thing in a push | the notice carries no content, ever |
| a follow-up in a group | private chat only, in code |
| narrating to nobody (the presence gate's job) | the followup flag is the only bypass and it names its recipient |
| # | Slice | What lands | Lens | Needs |
|---|---|---|---|---|
| 1 | due + state on loops | the reflection fills due; the store gains pings_sent / last_ping_at / answered | proven shape | the memory store |
| 2 | the gates + the judgment | the heartbeat computes candidates; one flash judgment each; the ledger rows; nothing sent yet (dry run, dashboard only, for a week) | proven shape | 1 |
| 3 | the delivery | the followup cue into the private chat; the content-free notice + push; the dial and the account switch on the pages | proven | 2 |
| 4 | the measure | reply-within-24h reward + TP/FP/TN/FN on the admin page; the dial's default set from the false-alarm rate after a month | harness | 3 |
| 5 | the after-silence line · wants | see Many minds §6 and Growth — one New at a time, after follow-ups have a number | new | — |