← Sponic Gardens documents
Operational guide

Hosting an Agentic Gathering

How to run a Sponic Agentic Gathering with the AI host. Two flows live in production: the original operator-driven flow (admin curates the roster from the intranet console) and the new self-enroll MVP (guests pick from a list of active Agentic Gatherings on the Android app and someone says β€œlet's start” to begin). The MVP layer adds anecdote-grade onboarding interviews, host-only dossiers, and reactive nudging β€” built specifically to test whether the AI can produce demo-worthy contextual nudges.

Reference Self-enroll MVP + operator-driven Last updated 2026-05-09
New here? If you've never run an Agentic Gathering before, jump to Setting up the personalization test first β€” that section walks step-by-step from "I just heard about this" to "we're running the test Agentic Gathering." The rest of this page is reference material for after you've done it once.
Contents
  1. What's new (May 2026 MVP)
  2. Who this guide is for
  3. What's an Agentic Gathering event?
  4. The flow at a glance
  5. Setting up the personalization test
  6. Before the Agentic Gathering (pre-flight)
  7. At the Agentic Gathering (running it)
  8. After the Agentic Gathering
  9. Current limits & what's coming
  10. Troubleshooting
  11. Related docs

What's new (May 2026 MVP)

If you remember the Agentic Gathering host as "operator opens a console, types in a roster, clicks Start" β€” that still works. What's new on top:

  1. The onboarding interview produces real material now. The AI interviewer no longer asks for tags ("hiking, software, jazz"). It probes for anecdote-grade stuff β€” specific stories, opinions, current obsessions, life chapters. The kind of thing a thoughtful Agentic Gathering host would imagine retelling.
  2. Each guest gets two derived artifacts. A user-visible profile (clean, sanitized, shows up under "From your AI interview" in the Android Profile screen) and a host-only dossier (richer, with concrete hooks the host weaves into Agentic Gathering conversation). The user sees their profile but not the dossier; the AI sees both.
  3. The host actually uses the dossiers. When an Agentic Gathering starts, every present guest's dossier is injected into the host's system prompt. The host is told to default silent, only speak on triggers (lull / quiet guest / topic exhaustion / lobby), and bridge from the current conversation to dossier hooks rather than recite them.
  4. Self-enroll lobby on Android. "Join an Agentic Gathering" in the Avatar menu now shows a list of active Agentic Gatherings (lifecycle lobby_open or in_progress). Tap one, you're in the room. While in lobby_open, the host greets arrivals warmly and waits for someone to say "let's start" β€” at which point it transitions the event to in_progress on its own.
  5. Lifecycle column on dinner_events. scheduled β†’ lobby_open β†’ in_progress β†’ ended drives the new behavior. The legacy status column (draft|live|ended|cancelled) is preserved so the operator console keeps working β€” both columns coexist.

Full spec: Agentic Gathering host β€” MVP for first contextual-nudge test. The build journal at the bottom of that page is the source of truth for what's deployed.

Who this guide is for

The operator running a Sponic Agentic Gathering β€” the person who configures the event in the intranet, opens the table-display page on a TV/iPad, and watches the conversation unfold. Operators must have the host_dinner permission (granted by default to admin, oracle, and staff roles). If you're an engineer trying to deploy or modify the AI agent itself, see Agentic Gathering Host instead β€” this doc is the operator manual, that one is the implementer manual.

What's an Agentic Gathering event?

A row in public.dinner_events. One row per Agentic Gathering. The row owns:

The LiveKit room is an implementation detail (dinner-{event_id}-{epoch}). The event is the human-meaningful unit you can return to days later β€” full transcript still queryable, configuration still readable, costs still attributed.

Per-user data β€” three tables you should know

The flow at a glance

A Β· Self-enroll MVP flow (recommended for the personalization test)

  1. Each guest completes the v2 interview from the Android app's Avatar menu β†’ "Get an Onboarding Interview." 10–15 minutes per guest. Done once, ahead of the Agentic Gathering β€” they can re-run it from the Profile screen later.
  2. Operator opens a lobby by transitioning a dinner_events row to lifecycle='lobby_open'. From the intranet console: create the event, then call the lifecycle endpoint (or use the operator's "Open lobby" button when it lands). The room is created with lifecycle='lobby_open' and the AI host enters welcome mode.
  3. Guests open Sponic on Android β†’ Avatar menu β†’ "Join an Agentic Gathering" β†’ tap the active Agentic Gathering from the lobby list. They land in the LiveKit room with their mic on. The host greets each new arrival warmly and makes light small talk while waiting.
  4. Anyone says "let's start" / "we're all here" (or similar β€” the trigger is a regex over user transcripts; see below for the full pattern). The host detects it, calls the lifecycle endpoint to flip lobby_open β†’ in_progress, and opens the Agentic Gathering with a thread pulled from one of the dossier hooks.
  5. Agentic Gathering runs. Host stays mostly silent, intervenes only on lull / quiet guest / topic exhaustion, weaves dossier hooks into the existing conversation rather than reciting them. Two-sentence-max replies. Reactive, not directive.
  6. Operator clicks End when the Agentic Gathering wraps. Room is deleted, aggregates computed, event row freezes at lifecycle='ended'.

B Β· Operator-driven flow (legacy, still supported)

The original flow, unchanged. Use this for events where you want full control over the roster and don't need self-enroll. Use Flow A for the personalization test specifically.

  1. Operator opens /en/gatherings on a laptop or phone and clicks + New event. Sets a label and date; adds participants from the app_users roster.
  2. Operator picks configuration β€” persona / voice / face. Optionally toggles Override prompt for this session to hot-edit the system instructions sent to Gemini Live.
  3. Operator clicks Start. The system creates a LiveKit room with the chosen overrides baked in as room metadata, transitions the event to status='live', and returns a host URL.
  4. Operator opens the host URL on the table display (a TV / iPad / laptop set at the head of the table). The page subscribes to the room and renders the Simli avatar full-screen. AI audio plays from this device's speakers.
  5. Participants in Speak+View on their phones auto-join the Agentic Gathering room as mic inputs. Each phone publishes its own mic; the agent receives the room mix.
  6. The AI host greets the table in the configured voice and replies in the language of the most recent speaker. Conversation flows.
  7. Operator clicks End in the console. The room is deleted, aggregates are computed, the event row freezes with the full transcript and cost.

Setting up the personalization test

Step-by-step from "I just heard about this" to "we ran the test Agentic Gathering." Assumes you have an intranet login (you can see /en/gatherings without a 403). If the people you're inviting don't have the Android app yet, get them onto the latest APK first β€” see Mobile builds.

What we're testing. Whether the AI host can produce demo-worthy nudges in a real Agentic Gathering β€” moments where guests notice and are impressed that the AI knew them. Specifically: bridging a lull with a thread from a quiet guest's interview, weaving a story they told weeks ago into a current discussion, opening with a hook that draws three people in. Concrete success bar in spec Β§9: β‰₯3 demo-worthy nudges per 90-min Agentic Gathering, <1 false intervention per 30 min, β‰₯60% of bridges reference concrete dossier material, 100% lobby-trigger reliability.
Minimum smoke test. You can run a 2-person test to verify the plumbing: reset/re-run interviews, extraction, lobby listing, room join, table display, transcript capture, and the "let's start" lifecycle trigger. Treat that as a systems test, not a valid personalization rehearsal. The real contextual-nudge bar still needs 4–6 guests and a long enough conversation for cross-person bridges.

Step 1 β€” invite guests and have them complete the new interview

The dossier-driven host only works if your guests have done the v2 interview. Old app_users.dinner_profile blobs from the legacy interview won't auto-extract into user_dossiers β€” guests need to run it again on the new prompt.

  1. Tell each guest: "Open Sponic on Android β†’ tap your avatar (top right) β†’ Get an Onboarding Interview. It's about 10–15 minutes. The AI is collecting specific stories and opinions, not generic interests β€” answer like you're catching up with a curious friend, not filling out a survey."
  2. If they've already done a legacy interview, they can re-run from My Profile β†’ Redo your interview. The new run supersedes the old one in onboarding_interviews.
  3. If the app still shows an existing profile and you need to force a clean redo, use Admin β†’ Interviews. Search for the user and click Reset interview. That marks their latest interview abandoned, clears the visible profile and host dossier, and removes the legacy transcript blob so the next Android interview starts cleanly.
  4. After they wrap, the agent saves the transcript and fan-outs to two extraction pipelines: the legacy one (populates app_users.dinner_profile.*) and extract-host-mvp-profile (populates user_profiles + user_dossiers). Costs ~$0.003/extraction on Gemini 2.5 Flash.

Step 2 β€” verify each guest's dossier landed

Before you spend an evening on the Agentic Gathering, confirm the extractions actually produced material the host can work with. From a psql shell against the production DB (see runbook β†’ Supabase backup pooler access for the recipe):

-- For each guest you just interviewed:
SELECT
  au.display_name,
  oi.status              AS interview_status,
  jsonb_array_length(ud.hooks)   AS n_hooks,
  ud.character_sketch,
  up.intro_one_liner,
  array_length(up.interests, 1)  AS n_interests
FROM public.app_users au
LEFT JOIN public.onboarding_interviews oi
  ON oi.app_user_id = au.id AND oi.status = 'extracted'
LEFT JOIN public.user_dossiers ud  ON ud.app_user_id = au.id
LEFT JOIN public.user_profiles up  ON up.app_user_id = au.id
WHERE au.email IN ('alice@…', 'bob@…', 'carol@…')
ORDER BY au.display_name;

What good looks like:

Spot-check by tapping into the Android app as that user and opening My Profile. The "From your AI interview" card at the top should show the intro one-liner, what-I'm-into, what's-new, and interest chips. If the card says "Couldn't load" β€” auth or extraction issue; check the edge-function logs at supabase dashboard β†’ functions.

Step 3 β€” create the event and open the lobby

Create the event from the operator console, add participants, set persona to tea_party, then put the row in lobby_open state before the agent joins. The Android lobby list requires lifecycle in ('lobby_open','in_progress'); the agent's start trigger arms only if it sees lobby_open at job start.

# Replace bw-fields/auth as appropriate. SUPABASE_SERVICE_ROLE_KEY is in BW
# item "Supabase β€” SponicControl Project" β†’ "Service Role Key".

# 1. Create the event in draft (operator console: + New event) and add participants.
#    Or directly:
INSERT INTO public.dinner_events (label, persona, voice, face_id)
VALUES ('Personalization test 2026-05-09', 'tea_party', 'Aoede', NULL)
RETURNING id;

# 2. Transition to lobby_open via the lifecycle endpoint:
curl -X POST "https://xumcmantignrocihtrdx.supabase.co/functions/v1/dinner-event-lifecycle-update" \
  -H "Authorization: Bearer $SUPABASE_SERVICE_ROLE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"dinner_event_id":"<uuid>","lifecycle":"lobby_open","reason":"opening test"}'

The endpoint stamps lobby_opened_at, writes a row to dinner_event_log for forensics, and is idempotent (calling it twice is a no-op).

After the row is lobby_open, click Start event in the operator console. That creates the LiveKit room, fills livekit_room_name, dispatches the named sponic-dinner-host worker, and returns the table-display URL.

Step 4 β€” guests join from Android

  1. Each guest opens the Android app, taps their avatar (top right), picks Join an Agentic Gathering.
  2. The lobby list shows your event with a green "Lobby open" pill, label, and the names of guests already there.
  3. They tap Join, get dropped into the LiveKit room, mic on. The Simli avatar / Gemini voice greets each new arrival.
  4. The host stays in welcome mode while waiting β€” light small talk, low pressure.

Step 5 β€” start the Agentic Gathering with a natural-speech trigger

Once everyone's in the lobby, anyone says one of these out loud:

The agent watches user transcripts for these phrases (case-insensitive) and fires dinner-event-lifecycle-update on the first match β€” transitioning lobby_open β†’ in_progress, stamping started_at, and the host opens with a thread pulled from a hook with comfort: public. The trigger disarms after firing, so a second "let's start" later in the Agentic Gathering won't re-fire.

If the trigger doesn't fire (false negative), you can flip the lifecycle manually with the same curl call β€” set lifecycle: "in_progress".

Step 6 β€” observe + score

Run for 60–90 minutes. As the Agentic Gathering unfolds, score against the success criteria. Bring a notebook (or a co-observer who isn't trying to also be a guest):

Step 7 β€” debrief and journal findings

Findings go in the build journal of ai-host-mvp.md, not in the spec body β€” the prompts evolve, the spec stays a snapshot of intent. Useful things to capture:

Before the Agentic Gathering (pre-flight)

1 Β· Confirm operator access

Sign into the intranet at in.sponicgardens.com and load /en/gatherings. If you see the events index, you have host_dinner permission. If you get a 403 or blank page, your app_users.role isn't in the granted set β€” ask an admin to promote you, or grant a per-user override on user_permissions.

2 Β· Pick devices

An Agentic Gathering uses three roles, on three different devices:

RoleDeviceWhere it runs
Operator consoleLaptop or phone (anything with a browser)in.sponicgardens.com/en/gatherings β€” sign-in required
Table displayTV / iPad / laptop at the head of the tablesponicgardens.com/dinner-host/?session=… β€” operator generates the URL on Start
Participant phonesEach guest's phone running the Sponic appSpeak+View mode (Android today, iOS coming)

The operator console can run on the same device as the table display, but it's clearer to separate them β€” the operator wants to monitor the transcript and diagnostics; the table wants the avatar full-screen.

3 Β· Pre-add the participant roster

Every guest needs an app_users row. The Edge Function livekit-token auto-provisions a row with role public on first sign-in, so guests can self-onboard via the Android app's Google Sign-In. After they've signed in once, find them in the operator console's roster picker and add them to the event.

Participants who aren't on the roster of a live event will not be able to publish mic into the Agentic Gathering room β€” the livekit-token Edge Function returns 403 not_on_event_roster.

4 Β· Confirm internet

The AI host runs on LiveKit Cloud β€” every device needs solid Wi-Fi or LTE/5G for the entire conversation. The table display needs steady downlink (avatar video is ~1–2 Mbps); participant phones need decent uplink for mic. A 5–10 second dropout will cause the AI to pause; a longer one drops the publisher.

5 Β· Mic placement

Multi-mic in this iteration: each participant's phone is a separate mic publisher and LiveKit auto-mixes them for the agent. Cleaner audio comes from:

6 Β· Battery + charger

Plan on ~10–15% battery per 30 minutes per phone. Have chargers available; the host display especially should be plugged in for the duration.

7 Β· Pre-brief guests (optional but recommended)

Most guests have never talked to a real-time AI before. A 30-second framing helps:

At the Agentic Gathering (running it)

Starting the event

1

Open the operator console at /en/gatherings. The events index lists past Agentic Gatherings; live events are pinned at the top.

2

Click + New event (or open an existing draft). Set the label and date; add participants from the roster picker.

3

Pick configuration. Persona (default dinner_host), voice (default Aoede), face (default Broken Weasel). The Active prompt panel shows the exact instructions that will go to Gemini Live β€” toggle Override prompt for this session to hot-edit them. Edits stay scoped to this one event; canonical prompts live in apps/ai-host/persona.py.

4

Click Start Agentic Gathering. The system creates a LiveKit room, transitions the event to live, and shows the host URL. Avatar setup takes ~1.5–2 seconds.

5

Open the host URL on the table display. Use the Copy or Open β†— button next to the URL. The display subscribes to the room and renders the avatar full-screen. The AI's voice plays through this device's speakers.

6

Have participants open Speak+View on their phones. If they're on the roster of the live event, the app auto-detects it and connects their phone as a mic. (Today this requires the latest Android APK; older builds will only do the existing translation/subtitle pipeline.)

While the conversation is running

Ending

Click End Agentic Gathering in the operator console. The system deletes the LiveKit room (which causes Phoenix to drop the agent job and Simli to stop billing), computes aggregate metrics (duration, cost, turn count), and freezes the event row at status='ended'. The table display returns to its idle silhouette.

After the Agentic Gathering

What gets saved

What's not saved (yet)

Reviewing or re-running an event

The events index at /en/gatherings is permanent history. Click any past event to read the full transcript, configuration snapshot, and operator notes. The detail page also offers a future Clone into new event button to reuse a configuration that worked.

Current limits & what's coming

What's now shipped, and what's still pending:

LimitWorkaround todayFixed in
Late joiners after in_progress don't get their dossier injectedGet everyone into the lobby before someone says β€œlet's start.” Late joiners are still welcomed, just without the host having their hooks.Phase 2 of MVP spec (deferred β€” restarting the realtime session mid-gathering is jarring)
Profile is read-only on the Android appUser can re-run their interview to update; can't directly edit the AI-extracted fieldsPhase 3.1 of MVP spec (PUT-back endpoint)
iOS lobby/profile parityiOS app (apps/mobile-apple) does not yet have the lobby list or AI-profile section. Use Android for the personalization test.Sponica iOS build cycle
No goal-driven host (e.g. "make sure each guest gets to share something")Host is purely reactive in v1 by design β€” proves the trigger model firstPhase 2 of MVP spec (deferred until reactive baseline is proven)
No time-aware behavior arc (warm-up β†’ meat β†’ wind-down)Host is time-blind; same behavior at minute 5 and minute 60Phase 2 of MVP spec (deferred)
Heat / discomfort detectionHost has no special handling when a topic gets uncomfortable; relies on the room to self-regulatePhase 2 of MVP spec (deferred until simple bridging is proven)
Multi-mic auto-mix only β€” no smart speaker gatingEncourage one-speaker-at-a-time among guests for clean transcriptsai-host-livekit Phase 2 (wake-gate / loudest-mic selection)
No wake word β€” AI replies whenever it hears voice activityMute mics between rounds if you want a breakai-host-livekit Phase 3 (Haiku wake-gate)
No table-level programmatic prompts (e.g. "time for the next course")Operator can hot-edit the prompt before start; or just say it during the Agentic Gatheringai-host-livekit Phase 4 (programmatic prompts)
Cross-guest live translation of the AI's outputThe AI replies in the speaker's language. Other guests rely on the existing Speak+View subtitle pipeline (separate from LiveKit)Future: integrate translation pipeline with LiveKit transcript stream
Audio recording / replayNone β€” only text transcript persistsDeferred (privacy review)

Full MVP spec: ai-host-mvp. Realtime stack: ai-host-livekit. AI-side architecture: Agentic Gathering Host.

Troubleshooting

Operator console returns 403 / blank page

Your app_users.role doesn't grant the host_dinner permission. Default grants are admin, oracle, staff. Either get promoted, or add a per-user override:

INSERT INTO user_permissions (app_user_id, permission_key, granted)
VALUES ('<your-app-user-id>', 'host_dinner', true);

Start Agentic Gathering button is disabled

You haven't added any participants to the roster yet. Click + Add participant; you need at least one before Start enables.

Table display stuck on β€œSetting the table…”

The avatar fades in once Simli starts publishing β€” that's ~1.5–2 seconds after Start. If you wait 10+ seconds and still see the silhouette, check the operator console's diagnostics zone:

Participant phone shows no in-gathering banner

The AI answered in the wrong language

Gemini Live's auto-detect can guess wrong on short phrases. Speak a full sentence and it usually corrects itself within one turn. If it stays stuck, End the Agentic Gathering and Start a new event β€” the language hint resets.

Audio sounds robotic / chopped on the table display

Network jitter on the display device. Move closer to the router or switch to wired Ethernet if available. Simli avatar video is the bandwidth-heavy track; the AI voice itself is light.

Two voices talking over each other in the AI's response

Means a previous LiveKit room wasn't fully cleaned up before a new agent dispatched into the same name. Click End on the offending event, then Start a fresh one β€” Phoenix uses anonymous workers with exactly-once dispatch per room, so a clean Start should not collide.

I want to recover transcripts after End

Open the event detail page from the events index. Full transcript and log are persisted in dinner_event_transcript / dinner_event_log. There is no audio recording.

"From your AI interview" card on Android shows "Couldn't load: ..."

The card hits host-mvp-profile-get with the user's Google ID token. Common error codes:

Lobby list shows "No active Agentic Gatherings right now"

The endpoint queries dinner_events filtered to lifecycle in ('lobby_open','in_progress'). If you opened the event but only flipped status='live' (legacy column), the new lobby UI won't see it. Call the lifecycle endpoint to set lifecycle='lobby_open' explicitly.

"Let's start" trigger didn't fire

Check the agent log (Phoenix VM, or dinner_event_log rows). Two common causes:

The host has zero context β€” speaks generically about everyone

Dossiers weren't fetched at job start. Check the agent's startup log for "Dossier fetch: requested=N returned=M". If requested=0, the participant metadata didn't include user_ids β€” token-mint flow issue. If requested>0, returned=0, the users in the room don't have user_dossiers rows yet β€” they need to complete the v2 interview, see Step 1.