Getting Started with Aeion Realtime
Configure your first realtime session, summon an AI agent into it, set up TURN relay, enable recording and transcription. Self-hosted on your own Hetzner VPS — no per-minute fees.
Detect Your Deployment Mode
Realtime auto-detects at boot. The deployment-mode probe inspects your environment and sets the capability matrix:
```bash # Lite mode — WebSocket only, no voice REALTIME_MODE=lite
# Standard mode — WebSocket + coturn TURN relay REALTIME_MODE=standard
# Full mode — WebSocket + coturn + embedded LiveKit REALTIME_MODE=full
# External mode — BYO LiveKit cluster REALTIME_MODE=external LIVEKIT_API_KEY=... LIVEKIT_API_SECRET=... LIVEKIT_EXTERNAL_API_URL=https://your-livekit.example.com LIVEKIT_EXTERNAL_WS_URL=wss://your-livekit.example.com ```
Auto-detection: If REALTIME_MODE is not set, the service probes for:
livekit-serverbinary → sets mode tofullCOTURN_SHARED_SECRET→ sets mode tostandard- Neither → mode =
lite
Capability matrix returned at boot:
typescript
{
mode: "standard",
effectiveMode: "standard",
features: {
webrtc: {
provider: "coturn",
available: true,
stunServers: ["stun:stun.l.google.com:19302"],
turnServers: [{ urls: "turn:your-vps:3478", credential: "...", username: "..." }]
},
voice: {
provider: "livekit-embedded" | "livekit-external" | null,
available: false // false in lite/standard modes
}
},
warnings: []
}
Admin view: Navigate to /admin/realtime to see the live capability matrix and adapter health status.
Configure TURN Relay (coturn)
| Capability | Purpose |
|---|---|
| **Embedded LiveKit** | Self-hosted SFU subprocess management |
| **Coturn relay metrics** | Bytes relayed, allocation rate, active sessions |
| **Recording & egress** | Composite + track export to RTMP / HLS / S3 |
| **Coturn relay control** | Subprocess control + circuit breaker on crash |
| **Room administration** | Server-side room ops (kick, mute, admin events) |
| **External LiveKit** | External LiveKit cluster (BYO infra) |
| **AI-powered transcription** | Per-tenant AI provider plumbed into the transcription pipeline |
| **Signed participant tokens** | JWT signing for participant tokens |
| **Managed TURN lifecycle** | Lifecycle management + generated `/etc/coturn/turnserver.conf` |
| **Cloudflare Calls** | Opt-in Cloudflare Calls fallback |
| **Webhook verification** | Verifies signed LiveKit webhooks before they hit your event stream |
| **Bring-your-own TURN** | Customer-supplied TURN server config |
| **Server config generation** | Generates LiveKit server config from tenant settings |
| **Honest fallback** | Returns a clear "not configured" status rather than silently degrading |
Create Your First Session
Universal room / peer / connection primitive:
POST /v1/sessions
{
"type": "meeting",
"scope": "private",
"displayName": "Q3 Planning Session",
"complianceProfile": "default",
"metadata": { "projectId": "proj_abc123" }
}
Session types: meeting, review, match, scene, stream, support, telehealth
With media (creates a video room):
POST /v1/sessions
{
"type": "meeting",
"media": { "audio": true, "video": true, "screen": true },
"complianceProfile": "hipaa",
"metadata": { "projectId": "proj_telehealth" }
}
This creates a video room and returns join credentials for each participant.
Data-only (no video infrastructure, WebSocket only):
POST /v1/sessions
{
"type": "support"
}
Omitting media skips video entirely — clients connect over a lightweight WebSocket for data (chat, presence, reactions).
Join a Session — Get ICE Servers
Resolve ICE servers for your tenant:
GET /v1/sessions/:id/ice-servers
Returns a standard WebRTC ICE server list and which provider is backing it for your tenant (self-hosted coturn, Cloudflare Calls, your own TURN server, STUN-only, or none):
json
{
"iceServers": [
{ "urls": "stun:stun.l.google.com:19302" },
{
"urls": "turn:your-vps.example.com:3478",
"username": "exp=1747056000&domain=aeion",
"credential": "HMAC-SHA256-signed-credential"
}
],
"provider": "coturn"
}
Client usage (browser WebRTC + WebSocket signaling):
```javascript const ws = new WebSocket("wss://api.your-domain.com/realtime/signaling"); const peerConnection = new RTCPeerConnection({ iceServers });
ws.onmessage = (event) => { const msg = JSON.parse(event.data); // handle offer/answer/ICE candidate exchange }; ```
Summon an AI Agent into the Session
AI participant lifecycle:
POST /v1/agents/summon
{
"agentDefinitionId": "review-producer",
"sessionId": "session_abc123",
"contextPreamble": "Summoned into Q3 planning session.",
"displayName": "Review Producer",
"idleTimeoutSec": 900,
"keepalive": false
}
Response includes the invocation's id and current status (e.g. "running").
Pre-built agents are installed automatically for every tenant when the module first activates — Review Producer, Helpdesk Triage, AI Tutor, Spatial NPC, and the Telehealth Scribe are ready to summon with no setup.
An agent definition includes: a unique name, a display name, a system prompt with custom instructions, which LLM provider and model it uses (OpenAI, Anthropic, or Google), the MCP tools it's allowed to call, human-readable skill labels, an optional monthly budget cap, and an optional compliance profile.
Summon pre-checks:
- The agent definition exists and is active.
- Your tenant's overall agent budget isn't exhausted.
- The specific agent's own budget cap (if any) isn't exceeded.
- The target session exists and hasn't ended.
- The requested compliance profile is allowed for that provider.
- Idempotency — if the same agent is already running in the session, the existing invocation is returned rather than creating a duplicate.
Enable Recording + Transcription
Recording flow: once a session with media starts and the first participant joins, a recording session is created automatically for it — with your requested format (e.g. mp4), consent requirements, and the session's compliance profile carried over.
POST /v1/sessions/:id/recording/start
{
"format": "mp4",
"consentRequired": true
}
Consent capture: participants must give consent before their audio is captured.
POST /v1/compliance/consent
{
"recordingId": "rec_abc123",
"participantId": "participant_xyz",
"status": "given"
}
Recording can't start until every participant has given consent. A participant who declines has their audio server-muted. A participant who revokes consent mid-recording is muted immediately and the recording is split — audio before the revocation is retained, audio after it is never captured.
Transcription: once a recording finishes, transcription kicks off automatically through the fallback chain — Whisper.cpp (local, free) first, then Cloud Whisper, then OpenAI Whisper, then AWS Transcribe. If every provider fails, the recording stays intact and you can retry manually. The finished transcript includes full text, word-level timestamps and confidence scores, speaker labels (if diarization is enabled), and which provider produced it.
Archiving: configure an archive target (e.g. Hetzner Storage Box), and a daily job at 04:00 UTC scans for recordings past their active window and evaluates them against your retention policy. Check your Realtime admin panel for your tenant's current archive status before relying on it as your sole compliance retention mechanism.
Configure Compliance Profiles
Three compliance profiles (included free with every module): set complianceProfile on session creation to "hipaa", "pci", or "gdpr-strict". Once set, a session's profile can't be downgraded.
HIPAA profile: encrypted, isolated recording storage; TURN traffic restricted to your self-hosted relay (no third-party TURN); only BAA-covered AI providers (Anthropic, OpenAI) permitted; 7-year (2555-day) retention; consent required before recording; every event signed and audit-logged; end-to-end encryption available.
GDPR-strict profile: EU-only recording storage with no US transfers; TURN traffic restricted to your self-hosted relay; only EU-data-resident AI providers permitted; 30-day default retention; consent required; every event signed and audit-logged; all data stays in the EU; erasure requests processed immediately.
Retention enforcement: a daily job at 05:00 UTC scans ended sessions past their profile's retention window, deletes recordings and transcripts, anonymizes participant records, and emits a signed compliance event documenting exactly what was removed.
Complete Example — Telehealth Session with AI Scribe
1. Create a HIPAA-compliant telehealth session POST /v1/sessions { "type": "telehealth", "displayName": "Dr. Smith / Patient Consultation", "media": { "audio": true, "video": true }, "complianceProfile": "hipaa", "metadata": { "appointmentId": "appt_xyz" } }
2. Attach the session to the appointment record POST /v1/sessions/:id/attach { "resourceType": "health_appointment", "resourceId": "appt_xyz" }
3. Get ICE servers for the WebRTC clients GET /v1/sessions/:id/ice-servers
4. Summon the Telehealth Scribe agent POST /v1/agents/summon { "agentDefinitionId": "telehealth-scribe", "sessionId": "session_id", "contextPreamble": "Summoned into HIPAA-compliant telehealth consultation.", "displayName": "Telehealth Scribe", "idleTimeoutSec": 3600 }
5. The agent uses its available tools to write clinical notes: loads appointment context → loads patient history → writes a structured clinical note → updates the linked contact record
6. Capture consent from both participants POST /v1/compliance/consent { "recordingId": "recording_id", "participantId": "patient_id", "status": "given" } POST /v1/compliance/consent { "recordingId": "recording_id", "participantId": "doctor_id", "status": "given" } Recording starts once both consents are captured.
7. Recording is auto-transcribed Whisper.cpp runs locally (free) → transcript is available via the API Downstream: AeionClaw summarizes the visit, CRM creates a follow-up activity
8. Session ends → the agent runs a final summary turn → is dismissed gracefully The conversation's checkpoint is preserved on the invocation record