brainstorming
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or planning anything new, in software or out of it (a talk, a business, a renovation).
voice-ai-engine-developmentBuild production-ready real-time conversational voice AI engines using async worker pipelines, Gemini Live API for streaming STT, Gemini TTS for synthesis, LangGraph or Google ADK agents, interrupt handling, and FastAPI WebSocket integration. Use when building voice assistants, real-time voice bots, or conversational AI pipelines with full interrupt support.
Independent GitHub snapshot · Automated classification · Original documentation governs
NO VOICE ENGINE WITHOUT INTERRUPT HANDLING AND ASYNC WORKER ISOLATION — EVERY COMPONENT RUNS IN ITS OWN QUEUE
A voice engine without interrupts is a demo, not a product. Every worker (transcriber, agent, synthesizer) MUST run in an isolated asyncio.Queue-based loop. Interrupt handling MUST be wired before any other feature is added. No exceptions.
uv init voice-engine && cd voice-engine
uv add "google-genai>=1.0.0" "fastapi>=0.135.2" "uvicorn[standard]" \
"websockets>=13.0" pydantic pydantic-settings structlog \
"langgraph>=1.0.7" "langchain-core>=1.2.8" \
"google-adk>=1.28.0" pydub numpy aiolimiter
uv add --dev pytest pytest-asyncio httpx ruff mypy
uv init + install google-genai (NOT google-generativeai) and dependenciescore/config.py with pydantic-settings, .env, structured logging (no print())start(), _run_loop(), terminate()LangGraphAgentWorker (StateGraph) or ADKAgentWorker (SequentialAgent)gemini-2.5-flash-tts-preview or gemini-2.5-pro-tts-previewStreamingConversation orchestratorInterruptibleEvent, broadcast_interrupt(), rate-limited chunk playback, mute logic/conversation endpoint, asynccontextmanager lifespan (NEVER @app.on_event)| Pattern | Implementation | Reference |
|---|---|---|
| Worker Pipeline | BaseWorker → asyncio.Queue → isolated _run_loop | reference/worker-pipeline.md |
| Gemini Live STT | GeminiTranscriberWorker — WebSocket to gemini-live-2.5-flash-native-audio | reference/worker-pipeline.md |
| Gemini TTS | GeminiSynthesizerWorker — gemini-2.5-flash-tts-preview / gemini-2.5-pro-tts-preview | reference/worker-pipeline.md |
| Interrupt System | InterruptibleEvent + broadcast_interrupt() + rate-limited chunks + transcriber mute | reference/interrupt-handling.md |
| Provider Factory | VoiceComponentFactory — config-driven worker creation | reference/worker-pipeline.md |
| WebSocket Integration | FastAPI /conversation + asynccontextmanager lifespan + WebsocketOutputDevice | reference/worker-pipeline.md |
| Error Recovery | Worker loop catches + logs + reraises; session reconnect for Gemini Live timeouts | reference/interrupt-handling.md |
Before generating code, consult these sources:
| Source | URL / Tool | Purpose |
|---|---|---|
| Gemini Live API | https://ai.google.dev/gemini-api/docs/llms.txt | Live API WebSocket protocol, audio format, barge-in |
| google-genai SDK | Context7 MCP → resolve google-genai | Current SDK API signatures |
| LangGraph | https://langchain-ai.github.io/langgraph/llms-full.txt | StateGraph, nodes, edges |
| Google ADK | Context7 MCP → resolve google-adk | SequentialAgent, session patterns |
| FastAPI | Context7 MCP → resolve fastapi | WebSocket, lifespan patterns |
| File | Content | When to Use |
|---|---|---|
reference/gemini-provider-setup.md | google-genai install, Live API WebSocket setup, model names, audio format, auth, rate limits | First — before writing any Gemini code |
reference/worker-pipeline.md | BaseWorker/BaseTranscriber/BaseAgent/BaseSynthesizer + GeminiTranscriberWorker + GeminiSynthesizerWorker + LangGraphAgentWorker + ADKAgentWorker + FastAPI wiring | Core pipeline implementation |
reference/interrupt-handling.md | InterruptibleEvent, broadcast_interrupt, rate-limited playback, transcriber mute, state machine, graceful shutdown | Interrupt system implementation |
reference/provider-comparison.md | Gemini vs Deepgram vs ElevenLabs vs Azure — latency, cost, features, when to use alternatives | Provider selection |
reference/common-pitfalls.md | Audio jumping, echo feedback, interrupts not working, Gemini-specific traps, session timeouts | Debugging and prevention |
uvicorn src.main:app --reload # Run dev server with hot reload
pytest -q # Run all tests
pytest -q tests/test_workers.py # Test worker isolation
pytest -q tests/test_interrupt.py # Test interrupt path
ruff check --fix . # Lint and auto-fix
ruff format . # Format code
mypy src/ # Type check
Iron rule: Every except block in a worker loop MUST:
structlog at error level (include full exception context)# Required pattern in every worker loop
async def _run_loop(self) -> None:
while self.active:
try:
item = await self.input_queue.get()
await self.process(item)
except asyncio.CancelledError:
raise # Never swallow CancelledError
except Exception as exc:
self._log.error("worker_error", worker=self.__class__.__name__, error=str(exc), exc_info=True)
# Continue loop — worker recovers from transient errors
# For fatal errors: self.terminate(); raise
Gemini Live session timeouts: Sessions expire after ~10 minutes. Implement reconnect with exponential backoff. See reference/interrupt-handling.md § Error Recovery.
No print() anywhere. Use structlog.get_logger().
After writing voice engine code, dispatch:
security-reviewer — WebSocket input validation, API key handlingagentic-ai-reviewer (if LangGraph agent) — graph correctness, iteration limitscode-reviewer — async patterns, resource cleanup, error handling