Heartbeat
A voice agent has many moving parts and almost all of them fail silently. A heartbeat endpoint is your first defense. It tells you, in one HTTP call, whether the service is up and whether FastRTC is actually importable in this environment.
@router.get("/health", response_model=ServiceInfo)
async def health_check():
return ServiceInfo(
status="ok",
service="realtime-phone-agents-fastrtc",
description="Realtime phone agent using FastRTC for WebRTC audio streaming",
fastrtc_available=FASTRTC_AVAILABLE,
webrtc_mount="/phone/webrtc",
)Two important fields here. fastrtc_available tells you whether the import succeeded on this host. webrtc_mount tells your client where to send the SDP offer. Both are things you want to verify before wasting time debugging audio.
class ServiceInfo(BaseModel):
"""Health check response"""
status: str
service: str
description: str
fastrtc_available: bool
webrtc_mount: strPydantic validates the shape so a regression that drops fastrtc_available fails the response schema instead of silently passing. Health checks that lie about themselves are worse than no health checks at all.
curl -s http://localhost:8000/phone/health | jq
# Expected output:
# {
# "status": "ok",
# "service": "realtime-phone-agents-fastrtc",
# "description": "Realtime phone agent using FastRTC for WebRTC audio streaming",
# "fastrtc_available": true,
# "webrtc_mount": "/phone/webrtc"
# }Before you touch the WebRTC client, curl the heartbeat. If fastrtc_available is false, do not chase audio bugs. Fix the import first.
Validation checklist: First connection checklist
Loading practice…
Quiz: Quiz
Loading practice…