Gemini Live Agent Challenge - Live Agents Category
#GeminiLiveAgentChallenge
A real-time, multimodal AI cooking assistant that lives in your browser. Your hands are covered in flour - you can't type. Your eyes are on the pan - you can't read a recipe. Sigma listens, watches, and responds with voice + vision, no screen touching required.
Now unlocked to guide through any YouTube tutorial.
This is not a chatbot. There is no text box. Sigma is entirely hands-free.
| Traditional Cooking App | Sigma |
|---|---|
| You type a question | You say it aloud |
| You read the answer | Sigma speaks back |
| You tap "next step" | You say "next" |
| Static recipe page | Live camera awareness |
| Single model | 6 Gemini models orchestrated in parallel |
- Bidirectional audio via Gemini Live API
- Barge-in detection, session resumption, real-time transcription
- 1 FPS camera feed streamed to Gemini for continuous kitchen awareness
| Tool | Trigger | What Happens |
|---|---|---|
set_timer |
"set a 5 minute timer" | Countdown widget |
find_object |
"where's the garlic?" | Camera β bbox detection β overlay |
find_substitute |
"I'm out of lemongrass" | Google Search grounding + camera check |
how_to |
"how do I dice an onion?" | Illustrated 4-step guide generated |
list_item |
"what do I need?" | Ingredient/tool list widget |
set_goals |
YouTube tutorial loaded | Steps parsed into progress tracker |
check_current_step / check_next_step |
"what step am I on?" | Returns tutorial state |
next_step |
"I'm done with this" | Advances tutorial index |
Paste a YouTube URL β Gemini 3.1 Pro watches the full video β extracts structured steps β navigate hands-free with voice.
Zero-backend β all orchestration runs client-side. No server, no database.
flowchart TB
subgraph USER["π€ User"]
MIC["π€ Microphone<br/><i>PCM 16kHz</i>"]
CAM["π· Camera<br/><i>JPEG 768px Β· 1 FPS</i>"]
SPK["π Speaker<br/><i>PCM 24kHz</i>"]
SCREEN["π₯οΈ Screen<br/><i>Widget display</i>"]
end
subgraph BROWSER["βοΈ Browser Client Β· React 18 + Vite"]
direction TB
subgraph HOOKS["Custom Hooks"]
GEMINI_HOOK["useGeminiLive<br/><i>WebSocket session<br/>auto-reconnect Β· resumption</i>"]
AUDIO_HOOK["useAudioStream<br/><i>AudioWorklet PCM codec<br/>16kHz β Β· 24kHz β<br/>FFT analyser</i>"]
CAM_HOOK["useCamera<br/><i>1 FPS capture loop<br/>on-demand full-res</i>"]
end
subgraph ORCHESTRATOR["π§ App.jsx β Orchestrator"]
DISPATCH["Tool Dispatcher<br/><i>Routes to sub-agents</i>"]
QUEUE["Result Queue<br/><i>FIFO Β· drains on idle</i>"]
STATE["Voice State Machine<br/><i>idle β listening β<br/>speaking β listening</i>"]
end
subgraph WIDGETS["π Widget Manager Β· 3 Slots"]
W_TIMER["β±οΈ Timer"]
W_BBOX["π² BBox"]
W_SEARCH["π Search"]
W_HOWTO["π¨ How-to"]
W_LIST["π Item List"]
W_LOADING["β³ Loading"]
end
TUTORIAL["π Tutorial Engine<br/><i>Step tracking + progress bar</i>"]
VOICE_VIZ["ποΈ VoiceIndicator<br/><i>40-bar FFT waveform</i>"]
end
subgraph GEMINI["βοΈ Gemini Cloud"]
direction TB
subgraph CONDUCTOR["π― Conductor"]
LIVE["Gemini Live 2.5 Flash<br/><i>WebSocket Β· bidirectional<br/>voice + vision + tool calling</i>"]
end
subgraph BBOX_AGENT["π² BBox Agent"]
BBOX_MODEL["Gemini 3 Flash Preview<br/><i>+ Code Execution</i>"]
CODE_EXEC["Python Sandbox (gVisor)<br/><i>Runs OpenCV bbox code<br/>inside Gemini's runtime<br/>No external Vision API</i>"]
BBOX_MODEL --> CODE_EXEC
end
subgraph SUB_AGENT["π Substitute Agent"]
SUB_MODEL["Gemini 3.1 Flash<br/><i>+ Google Search Grounding</i>"]
VISION_CHECK["Vision Follow-up<br/><i>Camera availability check</i>"]
SUB_MODEL --> VISION_CHECK
end
subgraph HOWTO_AGENT["π¨ How-To Agent"]
HOWTO_MODEL["Gemini 3.1 Flash Image<br/><i>Nano Banana Pro<br/>Illustrated guide gen</i>"]
end
subgraph TUTORIAL_AGENT["π Tutorial Analyzer"]
TUTORIAL_MODEL["Gemini 3.1 Pro Preview<br/><i>Full YouTube video<br/>multimodal understanding</i>"]
end
end
MIC -- "PCM 16kHz" --> AUDIO_HOOK
CAM -- "MediaStream" --> CAM_HOOK
AUDIO_HOOK -- "PCM 24kHz" --> SPK
WIDGETS --> SCREEN
AUDIO_HOOK -- "base64 chunks" --> GEMINI_HOOK
CAM_HOOK -- "base64 JPEG" --> GEMINI_HOOK
GEMINI_HOOK -- "audio out" --> AUDIO_HOOK
GEMINI_HOOK -- "tool calls" --> DISPATCH
DISPATCH -- "widget updates" --> WIDGETS
DISPATCH -- "async results" --> QUEUE
QUEUE -- "[BACKGROUND_RESULT]<br/>re-inject on idle" --> GEMINI_HOOK
GEMINI_HOOK <== "WebSocket<br/>audio + video + text" ==> LIVE
DISPATCH -. "REST async" .-> BBOX_MODEL
DISPATCH -. "REST async" .-> SUB_MODEL
DISPATCH -. "REST async" .-> HOWTO_MODEL
DISPATCH -. "REST async" .-> TUTORIAL_MODEL
style USER fill:#f9fafb,stroke:#d1d5db,color:#111
style BROWSER fill:#f0fdf4,stroke:#86efac,color:#111
style GEMINI fill:#faf5ff,stroke:#c4b5fd,color:#111
style CONDUCTOR fill:#ede9fe,stroke:#8b5cf6,color:#111
style BBOX_AGENT fill:#dcfce7,stroke:#4ade80,color:#111
style SUB_AGENT fill:#fef3c7,stroke:#f59e0b,color:#111
style HOWTO_AGENT fill:#ffe4e6,stroke:#fb7185,color:#111
style TUTORIAL_AGENT fill:#dbeafe,stroke:#3b82f6,color:#111
style HOOKS fill:#ecfdf5,stroke:#6ee7b7,color:#111
style ORCHESTRATOR fill:#ecfdf5,stroke:#6ee7b7,color:#111
style WIDGETS fill:#ecfdf5,stroke:#6ee7b7,color:#111
| Model | Role | Why this one? |
|---|---|---|
| Gemini Live 2.5 Flash | Conductor β voice conversation + tool calling | Native audio WebSocket, lowest latency, built-in session resumption |
| Gemini 3 Flash Preview | Bounding box detection | Code Execution β runs Python/OpenCV in Gemini's own gVisor sandbox to compute bbox coords. No external Vision API needed. Simple model is enough for object detection |
| Gemini 3.1 Flash | Substitute finder | Google Search Grounding β real-time web data for cooking substitutes. Flash is fast enough β no deep reasoning needed for "what replaces X?" |
| Gemini 3.1 Flash Image | How-to illustrated guides | Nano Banana Pro β native image gen with legible text, preserves camera frame assets as reference |
| Gemini 3.1 Pro Preview | YouTube tutorial analysis | Most capable multimodal model β watches full video (visual + audio + captions), extracts structured steps. Pro-level reasoning needed for unstructured tutorial content |
| Gemini 2.5 Flash TTS | Timer announcements | Dedicated TTS endpoint β bypasses live session so timers fire even mid-conversation |
stateDiagram-v2
[*] --> IDLE: App starts
IDLE --> LISTENING: Gemini connected
LISTENING --> SPEAKING: onAudio received
SPEAKING --> LISTENING: onTurnComplete
LISTENING --> TOOL_RECEIVED: toolCall event
SPEAKING --> INTERRUPTED: user speaks
INTERRUPTED --> LISTENING: audio flushed
state TOOL_RECEIVED {
[*] --> IMMEDIATE_RESPONSE
IMMEDIATE_RESPONSE --> SHOW_LOADING: place widget
SHOW_LOADING --> FIRE_SUB_AGENT: async REST
FIRE_SUB_AGENT --> WAITING: processing
WAITING --> UPDATE_WIDGET: result
UPDATE_WIDGET --> ENQUEUE_RESULT: push to queue
}
TOOL_RECEIVED --> LISTENING: unblocks Gemini
state QUEUE_DRAIN {
[*] --> CHECK_STATE
CHECK_STATE --> INJECT: listening
CHECK_STATE --> WAIT: not listening
WAIT --> CHECK_STATE: onTurnComplete
INJECT --> [*]: sendClientContent
}
ENQUEUE_RESULT --> QUEUE_DRAIN
QUEUE_DRAIN --> LISTENING: result injected
sequenceDiagram
actor U as π€ User
participant S as π― Sigma<br/>Live 2.5 Flash
participant O as π§ Orchestrator
participant W as π Widget
participant A as π² BBox Agent<br/>3 Flash + Code Exec
participant Q as π¬ Queue
U->>S: π€ "where's the garlic?"
S->>O: toolCall: find_object("garlic")
O->>S: β‘ "Searching..."
Note over S: Unblocked β keeps talking
par Parallel execution
O->>W: slot = loading
O->>A: camera frame + prompt
Note over A: Code Execution runs<br/>Python in gVisor sandbox<br/>β bbox coords [y,x,y,x]
A-->>O: JSON bbox results
end
O->>W: loading β bbox overlay
O->>Q: enqueue result
alt Conductor idle
Q->>O: dequeue
O->>S: [BACKGROUND_RESULT] Found garlic
S->>U: π "Found it β right by the cutting board!"
else Conductor busy
Note over Q: Wait for onTurnComplete...
S-->>O: turn complete
O->>S: [BACKGROUND_RESULT] Found garlic
S->>U: π "Oh, spotted your garlic!"
end
W->>W: auto-dismiss (15s)
sequenceDiagram
actor U as π€ User
participant S as π― Sigma
participant O as π§ Orchestrator
participant F as π 3.1 Flash<br/>+ Google Search
participant V as ποΈ Vision Check
participant W as π Widget
U->>S: π€ "I don't have lemongrass"
S->>O: find_substitute("lemongrass")
O->>S: β‘ "Searching..."
O->>F: query + Google Search grounding
Note over F: Flash is fast enough β<br/>no reasoning needed<br/>for substitute lookup.<br/>Google Search provides<br/>real-time cooking data.
F-->>O: ranked substitutes + ratios
O->>V: camera frame + "which are visible?"
V-->>O: ginger: visible, lemon zest: not found
O->>W: search widget (subs + availability)
O->>S: [BACKGROUND_RESULT] Best: ginger (visible)
S->>U: π "Ginger works β and you've got some!"
sequenceDiagram
actor U as π€ User
participant APP as βοΈ Start Screen
participant PRO as π 3.1 Pro Preview
participant S as π― Sigma
U->>APP: Paste YouTube URL
APP->>PRO: fileData: {fileUri: url}
Note over PRO: Why 3.1 Pro?<br/>Most capable multimodal model.<br/>Watches full video β<br/>visual + audio + captions.<br/>Pro reasoning extracts<br/>structured steps from<br/>unscripted content.
PRO-->>APP: JSON: [{step_number, step_name,<br/>timestamp, description}, ...]
APP->>S: [TUTORIAL_LOADED] + steps
S->>S: set_goals(steps)
S->>U: π "Tutorial loaded! 8 steps.<br/>Let's start with Step 1!"
stateDiagram-v2
[*] --> EMPTY
EMPTY --> LOADING: tool dispatched
LOADING --> TIMER: set_timer
LOADING --> BBOX: find_object
LOADING --> SEARCH: find_substitute
LOADING --> HOW_TO: how_to
LOADING --> ITEM_LIST: list_item
TIMER --> TIMER_DONE: countdown = 0
TIMER_DONE --> EMPTY: 5s
BBOX --> EMPTY: 15s
SEARCH --> EMPTY: 15s
HOW_TO --> EMPTY: 30s
ITEM_LIST --> EMPTY: next_step or 20s
note right of TIMER_DONE: π Alarm chime<br/>+ TTS announcement
| Decision | Why |
|---|---|
| Zero backend | All API calls from browser β no server, no infra cost |
| Fire-and-forget tools | Immediate placeholder unblocks voice β no silence |
| Code execution for bbox | Python runs inside Gemini's sandbox β no external Vision API |
| Google Search grounding | Real-time web data β recipes change, training data doesn't |
| 3.1 Flash for substitutes | Fast enough β "what replaces X" doesn't need reasoning |
| 3.1 Pro for tutorials | Only model that watches full YouTube video multimodally |
| Separate TTS agent | Timer announcements fire even mid-conversation |
| Result injection queue | Sub-agent results wait for idle β no mid-sentence interrupts |
| 3-slot widget system | empty β loading β result β auto-dismiss lifecycle |
sigma/
βββ frontend/
β βββ src/
β β βββ App.jsx # Orchestrator + tool dispatch
β β βββ hooks/
β β β βββ useGeminiLive.js # Gemini Live WebSocket client
β β β βββ useCamera.js # Camera stream + frame capture
β β β βββ useAudioStream.js # PCM audio I/O via AudioWorklet
β β βββ components/
β β βββ CameraWidget.jsx # Live feed + flash animation
β β βββ TimerWidget.jsx # Countdown + drain bar
β β βββ BBoxWidget.jsx # Bounding box overlay
β β βββ SearchWidget.jsx # Substitute display
β β βββ HowToWidget.jsx # Illustrated guide
β β βββ VoiceIndicator.jsx # FFT waveform canvas
β β βββ TutorialProgressBar.jsx
β βββ public/
β β βββ pcm-recorder-processor.js # AudioWorklet: mic β 16kHz PCM
β β βββ pcm-player-processor.js # AudioWorklet: 24kHz PCM β speaker
β βββ .env # VITE_GEMINI_API_KEY
βββ README.md
cd frontend
npm installCreate frontend/.env:
VITE_GEMINI_API_KEY=your_google_ai_studio_key_here
npm run devOpen http://localhost:5173, grant mic + camera, start talking.
For Tutorial Mode: paste a YouTube URL on the splash screen before starting.
| Layer | Technology |
|---|---|
| Frontend | React 18 + Vite 5 |
| Styling | Tailwind CSS 3.4 |
| Animation | Framer Motion 12 |
| Gemini SDK | @google/genai 1.45 |
| Audio | Web Audio API + AudioWorklet |
Background tasks + result injection is the key pattern. Respond immediately, run heavy tasks async, inject results as [BACKGROUND_RESULT] on the next idle turn. Conversation never blocks.
Context window compression matters. Long cooking sessions accumulate context. SlidingWindow compression prevents degradation over 30-60 minute sessions.
Multi-model orchestration needs clear handoffs. Each model returns different formats. A clean dispatch layer with a FIFO result queue prevents race conditions.
MIT