Skip to content

Agenda Meetings

An agenda meeting is a structured solo working session: silicon-zack preps a grounded agenda, then bio-zack works it through by voice one item at a time β€” on the move β€” while the real work (filing tasks, writing artifacts) happens asynchronously between items.

It is deliberately not a recording. Capture belongs to the HiDock recorder.

Status: shipped 2026-07-21 as part of the iOS overhaul. Replaced a phone-side meeting-upload flow that was built and killed the same day.

Why the phone stopped trying to capture meetings

On the morning of 2026-07-21 an iOS MeetingRecorder shipped: record a meeting on the phone, upload the m4a, run it through the existing diarized ingest. It was deleted that afternoon on bio-zack's call β€” the phone will never capture meetings. The recorder hardware owns capture, and a second path into the meeting-ingest pipeline is split-brain by construction.

The lesson generalized into the pivot: the highest-leverage thing the phone can do for a meeting is not capture it but be the other participant β€” a grounded, pushing, hands-free thinking partner for solo work (planning a WBR, thinking through a decision) in exactly the moments bio-zack is walking or driving and can't sit at a keyboard.

Lifecycle

  goal submitted (phone composer or POST /api/v1/agenda-meetings)
        β”‚
        β–Ό
  status: preparing ──▢ agenda_prep agent (claude daemon / stream_inference)
        β”‚                researches, produces 2-6 items, each with a
        β”‚                compiled grounding_prompt: facts w/ sources,
        β”‚                prior decisions, open questions, what to push on
        β–Ό
  status: ready
        β”‚
        β–Ό
  β”Œβ”€β”€ per item ────────────────────────────────────────────────┐
  β”‚  POST .../items/{id}/start                                  β”‚
  β”‚        β–Ό                                                    β”‚
  β”‚  server mints ephemeral client secret (agenda_realtime.py)  β”‚
  β”‚        β–Ό                                                    β”‚
  β”‚  phone connects DIRECTLY to the realtime provider (WS)      β”‚
  β”‚  full duplex, barge-in, live transcripts both sides         β”‚
  β”‚        β–Ό                                                    β”‚
  β”‚  model calls end_agenda_item  (or manual end button)        β”‚
  β”‚        β–Ό                                                    β”‚
  β”‚  phone POSTs transcript β†’ item: live β†’ processing           β”‚
  β”‚        β–Ό                                                    β”‚
  β”‚  agenda_item_process agent: extracts decisions/actions AND  β”‚
  β”‚  does the executable work β€” files Precedent tasks, writes   β”‚
  β”‚  artifacts β†’ outputs.md β†’ done                              β”‚
  β”‚        β–Ό                                                    β”‚
  β”‚  3s interstitial, auto-advance to next item                 β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚
        β–Ό
  agenda_wrap agent writes the summary
        β”‚
        β–Ό
  everything posts to a per-meeting telegram topic

The realtime layer

Each item runs as one bounded duplex voice session. The server mints an ephemeral client secret (gpt-realtime-2.1-mini, voice marin, 24 kHz PCM, WebSocket subprotocol auth) with the persona, grounding pack, and tools baked in server-side.

Two properties follow from that split, and both are deliberate:

  • The phone never sees the prompt or the API key.
  • The server never touches audio. Audio goes phone ↔ provider directly.

The model gets exactly one tool β€” end_agenda_item β€” so "close that out" ends the session naturally. A manual end button always exists.

Barge-in works through hardware AEC (.voiceChat audio session), so bio-zack can interrupt the model mid-sentence the way he would a person.

The layer is provider-swappable on purpose: the server dispatches through mint_realtime_session(provider=...) and iOS talks to a RealtimeVoiceProviding protocol with a normalized RealtimeEvent. OpenAI can become Gemini Live or xAI later. xAI is currently blocked β€” its ephemeral tokens can't carry baked session config.

Why grounding is the whole product

An ungrounded voice model is a chatbot. The grounding_prompt compiled during prep is what makes each item substantive: real facts with sources, decisions already made, the open questions, and an explicit note on what to push back on. bio-zack's profile explicitly rewards aggressive pushback β€” he gets to insights that gentle probing misses β€” so the grounding pack tells the model to argue.

Honest-failure design

Statuses only ever reflect live reality. This is the instrumentation-lying antibody applied to a multi-agent pipeline:

  • any agent death, timeout, or empty result β†’ error + error_detail + a telegram note
  • a startup orphan sweep (sweep_orphans()) marks lost preparing / processing / wrapping runs past their budget as error
  • never a faked "done", never an infinite spinner

Where it lives

Piece Path
Router + prep/item/wrap runs + orphan sweep api/src/routers/agenda_meetings.py
Agent prompts api/src/services/agenda_prompts.py
Realtime session minting api/src/services/agenda_realtime.py
Storage api/src/services/agenda_store.py
On disk data/agenda-meetings/<id>/{meeting.json, items/<item_id>/{transcript.md,outputs.md}}
iOS Services/AgendaMeetings/*, Views/Meetings/*
Kickoff nudge scripts/proactive/agenda_kickoff.py

Signals

Working: bio-zack starts agenda meetings for real solo-thinking work and the grounded agent surfaces tension he hadn't pre-loaded; item-process agents produce genuinely filed tasks and written artifacts, not just summaries; the async auto-advance feels natural; errors surface honestly.

Failing: the voice agent feels like an ungrounded chatbot, or he'd rather just type.

Watch: whether a second realtime provider actually lands (that validates the swap seams); whether ~5 minutes of prep is worth the wait; resumability of a dropped mid-item session.