Seraphim Labs

04

The Gemini relay

What the relay does for your coach, what it costs in latency, and how the worker talks to it.

4. The Gemini relay

Your card carries a team token, not a Google key. With GEMINI_API_KEY=<team token> and GEMINI_BASE_URL=https://james-72765--rtcoach-gemini.modal.run exported, every Gemini byte from your laptop goes to our relay (modal/gemini_relay.py), which swaps the token for our key and forwards to Google: the Live websocket (/ws/..., the worker's --voice gemini) and plain HTTPS (generateContent, models.list, TTS for cues_tts, streaming alt=sse). The token travels in the x-goog-api-key header; the google-genai SDK does that itself once the two variables are set, so the worker and cues_tts need no change. An unknown token gets HTTP 401 (JSON {"error": "unknown team token"}) or a websocket close 1008. Each team has 240 Live minutes; past the cap the relay answers 429 or close 1008 "team cap reached, ask the organiser". GET /health is public and shows token counts and totals, never a key or token. A team's own Google key works too: put it in GEMINI_API_KEY and leave GEMINI_BASE_URL unset. Smoke test (replace the token, never paste it anywhere):

curl -s -X POST "https://james-72765--rtcoach-gemini.modal.run/v1beta/models/gemini-2.5-flash:generateContent" -H "x-goog-api-key: <team token>" -H "content-type: application/json" -d '{"contents":[{"parts":[{"text":"hi"}]}]}'