openalice-voice-agent
[Atlas card](https://atlas.blal.pro/repos/openalice-voice-agent)
Architecture rating
Strong substrate adoption: valid manifest (100), drift 100, zero circular deps, zero dead imports, AGENTS.md + deny.toml present — uniform with org conventions, only 1 god module/deep-nesting blemish.
Good manifest summary + 7 @feature annotations + AGENTS.md, but README is a bare Atlas-card stub and 27 missing docstrings across modules; roadmap 80, features axis weakest at 76.
Realtime STT→LLM→TTS loop with one max-complexity-51 hotspot and a single TODO; no visible evidence of SIGTERM graceful shutdown, timeouts/retries on LLM/TTS calls, or idempotency — code_health 100 but reliability primitives unconfirmed.
deny.toml present (cargo-deny supply-chain/license gate) is the only concrete control; no manifest evidence of authn/authz on SFU/LLM join, token/secret handling, rate-limiting or security headers — graded conservatively for absent signals.
Only a GET /health probe is exposed (and it currently fails Atlas probe — no https endpoint in manifest); no metrics, tracing, or structured-log signals surfaced for a latency-sensitive voice pipeline.
Stateless pipeline — owns 0 tables, no migrations dir, no schema/FK/RLS/GDPR surface; nothing wrong but nothing to credit, so scored low on absence rather than design quality.
No tests/ directory and no test signal from inspector (no count, critical STT/LLM/TTS paths uncovered); any inline #[cfg(test)] is unverified — graded as effectively absent.
source · auto-grader-2026-06-16
Ecosystem manifest
.atlas-deps.ymlRust AI voice participant — STT→A2A LLM→TTS pipeline that joins openalice-voice SFU rooms as an agent.
- openalicehttpvia A2A_URLExternal A2A endpoint — forward transcribed user utterances and receive LLM reply text
- via cargoConnectorEvent / ToolCall types and A2A message schema
- via cargoShared Axum/reqwest/JWT plumbing used at compile time
- via VOICE_SFU_WS_URLJoin SFU voice rooms as a participant; receive Opus audio frames and send TTS audio back
- via RT_URLPersona side-channel — emit emotion/expression events so the VRM avatar reacts to conversation
- VOICE_AGENT_PORT
- VOICE_AGENT_MODE
- VOICE_AGENT_AUTO_JOIN_ROOM
- VOICE_SFU_WS_URL
- VOICE_SFU_API_URL
- A2A_URL
- A2A_API_KEY
- RT_URL
- STT_PROVIDER
- STT_API_URL
- STT_API_KEY
- STT_MODEL
- TTS_PROVIDER
- TTS_API_URL
- TTS_API_KEY
- TTS_VOICE_ID
- TTS_MODEL
- VAD_THRESHOLD
- SILENCE_DURATION_MS
- MAX_AUDIO_DURATION_MS
- http_endpoint: GET /health
- docker_image: openalice-voice-agent
Roadmap · what's planned next
- voice-agent.orchestrator.spawn-on-a2a-joinP3planned0%Spawn agent on A2A 'join voice room' task instead of relying on VOICE_AGENT_AUTO_JOIN_ROOM bootstrap env.
- voice-agent.stt.streaming-whisperP3planned2%Replace per-utterance multipart POST with streaming Whisper (or Deepgram) for sub-500ms transcript latency.
- voice-agent.tts.elevenlabs-streamingP4planned2%Wire ElevenLabs streaming WebSocket TTS path so first audio chunk plays before the full sentence is synthesized.
- voice-agent.rt.viseme-from-ttsP4planned2%Derive real lipsync visemes from TTS audio (Opus PCM → phoneme estimator) instead of the current placeholder array.
Code composition
tokei · loc- Rust96.4%
- TOML3.6%
- Rust96.4%
- TOML3.6%
- Rust96.4%· 912
- TOML3.6%· 34
| Language | % code | code | comments | blanks | files |
|---|---|---|---|---|---|
| Rust | 96.4% | 912 | 71 | 153 | 10 |
| TOML | 3.6% | 34 | 10 | 2 | 2 |
| Markdown | 0.0% | 0 | 105 | 42 | 2 |
Telemetry ribbon · last 90 days
5 eventsvoice-agent/llm
1 feature- voice-agent.llm.bridgesrc/a2a_client.rs:1A2A JSON-RPC 2.0 client in src/a2a_client.rs. Calls tasks/send on the openalice A2A gateway (A2A_URL) with the transcript as a user message and channel metadata "voice". Extracts the response text from result.history[-1].parts[0].text.
voice-agent/metrics
1 feature- voice-agent.http.metricssrc/main.rs:6GET /metrics — Prometheus text exposition with `voice_agent_up`,api:GET /metrics
voice-agent/persona
1 feature- voice-agent.persona.rt-emittersrc/rt_emitter.rs:1Real-time Persona side-channel in src/rt_emitter.rs. Sends WebSocket "mutate" events to openalice-rt for the agent persona: emotion state (thinking/speaking/neutral) and lipsync viseme weights (placeholder float array). Failure is non-fatal; the pipeline continues without RT if unreachable.
voice-agent/service
1 feature- voice-agent.service.cratesrc/main.rs:1Binary crate `openalice-voice-agent` (Tokio + Axum runtime). Exposes GET /health and GET /metrics; spawns AgentManager background task that joins SFU rooms and runs the voice pipeline on demand. Entry point: src/main.rs.
voice-agent/stt
1 feature- voice-agent.stt.pipelinesrc/stt.rs:1Speech-to-text stage. Trait SttProvider in src/stt.rs. Concrete backend: OpenAiStt — POSTs WAV to OpenAI Whisper (default model: whisper-1, configurable via STT_MODEL). PCM→WAV conversion is performed inline by OpusCodec::pcm_to_wav.
voice-agent/tts
1 feature- voice-agent.tts.pipelinesrc/tts.rs:1Text-to-speech stage. Trait TtsProvider + enum TtsBackend in src/tts.rs. Two concrete backends selectable at runtime via TTS_PROVIDER: OpenAiTts (requests response_format "opus"/OGG Opus bytes) and ElevenLabsTts (v1 API with stability/similarity_boost tuning). Audio bytes are forwarded as binary WebSocket frames to the SFU.
voice-agent/vad
1 feature- voice-agent.vad.energysrc/vad.rs:1Energy-based voice activity detector in src/vad.rs. is_speech() computes RMS over i16 PCM frames against a configurable threshold (VAD_THRESHOLD, default 0.5 normalised). VadState tracks speech/silence transitions and fires speech-end events after SILENCE_DURATION_MS (default 1500ms) of sustained quiet.