Public
Remixed
Sample app for the OpenAI Realtime API
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.

hello-live

Hello Live is an OpenAI GPT-Live app that supports both WebRTC and SIP (telephone) users. You can access the app via WebRTC at hello-live.val.run, or via SIP by calling 425-800-0073.

This demo shows off the GPT-Live WebRTC session API, the SIP webhook flow, and the server-side sideband websocket used to observe and control a session. It uses Responses delegation: gpt-live-1 handles the spoken conversation while a backend Responses model (gpt-5.6-luna) handles reasoning and tool calls (e.g. end_call). Demo calls are limited to 3 minutes.

If you remix the app, you'll just need to pop in your own OPENAI_API_KEY (from platform.openai.com), and if you want SIP, the OPENAI_SIGNING_SECRET. For SIP you also need to subscribe your project's webhook to the live.transport.incoming event.

Architecture

  1. WebRTC Flow:
    • Browser connects to frontend and creates a WebRTC offer
    • /rtc endpoint posts the offer + session config to POST /v1/live/sessions and returns the SDP answer + session ID
    • sideband observer attached to monitor the session
  2. SIP Flow:
    • Phone call triggers the live.transport.incoming webhook
    • /sip endpoint verifies the webhook and accepts the call with the session config
    • sideband observer attached to monitor the session
  3. Delegation:
    • GPT-Live delegates tool use to the Responses backend
    • Function calls arrive on the sideband wrapped in response.event
    • The observer returns results with response.item.create and continues the backend with response.create
Rendering mermaid diagram...

API Endpoints

  • GET / - serves the WebRTC-based app
  • POST /rtc - creates a new GPT-Live WebRTC session; body is the SDP offer, response is { session: { id }, transport: { type: "webrtc", sdp } }
  • POST /sip - handles the live.transport.incoming webhook for an incoming SIP call
  • POST /observer/:sessionId - internal endpoint to attach a GPT-Live sideband websocket for session control

Project Structure

├── frontend/
│   └── index.html          # HTML/JS application for WebRTC
├── main.tsx                # Main entrypoint for the val.town app
└── routes/
    ├── agent.ts            # GPT-Live session configuration, delegation, and tools
    ├── observer.ts         # Server-side sideband control for SIP & WebRTC
    ├── rtc.ts              # WebRTC session setup
    ├── sip.ts              # SIP webhook handling and session setup
    └── utils.ts            # Various HTTP helpers

TODO

  • Drive audioActive / callEnding from reflected session.output_audio.delta events so hangup waits for the goodbye to finish playing
  • Send session.close from the browser on Stop and wait for session.closed
  • Render transcript deltas as captions