Skip to content

feat(whatsapp): support inbound voice notes (#288) - #299

Merged
robertocarlous merged 2 commits into
Neurowealth:mainfrom
B-Hands:feat/whatsapp-voice-notes-288
Jul 24, 2026
Merged

feat(whatsapp): support inbound voice notes (#288)#299
robertocarlous merged 2 commits into
Neurowealth:mainfrom
B-Hands:feat/whatsapp-voice-notes-288

Conversation

@Anuoluwapo25

Copy link
Copy Markdown
Contributor

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

  1. The Twilio webhook now accepts audio media alongside text. Body becomes
    optional, since a voice-only message carries no text.
  2. Audio is fetched via a media downloader with size and MIME-type limits.
  3. The clip is transcribed through a pluggable provider (OpenAI Whisper in v1),
    behind a registry so a different backend can be swapped in without touching
    the handler.
  4. The transcript is fed into the existing parseIntent NLP path — voice and
    text converge on the same intent pipeline, so no command logic is duplicated.
  5. Because transcription is lossy, any state-changing intent (deposit/withdraw)
    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

  • Transcription is opt-in. With no provider configured the webhook degrades to
    a "voice notes unavailable" reply rather than erroring, so this is inert until
    the API key is set.
  • No schema or migration changes.
  • Unsupported/oversized audio is rejected before any provider call, so a bad
    attachment can't run up transcription spend.

Testing

  • 287 unit tests pass (27 suites), including a new voiceHandler suite covering
    the transcription path, the confirmation flow, and rejection of unsupported
    media.
  • tsc, production build, and prisma validate all clean.
  • Branch is based directly on current main (b3c6f38); no conflicts.

🤖 Generated with Claude Code

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`.
@robertocarlous
robertocarlous merged commit c268ebd into Neurowealth:main Jul 24, 2026
7 checks passed
@grantfox-oss grantfox-oss Bot mentioned this pull request Jul 24, 2026
7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Voice Message Support for WhatsApp

2 participants