Real-time voice agent (OpenAI Realtime API) over Loop threads - #107
devin-ai-integration[bot] wants to merge 2 commits into
Conversation
D2M: Sat, Jun 20, 2026 (v6.20.26)
Co-Authored-By: bot_apk <apk@cognition.ai>
Original prompt from API User
|
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Summary
Adds a real-time voice interface (OpenAI Realtime API) that acts as a conversational router on top of the existing Loop thread/sub-agent system. The voice agent does not reason long-running itself — it creates/continues threads, hands work off to background agents, checks status, and speaks async updates back into the live conversation. Everything runs on-device; there is no new orchestration backend.
The core mapping is intentionally thin — a "thread" is a
SimpleConversation, and "sending a message" dispatches aSubAgent(exactly like the primary chat'sspawn_sub_agent). So the voice layer reuses all existing persistence, sub-agent execution, and completion-notification plumbing rather than introducing a parallel store.New module
LoopIOS/VoiceAgent/:LoopThreadModels— vocabulary:LoopThreadStatus(queued/running/waiting/complete/failed),LoopThreadUpdate(theLoopThreadUpdatedevent payload withspokenSummary+shouldInterrupt), and.loopThreadUpdatednotification.LoopThreadService— the local tool layer.createThread→ new conversation + dispatch sub-agent;sendMessage→ append + dispatch with thread context;status→ resolve from the thread's live sub-agent (falling back to the transcript); pluslistThreads/summarize. Tracks the latest sub-agent per thread.LoopThreadTools— Realtime function-tool schemas + JSON dispatcher for the 5 tools:createLoopThread,sendLoopMessage,getLoopThreadStatus,listLoopThreads,summarizeLoopThread.LoopThreadEventBridge— translates the existing.subAgentDidPostMessagecompletion signal into a speakable.loopThreadUpdatedevent so background work surfaces in a live session.RealtimeVoiceSession— owns the WebSocket towss://api.openai.com/v1/realtime, sendssession.update(server VAD, pcm16 in/out, tools), streams mic audio, plays back audio deltas, dispatches function calls, and injects thread updates as conversation items (withresponse.cancel+ playback flush whenshouldInterrupt).RealtimeAudioEngine— full-duplex 24 kHz mono PCM16 viaAVAudioEnginein.voiceChatmode (echo cancellation), with mic→PCM16 conversion and PCM16→float playback.VoiceSessionViewController— full-screen session UI reusingAvatarView, with mute/end controls and mic-permission handling.Wiring:
.globalsession (can create/route across threads)..threadsession; new messages default to continuing that conversation.Also:
NSMicrophoneUsageDescriptionadded toInfo.plist; the 7 new files are excluded from theLoopMac/LoopVisiontargets (they depend on UIKit/AVAudioSessionand iOS-only views).Deferred / notes
summarizeLoopThreadis transcript-based (no separate summarization model call yet).[BACKGROUND UPDATE] …) since the Realtime API conversation items don't take a system role.developdid not exist on the forktheashbhat/LoopHarnessand the Devin app lacked write access there, so this PR targetsgetathelas/LoopHarness:developper your instruction.Link to Devin session: https://app.devin.ai/sessions/d7346099fc4947efa319fa90ab05ed20