transcript.v1 → agent bridge) lives in one place: Modules & seams.
The lifecycle — one meeting, one row
A meeting is one record from plan to transcript. It is born in a user-owned intent status, is claimed by the bot lifecycle when the bot joins, and ends terminal — the plan’s title, its workspace binding, and the eventual transcript all live together:| Phase | Statuses | Owned by |
|---|---|---|
| Planned | idle (no time) · scheduled (time set) | you — create/edit/delete freely |
| Live | requested → joining → awaiting_admission → active → stopping | the bot lifecycle FSM |
| Done | completed · failed | terminal |
Plan
Create a meeting before it happens withPOST /meetings: a title,
an optional start time, an optional meeting link (Meet/Zoom/Teams — parsed server-side), an
optional workspace binding. A plan without a link is fine — attach the link
later; a plan without a time sits in idle until you schedule it.
Import — calendar sync
Connect your calendar with its secret ICS address (Google Calendar and Outlook both provide one — see Calendar sync); no OAuth needed. Connecting syncs immediately and answers with the result — every sync failure is stamped as a human-readable status (GET /user/calendar/sync, shown in the Terminal’s calendar panel), never swallowed — failures
are loud here, like everywhere in the lifecycle. A background sweep re-fetches
the feed (default every 5 minutes) and upserts planned meetings:
- Only events with a recognizable meeting link import — a dentist appointment is not a joinable meeting.
- One meeting per calendar event, next occurrence only — a weekly meeting reuses one link, so the importer tracks the next upcoming occurrence; the following one imports after the current completes.
- Moves and cancellations follow the feed; a meeting the bot already joined is never touched.
- A meeting you planned manually on the same link is adopted (linked to the calendar event), not duplicated.
Auto-join — “scheduled” means the bot comes
Ascheduled meeting with a link is joined automatically: a sweep sends the bot shortly
before the start time (default 60 s lead). Control it per meeting with the auto-join toggle
(default on) and globally for imported meetings with the calendar’s auto-join switch. Two
guarantees:
- Never hours late — a meeting whose start passed the grace window (default 10 min) is skipped, not joined absurdly late.
- Failures are loud — a concurrency-cap or spawn failure stamps a visible error on the
meeting (
auto_join_error) instead of silently not showing up. See Troubleshooting.
Capture
The bot joins natively, in real time, with no plugins or host configuration — it attends like any participant, on Google Meet, Zoom, and Microsoft Teams. Mechanically it is a browser container spawned by the runtime — the same runtime an agent runs in. The speaker-attributed (diarized) transcript streams live over the API and WebSocket.Share — workspaces carry the meeting
Bind a meeting to a shared workspace and every member of that workspace sees it: the upcoming plan, the live transcript feed, and the finished transcript. That makes the prep workflow one motion — prepare context in a workspace, invite the people you’re meeting, and the meeting itself rides along. See Plan and share a meeting. (Independent one-off transcript share links exist too — no workspace required.)From transcript to knowledge
- The bot captures audio; transcription produces a real-time
transcript.v1stream. - The transcript compiles into the person’s workspace as Markdown.
- Agents read it like any other file — and act on it:
- Before the meeting — prepare a briefing in the bound workspace; attendees see it live.
- After the meeting — a dispatch writes notes, decisions, and action items as workspace files.
- During the meeting — a live dispatch surfaces proactive cards (new person, action item, decision); see Meeting copilot.