feat(whatsapp): support inbound voice notes (#288) - #299
Merged
robertocarlous merged 2 commits intoJul 24, 2026
Conversation
Transcribe Twilio WhatsApp audio attachments into text intents: - webhook schema accepts optional Body + media fields (passthrough) - route parses audio media and passes it to the handler - media downloader + transcription provider registry (OpenAI) - pending-confirmation flow for transcribed actions - unit tests and audio fixtures
Making `Body` optional for voice notes (Neurowealth#288) also let a payload with neither text nor media reach the Twilio signature check, turning the expected 400 into a 403. Require Body or MediaUrl0 via a refinement, which adds no keys and so leaves the signed params intact. Also applies Prettier to the files that failed `format:check`.
7 tasks
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.
Closes #288.
Adds support for inbound WhatsApp voice notes, so users can speak a command
("deposit 50 usdc", "what's my balance") instead of typing it.
How it works
Bodybecomesoptional, since a voice-only message carries no text.
behind a registry so a different backend can be swapped in without touching
the handler.
parseIntentNLP path — voice andtext converge on the same intent pipeline, so no command logic is duplicated.
routes through a pending-confirmation step: the bot echoes back what it heard
and waits for confirmation before acting. Read-only intents answer directly.
Notes for review
a "voice notes unavailable" reply rather than erroring, so this is inert until
the API key is set.
attachment can't run up transcription spend.
Testing
voiceHandlersuite coveringthe transcription path, the confirmation flow, and rejection of unsupported
media.
tsc, production build, andprisma validateall clean.main(b3c6f38); no conflicts.🤖 Generated with Claude Code