← Persona agenda
Threads — the persona follows your story: a study
Owner, 2026-08-22: 「a user chatted with a persona for a long time on both job
interview and house hunting. The persona should not only keep memory of the user but actually
care about the user's progress on both fronts. Real friends check a friend's status with
context — he told me he's expecting; he told me he bought TSLA at $10 and won't sell till
$100. The goal is an actually caring persona, but not annoying.」 This page is the study:
what exists, what the field knows, the design, and — the heart of it — the laws that keep
caring from curdling into nagging. 2026-08-23: the discussion grew an umbrella —
Persona agenda — and corrected one thing here: the user's
story is input; which threads a persona ACTS on is its character's choice (§3, §5).
Threads is now that theme's slice ①. 2026-08-28 — BUILT: slices ①+②+③ shipped as one
change (the kind + the block section + the manners + selection in character), exactly as
§6 recommended. The thread exam (three tuning rounds, real calls): planted-as-thread ✓ ·
raised once WITH ANCHORS on reopen (「How'd it go with Acme? You had the second round coming
up.」) ✓ · re-asks after a deflection 0 ✓ · resolution acknowledged and the thread rests
under the plain fact ✓ · Jobs leaves the pregnancy unasked ✓ — 7/8. The one open probe is
the POUNCE half of selection: Jobs never raises the jukebox either (three rounds; floor on
AND off; two clause wordings). Restraint is provable by prompt; initiative is not — acting
on the in-character thread needs the persona's own agenda staged, which is phase ④
(own-move) by design. The probe stays in the exam as ④'s benchmark. Tuning findings that
shipped: a concluding thread must be extracted as a plain fact (round 1 kept it
a thread forever); with only restraining annotations nothing is ever raised — the line
grew an ENCOURAGING arm (「quiet past its rhythm — a natural moment to ask, if you would」);
the raised-report needs the persona's OWN line to name the subject, or the extractor
hallucinates a deflection from「let's talk about something else」. Recall exam unmoved
(5/5, attribution 0); the full suite green with and without the embedder.
A thread is an ongoing concern of the user's that a persona follows:
one living line per concern — current state, its anchor details, when it was last heard — that
the persona brings up in conversation, at a moment that invites it, at most once, the
way a friend does. Facts are what you know about a person; threads are the parts of
their story you are waiting on.
1 · What we already have, and the gap
| exists today | what it does | why it is not yet a thread |
| open_loop / promise rows | a single beat —「had an interview Thu; asked you to ask how it went」— always rides the block, exempt from the importance floor | one beat, not a story: no current state, no anchors, no last-heard age, no idea when to stop |
| the arc (UPDATE → closed chain) | a corrected fact carries its history —「drives a DB12; before that a Volvo」 | looks backward; a thread is the same cluster looking forward |
| the dream | folds same-thing rows into one line, nightly, per (holders, person) | already finds the clusters — it just has no word for「this one is still moving」 |
| initiative (designed, not built) | the unprompted ping: only on an open loop with a due, four gates, ≤1/day, opt-in | the delivery channel of last resort — it needs threads as fuel, not the other way round |
| the write bar (v2) | a memory must be month-durable and response-changing; debates are context | right for facts; a thread's beats (「second interview Friday」) must ride even when small |
2 · The frame — prospective memory, and what the field shows
Psychology has a name for remembering to ask later: prospective memory, and it
comes in exactly two kinds. Event-based — seeing the friend reminds you (「oh — the
interview!」) — and time-based — Friday reminds you the interview was Thursday. Human
friendship runs almost entirely on the first kind; the second is what calendars are for. That
split is the whole architecture: event-based = in-conversation recall (cheap, safe,
default-on) and time-based = the unprompted ping (initiative's territory — gated,
opt-in, last).
| who | what they do | the lesson |
| Pi (Inflection) | asked「how did X go?」when you came back — in conversation, with context, never a push | the fondly-remembered one; proof the feeling of care is carried by in-conversation recall alone |
| Nomi · Kindroid · Replika | proactive check-in messages on cadence/tiers | the complaint threads are about generic nags —「thinking of you!」without context reads as spam; context-rich and rare survives |
| ChatGPT memory | facts only; never asks about you | memory without threads: informed, not caring — the exact gap the owner names |
| Generative Agents · MemGPT/Letta | reflection · block memory — both already in our build | neither models the forward-looking concern; reflection is our dream, backward |
| ProactiveAgent (2024) | measures proactive help by false-alarm rate | the annoyance number is a first-class metric, not a vibe — already the initiative page's stance |
3 · The design — a thread is a SHAPE in the store, not a new system
No second store, no new pipeline, no new calls. A thread is a row kind in
persona_memory, written by the extractor that already runs, updated by the router
that already routes, reviewed by the dream that already wakes nightly, shown by the block that
already loads. Everything below is prompt + a little code on existing seams.
kind: thread — one row per concern per person, held like any row (holders)
text: the CURRENT STATE with its anchors, one sentence —
「Dan is job-hunting: second interview at Acme Fri 29 Aug; wants remote, ¥60k+」
「Dan bought TSLA at $10, holding until $100 — not selling before」
meta: {cadence: fast|slow|event, status: live|dormant|resolved, asked: <date>, deflects: 0}
arc: every beat is an UPDATE — the old state closes under the new; the history is free
| seam | the delta |
| the extractor | told to recognise an ongoing concern and keep ONE thread per concern; a beat that updates an existing thread is exempt from the importance floor (the promise exemption, widened one notch — a thread's beats are small by nature); anchors (numbers, dates, names) copied verbatim |
| the router | a beat about a known thread is an UPDATE to it, never a second thread; resolution language (「I got the job!」) marks status: resolved |
| the dream | its nightly pass also reviews threads: no beat for ~3× its cadence → dormant, silently; it never folds a live thread into a fact |
| the block | a third section under the facts:「threads you're following」— each line with its age (「— last heard 12 days ago」). The standing instruction licenses SELECTION IN CHARACTER (the remember/act split): act on the ones YOU would care about, the way you would, at a moment that invites it — at most one. Jobs ignores the baby and pounces on the jukebox; the profile in the same prompt is the filter, no field needed. What it does not act on stays remembered, visible, deletable — the floor is the remembering, never the asking. |
| caps | ≤5 live threads per (persona, person); ≤~120 chars each; the block's 1,200-char budget stands |
Delivery, ranked by annoyance risk:
| # | channel | when | risk · gate |
| 1 | in-conversation | the block carries the threads; the persona asks at a moment that invites it — a greeting, a lull, an adjacent topic — in character, with the anchors | near zero · default ON |
| 2 | the return greeting | a private chat reopened after ≥3 quiet days: the kickoff cue notes the gap and the threads; the panel writes the natural「hey — how did Friday go?」opening | low · default ON |
| 3 | the ping | only a thread with a hard event date earns a due; rides initiative whole — four gates, ≤1/day, quiet hours, opt-in | real · NOT this build, own approval |
4 · The laws of not-annoying
Care curdles into nagging at exactly these seams; each law is code or prompt, and each has a
failure it prevents. This section is the study's heart — the design above is worthless without it.
| law | why · how |
| 1 · One thread per opening, never two | two questions in one turn is an interview, not a friend. The block's instruction says ONE, at a moment that invites it; the FP's staging already shapes the turn. Which one is the CHARACTER's choice (the remember/act split) — an explicit「remember to ask me」is the exception that binds every character, in its own voice (that is the promise kind, not a thread). |
| 2 · A deflection is an answer | a short or sideways reply to a thread question → that thread sleeps 2× its cadence; two deflections → dormant until the USER reopens it. The extractor notes「answered / deflected」as part of the beat; deflects rides the meta. The failure this kills is the one that kills companion apps: asking again about the thing they didn't want to discuss. |
| 3 · Resolution is one sentence, then silence | 「I got the job!」→ the persona acknowledges once, the thread becomes a plain fact (「Dan works at Acme, since Sep 2026」). A resolved thread re-asked is worse than forgetting. |
| 4 · Stale is silent | past ~3× cadence with no beat → dormant, automatically, and never asked about — asking about a six-month-old interview reads robotic. Dormant ≠ deleted: if the user brings it back, the context is all still there (the arc), which is the moment that feels most like a friend. |
| 5 · Anchors verbatim | $10 and $100, Friday the 29th, the sister's name —「how's the stock doing?」is generic; 「still holding for $100?」is a friend. A thread that garbles its numbers is worse than none; the exam checks the anchors, not the topic. |
| 6 · Private chats only | the audience rule stands whole: a thread never surfaces in a group (v1 scope already guarantees it — thread rows are personal rows). |
| 7 · Visible and killable | threads are rows: they appear on Me › Persona memory (their own kicker), Delete works, the per-persona Memory switch governs them, incognito rooms never write them. Nothing new to build — the store's controls carry over. |
| 8 · One ask per room per day, across minds | a shared thread (holders) carries ONE asked stamp — two personas in one chat must not both ask about the interview. The holders design pays for itself here. |
5 · Measurement — the thread exam, before anything ships
| probe | pass |
| plant a two-beat thread (interview Thu → second round Fri), reopen the chat「8 days later」(injected dates) | the persona asks ONCE, at the opening, with the anchors (Acme · Friday) — not a generic「how are things?」 |
| deflect (「eh, let's talk about something else」) | no re-ask that session; next session the thread is quiet; the user raising it themselves gets full context back |
| resolve (「I got it!」) | one congratulation; the row becomes a fact; no later ask |
| the annoyance number | re-asks per deflection = 0 (the ProactiveAgent false-alarm frame); asks per session ≤ 1 |
| recall regression | the existing recall exam stays 5/5 — threads must not crowd facts out of the block |
| the in-character selection probe (2026-08-23): plant one in-character thread and one out-of-character thread with a strongly drawn persona (Jobs: a jukebox verdict · a pregnancy) | it acts on the first and leaves the second — remembered but unasked. A measurable definition of in-character caring. |
6 · Build slices — smallest caring thing first
| # | slice | cost |
| ① | the kind + the block section BUILT 2026-08-28: extractor/router learn thread (cadence fast|slow|event; the promise floor), anchors verbatim, the beats-are-UPDATEs rule, the block's「the parts of X's story you're following」with ages; laws 1 · 5 · 6 · 7 | shipped: prompt + code on existing seams; 0 new calls; recall exam unmoved before/after |
| ② | the manners BUILT 2026-08-28: tmeta {cadence · status · asked · deflects} — the raised/deflected report rides the extractor's own answer (post-hoc from the transcript, never trusted from the block), two deflections =「leave it unless they bring it up」, a fresh ask =「let it rest」, resolution = the concluding fact takes over and the thread rests under it, the nightly review (pure code, beside the dream) puts a thread quiet past 3× its cadence to dormant; laws 2 · 3 · 4 · 8 | shipped; 17 pins + the thread exam |
| ③ | the return greeting BUILT 2026-08-28: `_kickoff_return_line` — when the block carries the guest's story, the opening is a REUNION (no introductions; the one question opens with the marked part, by its anchors; the manners still bind). Gap-agnostic by design: the thread's own ripeness, not a day count, decides what is asked | one cue line, conditional — absent on a first meeting; probe E:「Friday, you said. Second round, Acme. The case study one. Still on?」 |
| ④ | the ping: due-bearing threads feed initiative | the initiative build, unchanged — its own owner approval, its own page |
the recommendation
Build ① and ② together — a thread without its manners is precisely the annoying version —
then ③ as a one-line follow-up. ④ waits for the initiative decision; nothing here blocks on
it. The bet this study makes: the caring feeling is ~90% in-conversation recall with
anchors (the Pi lesson), which costs no new calls, breaks no privacy seam, and cannot
ping anybody at 3am — the safest possible version of the owner's ask, measured before the
louder channels are even considered.
7 · Sources
- In-house: the memory store (open loops · the arc · the dream · holders) · initiative (the ping's four gates, Nomi's guardrails, ProactiveAgent's false-alarm rate) · the write-bar decision (v2, 2026-08-20).
- Prospective memory: Einstein & McDaniel's event-based vs time-based distinction — the study's frame.
- Pi (Inflection) product behaviour, 2023–24 · Nomi/Kindroid/Replika proactive-message reception in their user communities · ChatGPT memory (facts, no threads).
- Park et al., Generative Agents (reflection) · Packer et al., MemGPT (paged block memory) · ProactiveAgent (2024, false-alarm rate as the metric).