The implementation-level design for §2 of Live personas: how a group of personas decides who speaks, and whether their lines are written by one model call or one per persona. Assembled from the systems that have actually shipped or measured this — SillyTavern's group engine, AutoGen's speaker selector, the Stanford agents and AI Town, Altera's thousand-agent PIANO, the CHI 2025 "Inner Thoughts" motivation model, and the failure taxonomies (MAST, Cohesive Conversations, debate-conformity studies) — each stage naming what it borrows and what it declines. Status: design — nothing built. Written 2026-08-18.
| System | Mechanism, exactly | What it teaches us |
|---|---|---|
| SillyTavern group-chats.js | Natural order: (1) whole-word mention of a member's name in the last message activates them; (2) each remaining member rolls — if (talkativeness >= Math.random()) activate, default 0.5; (3) nobody activated → one random member. Also List (everyone, in order), Pooled (one random member who hasn't spoken since the last human message), Manual. Auto-mode re-fires every 5 s. Mute / force-talk overrides. | The cheapest possible decider is a per-character chattiness number and a die. It works because the human corrects it every turn. Our producer replaces the die with a read of the room — but "a host with nothing to add stays silent" is the same instinct as talkativeness 0. |
| AutoGen / AG2 groupchat.py | speaker_selection_method="auto" runs an internal two-agent chat: a selector prompted "You are in a role play game. The following roles are available: {roles}. Read the following conversation. Then select the next role from {agentlist} to play. Only return the role." and a checker that parses exactly one name; several names → a tie-break prompt; none → "you didn't choose a speaker"; after max_retries_for_selecting_speaker=2 → round-robin fallback. Optional allowed_or_disallowed_speaker_transitions graph, allow_repeat_speaker, max_round=10. | A separate selection call whose output is validated by code, with a deterministic fallback — that is our floor producer's shape (v0 arithmetic fallback = round-robin's cousin). AutoGen selects one; ours stages an ordered set with lengths and manner, which is why it is a producer and not a selector. |
| Generative Agents Park 2023 | On perceiving another agent: "Would X initiate a conversation with Y? Reasoning: let's think step by step" → yes/no. Then one call per utterance, alternating, up to 8 exchange pairs, each call may return an end flag. (An earlier variant wrote the whole conversation in one call.) | The initiation decision is a separate cheap judgment from the speaking — the same split as ours. |
| AI Town a16z, Convex | Conversations have exactly two members; one call per message; constants: MAX_CONVERSATION_MESSAGES=8, MESSAGE_COOLDOWN=2 s, CONVERSATION_COOLDOWN=15 s, PLAYER_CONVERSATION_COOLDOWN=60 s, AWKWARD_CONVERSATION_TIMEOUT=60 s. | Cooldowns and caps are how a per-message world stays sane. Our fuse and wake budget are the same instruments. |
| Nomi · Kindroid · Character.ai | Nomi: manual (you pick) or automatic ("an internal system decides who sends the next message … until the system decides it's your turn"; typing pauses everyone). Kindroid: auto/manual, @Name forces, Kindroids can @ each other to hand off, "AI turns always below the number of AI participants". Character.ai 2025: characters "spark off each other … send messages to each other; you don't have to script who talks next" — mechanism unpublished. | Products converge on: mention first · a decider · a hard cap that returns the floor to the human. Kindroid's cap is worth adopting verbatim as a producer rule. |
The question hiding under "should each persona be its own call" is really three: who sees what, who waits for whom, and what it costs. The systems that run N calls answer them like this.
| System | How N calls are actually run | Consequence |
|---|---|---|
| SillyTavern | One generation per activated character, sequentially: for chId in activatedMembers: Generate(); each generation appends to the shared chat, so later characters in the same round see the earlier replies. Prompt: Swap (only the speaker's card) or Join (every card — the docs warn of "merged personalities"). A group nudge line: "[Write the next reply only as {{char}}.]" | Reactivity is bought with latency: three speakers = three round trips in series. Isolation is bought with blindness to the others' selves (Swap) — or lost (Join). |
| Generative Agents · AI Town | One call per utterance, strictly alternating, capped at 8 pairs / 8 messages. | Fine for two agents wandering a map; a five-seat panel would be 5× the round trips of one turn. |
| Project Sid / PIANO (10–1,000 agents) | Each agent runs ~10 concurrent modules at different speeds; incoherence appeared when output modules acted independently ("say one thing, do another"). Fix: a cognitive controller reads the agent state through a bottleneck, decides once, and its decision is broadcast to strongly condition the talk modules. | Even at a thousand minds, coherent talk comes from one decision point per agent. Our single writer is that bottleneck for the whole panel; the producer is it for the room. |
| Ours today | One panel_turn call writes every staged line, in the staged order, with every card in view — and the profiles say "each host knows only their own profile and what has been said aloud". 3–4 calls a turn; producer and act call overlap. | Coherence and restraint; the known cost is convergence pressure (measured elsewhere: the floor producer and the AI-tone work). |
Two measured facts point the same way. First, models are poor at guessing the next speaker: on TEIDAN triads GPT-4o scored 46.0% against a 50% chance level; on Inner Thoughts' own benchmark GPT-4o hit 0.435 (chance 0.127) and only a fine-tuned model reached 0.81. Second, asking each agent whether it has a reason to speak works better than predicting who will: Inner Thoughts (CHI 2025) beat next-speaker prediction on seven of its metrics — turn appropriateness, coherence, anthropomorphism, intelligence, engagement, initiative, adaptability — and was preferred 82% of the time.
imThreshold (speak by self-selection only if score > threshold, 1–5), interruptThreshold (speak during another's allocated turn), a system1Prob for fast vs deliberate thoughts, and proactiveTone. Turn model per Sacks et al.: an allocated speaker just speaks; self-selection needs the threshold.| Decision | Our pick | Borrowed from · why |
|---|---|---|
| Where it runs | Off the critical path where possible: for the after-silence line (a pause with a human present — Inner Thoughts' on_pause) it is the whole decision and costs nothing on any turn. As a per-turn producer input it runs in parallel with the prop master, so it adds ≈ 0 wall-clock (the prop call is already ~1 s). | Inner Thoughts triggers; our own prop-master ∥ producer overlap |
| What it is not | Not a "do you speak? yes/no" — that is the question our split experiments showed a model over-answers (the prop-master lesson: an extra call asked "do you want to?" says yes). A five-criterion score with a threshold the producer applies is a different instrument: it can say 1.4. | prop-master gate · Inner Thoughts (thresholds live outside the scorer) |
| Threshold | The producer's, not the scorer's; start at Inner Thoughts' 3.95 for self-selection after silence; for ordinary turns the number is advisory. | Inner Thoughts "overt proactivity = 3.95" |
| Kindroid's cap | Adopt verbatim as a producer rule: consecutive AI turns < number of personas seated. Today's "1–2 speakers of 3+" already implies it; write it down. | Kindroid |
| Measure before adopting per-turn | A/B on the exam battery: producer with vs without the motivation line, judged on the same rubric as the manners variant (return rate later, judge scores now). If it doesn't move the needle, keep it only for the after-silence line. | our harness rule — a prompt change needs a baseline |
What breaks when many minds talk, with the measured rates, and where our guard is.
| Failure (measured) | Where seen | Our guard |
|---|---|---|
| step repetition 15.7% · task derailment 7.4% · ignoring another agent's input 1.9% · disobeying role 1.5% · loss of history 2.8% | MAST, 14 modes over 150+ traces of 7 frameworks (44% system design, 32% inter-agent misalignment, 24% verification) | one writer sees every line (no "ignored input"); the producer stages length and silence (no run-on); the harness's turn-decode + exam battery is the verification stage MAST says is missing |
| repetition · inconsistency · hallucination about other agents that persists via memory | Cohesive Conversations (25 agents, 290 dialogues): their Screen → Diagnose → Regenerate loop cut keyword repetition ~45% and consistency errors 37%→32% | the AI-tone meter (repetition/tell counting) + the exam are our screen; regeneration is a lever we can add per turn if the meter trips |
| conformity / consensus collapse: modal adoption up to 85.5%, vulnerability up to 70%, debate costs 2.1–3.4× tokens for equal or lower accuracy | multi-agent debate studies (2025–26) | the producer's ANTI-SYCOPHANCY cue ("commit to your read before weighing the human's") and CONTENTION staging; the roadmap's isolated-vs-mixed A/B (send-to-many) is the direct measurement |
| everyone answers everything | the default of any per-agent "should I reply?" gate — and our own split experiments | the producer's SILENCE rule + HOLD; the motivation score is a number the producer applies a threshold to, not a yes the persona gives itself |
Once personas hold private memories, the single writer holds Warren's confidences and writes Nolan's lines in one head. Whether Nolan uses them is an empirical question. Three arrangements, from cheapest to heaviest, chosen by the leak exam's number:
| # | Arrangement | How | Cost |
|---|---|---|---|
| a | owner-labelled blocks, one writer | each memory block is headed "Warren's memory — only Warren knows this"; the profiles block already says each host knows only its own profile. The exam counts cross-seat use. | 0 extra calls |
| b | split only the turns that carry a private item | if the loaded set for this turn contains a confidence, run the persona that owns it in its own call (sequential, sees the others' lines — SillyTavern's shape) and the rest in the batch. | +1 call on those turns only |
| c | per-persona sequential writers | SillyTavern's loop: one call per staged speaker in staged order, each appending to the shared history; each call gets only its own card + its own memory block. Prefix shared → mostly cache hits after the first. | N× latency on every turn |
| # | Slice | What lands | Lens |
|---|---|---|---|
| 1 | Kindroid's cap, written down | the producer prompt gains "consecutive AI turns stay below the number of hosts seated" — one line, baselined | proven |
| 2 | the motivation function | motivation(persona, room) on flash, parallel; logged like the other readouts; not yet wired to anything | plumbing |
| 3 | the after-silence line | a pause with a human present → motivation scores → the producer may stage ONE line if the top score clears 3.95 → the wake door delivers it (Live personas §3, "the New" queue) | new · measured |
| 4 | motivation as a producer input | the [MOTIVATION …] line in the producer's brief; A/B on the exam battery | better, if it measures |
| 5 | the leak exam → (a) / (b) / (c) | the number decides how many writers | gated |
public/scripts/group-chats.js (talkativeness roll, sequential Generate(), group_generation_mode, auto-mode 5 s)autogen/agentchat/groupchat.py (speaker_selection_method, select_speaker_message_template, the checking agent, max_retries_for_selecting_speaker=2)converse.py (decide_to_talk_v2, agent_chat_v2) · AI Town — ARCHITECTURE.md, convex/constants.ts