feat: add selectable phone call voice stacks - #52
Merged
Conversation
This was referenced Jul 31, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Executive Summary
call.endedreconciliation with exact-recipient, exact-once post-call SMS settlement.Description
INKBOX_VOICE_AI_AUTHORITY_MODE.doctor.mode=hosted_agentwith a required bounded reason and no authority override; Realtime and Inkbox TTS/STT sendmode=client_websocketwith the current media URL.call.endeddelivery without replacing mail, text, iMessage, A2A, or external-event subscriptions.>=0.5.9,<1.0.0everywhere.Reason
Operators need one explicit setup surface for who owns phone audio and one saved Voice AI authority default for inbound and outbound hosted calls. Hosted calls also need to complete promised work after hangup without allowing model memory, duplicate delivery, restart, or an ambiguous provider outcome to redirect or replay an external write.
Decisions
hosted_agent.consult_agentbridge into Claude Code. Hermes' direct realtime contact-tool scenario is not applicable because Claude does not expose that host-specific surface.disabled.Testing
Live-test inventory
test_inbound_call_inkbox_tts_stt: proves a direct inbound client-WebSocket call has two-way audio, uses Inkbox STT/TTS, and persistsvoicemail_detection=disabled. This closes the prompt/audio-only false positive where the actual call record could retain the product default.test_outbound_call_realtime: correlates the driver's fresh inbound media leg with the AUT's fresh outbound request, proves two-way audio through OpenAI Realtime, and verifies disabled voicemail detection on the exact AUT-owned record. This closes both the uninspected-policy gap and the wrong-owner false failure where the driver's independent inbound default was asserted instead.test_outbound_call_hosted_and_post_call_wakeup: pairs fresh driver and AUT legs, requires hosted mode, non-empty reason, saved effective authority, disabled voicemail detection, current caller transcript plus matching open action before hangup, call-ID-scoped reconciliation, one exact-target sender row with the current speech-safe marker, and a full duplicate grace window. This removes acknowledgement/arbitrary-delay false positives, stale-call and wrong-leg races, recipient-inbox ambiguity, and duplicate-send false negatives.test_email_request_gets_call: correlates exactly one fresh driver inbound leg with exactly one fresh AUT outbound leg, observes the full duplicate grace window, and verifies disabled voicemail detection on the AUT-owned request. This closes stale-call, wrong-owner, prompt-only, and duplicate-call gaps.test_sms_request_gets_call: applies the same two-owner correlation, duplicate rejection, and exact AUT policy assertion to the SMS-triggered path. This closes the same stale/wrong-leg race without treating the driver's independent inbound default as the agent's request policy.test_reports_sender_details: explicitly asks for the full known email and phone while keeping exact contact-card assertions. This closes a live false negative where the model correctly reported the name and phone but referred to the email generically because the prompt only explicitly required the phone.Validation
git diff --check: passed.23d406fe73960aec9a26f6da2115692735535b29.Related PRs