3D office UI + multi-agent Google Meet assistant.
apps/web (Next.js UI: / + /meet) ─┐
apps/api (Hono REST stubs) ─┼─► backend/ (FastAPI) ──WS──► worker/ (Python)
─┘ │
Playwright/Chrome + Google Meet
│
Virtual audio ⇄ Gradium STT/TTS / agents
apps/web— 3D headquarters (/) + Meet deploy screen (/meet)apps/api— Hono REST stubs (chat, presence, meet)packages/shared— Shared TypeScript contractsbackend/— FastAPI: session REST +/workerWebSocketworker/— Meet control, audio routing, speech pipelinespeech/— Gradium STT/TTS, wake-word routing, orchestratoragents/— Cursor cloud agentSKILL.mdfilesdocs/AUDIO_SETUP.md— virtual audio setup
GRADIUM_API_KEYfor STT + TTSCURSOR_API_KEYfor cloud agent invocation (see below)- Chrome with agent Google account in
CHROME_USER_DATA_DIR - Virtual audio devices (see
docs/AUDIO_SETUP.md) - Python 3.11+, Node 18+, PortAudio (
brew install portaudioon macOS)
# UI (headquarters + /meet deploy screen)
npm install && npm run dev # http://localhost:3000
# Backend
cd backend && uv sync && uv run uvicorn main:app --host 0.0.0.0 --port 8000
# Worker
cd worker && uv sync && uv run playwright install chromium
cp .env.example .env && uv run python main.pyFlow: / → click agent → info popup → Meet → /meet → share link + Start Agent
All agents dial the same Meet room via SHARED_MEET_URL (see .env.example).
Backend exposes it at GET /meet-url, worker uses it as the default target,
and speech/agent_context.py injects it into every agent invocation.
Set CURSOR_API_KEY and (optionally) override CURSOR_AGENTS_API_URL.
The voice loop dispatches wake-word commands via speech/cursor_cloud_client.py,
which wraps the Cursor Agents REST API
with retry + try/except. Failures never crash the meeting loop.
| Agent | Folder | Wake word |
|---|---|---|
| Meeting router | agents/meeting-router/SKILL.md |
— |
| Angie (Incident orchestrator) | agents/angie/SKILL.md |
Angie |
| Nikki (Code — local mock) | agents/nikki/SKILL.md |
Nikki |
| Olaf (Computer-Use) | agents/olaf/SKILL.md |
Olaf |
| Speech editor | agents/speech-editor/SKILL.md |
— |
Meet audio → Gradium STT → wake word → meeting-router
→ Angie delegates → Nikki (raw incident analysis)
→ speech-editor (conversational script)
→ Gradium TTS → Meet audio
Core loop: speech/meeting_session.py · Meet audio bridge: worker/speech_bridge.py
Demo customer complaints map to a local bug — no Git repo access required.
mock-incident/
INCIDENT.md # customer write-up
app/checkout.py # planted bug (empty cart → KeyError)
app/checkout_fixed.py # reference fix
Nikki reads these files via speech/nikki_client.py. Override path with MOCK_INCIDENT_ROOT in worker/.env.
Try in local sim: ROUTER_MODE=heuristic then say "Angie, a customer says checkout crashes on an empty cart."