Skip to content

fix(voice-call): play inbound greeting for Twilio answered calls#29121

Merged
steipete merged 3 commits intoopenclaw:mainfrom
xinhuagu:fix-29101-twilio-inbound-greeting
Mar 2, 2026
Merged

fix(voice-call): play inbound greeting for Twilio answered calls#29121
steipete merged 3 commits intoopenclaw:mainfrom
xinhuagu:fix-29101-twilio-inbound-greeting

Conversation

@xinhuagu
Copy link
Contributor

@xinhuagu xinhuagu commented Feb 27, 2026

Summary

  • remove the Twilio early-return in CallManager.maybeSpeakInitialMessageOnAnswered
  • let Twilio follow the same initial-message path as other providers when calls are answered
  • expand manager tests to assert notify-mode initial greeting is spoken for both Plivo and Twilio

Why

Inbound Twilio calls were creating metadata.initialMessage but never speaking it, because answered-call handling explicitly skipped Twilio.

Fixes #29101

Testing

  • pnpm -C openclaw-repo test extensions/voice-call/src/manager.test.ts

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 27, 2026

Greptile Summary

Removes Twilio-specific early-return in maybeSpeakInitialMessageOnAnswered that was preventing inbound Twilio calls from speaking the initial greeting. The Twilio provider has built-in fallback handling for TTS failures, so this special case is no longer needed.

Key changes:

  • Removed 6 lines from extensions/voice-call/src/manager.ts:157 that skipped Twilio in the answered-call handler
  • Updated test to verify both Plivo and Twilio providers speak initial message in notify mode using it.each

Testing:

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The change is a straightforward bug fix that removes an overly cautious early-return. The Twilio provider already has robust fallback handling for TTS failures (extensions/voice-call/src/providers/twilio.ts:563-599), so the removed special case is unnecessary. Tests now explicitly verify both providers work correctly, and all 13 tests pass.
  • No files require special attention

Last reviewed commit: 39f45e3

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 39f45e38f2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

return;
}

void this.speakInitialMessage(call.providerCallId);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reintroduce Twilio skip for answered-message playback

Calling speakInitialMessage unconditionally on call.answered now affects Twilio notify calls, but Twilio notify mode already injects a one-shot <Say><Hangup/> TwiML in initiateCall. This means answered callbacks can trigger a second playTts update that overwrites the notify flow (potentially replacing immediate hangup with <Gather>) or fails after the call has already ended, and either way initialMessage gets cleared so it cannot be retried on stream connect. This regression is specific to Twilio answered events and changes notify-call behavior from single-play/auto-end to duplicate or inconsistent playback.

Useful? React with 👍 / 👎.

@xinhuagu
Copy link
Contributor Author

@chatgpt-codex-connector Good catch on Twilio notify-mode behavior. I rebased this PR and will validate answered-event playback against the existing Twilio Say+Hangup flow to avoid duplicate/overwriting playback. If conflict is confirmed, I will restore the Twilio guard (or narrow the condition) and update tests accordingly.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 71a11386cd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

return;
}

void this.speakInitialMessage(call.providerCallId);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restore Twilio notify guard on answered callbacks

For Twilio outbound calls in notify mode, initiateCall already provisions a one-shot <Say>...<Hangup/> TwiML, but this answered-path now always triggers speakInitialMessage again. That second path calls playTts (which updates the live call to TwiML with <Gather>) and clears metadata.initialMessage before success is confirmed, so answered status callbacks can overwrite the notify flow, cause duplicate playback, or drop the message if the call already ended.

Useful? React with 👍 / 👎.

@xinhuagu
Copy link
Contributor Author

Validation update: I re-ran after rebase and it passes (12/12), including the Twilio/Plivo initial-notify greeting path. Current remaining red CI is the known Windows Feishu proxy test, unrelated to this voice-call change.

@xinhuagu
Copy link
Contributor Author

Clean follow-up: validated after rebase; voice-call manager test suite passes (12/12), including Twilio/Plivo initial-notify greeting behavior. Remaining red CI is the known Windows Feishu proxy test and appears unrelated to this voice-call change.

@xinhuagu xinhuagu force-pushed the fix-29101-twilio-inbound-greeting branch from 41d6cdf to a9cfed5 Compare February 28, 2026 21:02
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a9cfed53b5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

return;
}

void this.speakInitialMessage(call.providerCallId);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Skip Twilio notify replay on answered callbacks

Fresh evidence in this revision: Twilio notify calls still deliver a one-shot <Say><Hangup/> via stored TwiML and separate status callbacks (extensions/voice-call/src/providers/twilio.ts), but this new unconditional call to speakInitialMessage on call.answered makes those status callbacks invoke playTts again for notify mode. That can replace the notify hangup flow with <Gather>/second playback (or fail if the call already ended), and speakInitialMessage clears metadata.initialMessage before confirming playback, so the greeting is lost on failure (extensions/voice-call/src/manager/outbound.ts).

Useful? React with 👍 / 👎.

@xinhuagu xinhuagu force-pushed the fix-29101-twilio-inbound-greeting branch from a9cfed5 to 9b87505 Compare February 28, 2026 21:22
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9b87505993

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

return;
}

void this.speakInitialMessage(call.providerCallId);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep Twilio notify calls out of answered greeting replay

For Twilio outbound notify calls, the provider already serves one-shot notify TwiML (<Say>...<Hangup/>) from initiateCall, so replaying speakInitialMessage on every call.answered introduces a second playback path that can overwrite the notify flow with playTts call updates (or fail after hangup). In this path speakInitialMessage clears metadata.initialMessage before confirming playback, so a failed replay also drops the greeting entirely; this regression is introduced by removing the Twilio skip and affects answered status-callback handling for Twilio notify mode.

Useful? React with 👍 / 👎.

@steipete steipete force-pushed the fix-29101-twilio-inbound-greeting branch from 9b87505 to b8f32ce Compare March 2, 2026 23:54
@steipete steipete merged commit dba47f3 into openclaw:main Mar 2, 2026
10 checks passed
@steipete
Copy link
Contributor

steipete commented Mar 2, 2026

Landed via temp rebase onto main.

  • Gate: pnpm lint && pnpm build && pnpm test
  • Land commit: b8f32ce
  • Merge commit: dba47f3

Thanks @xinhuagu!

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b8f32cea65

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

return;
}

void this.speakInitialMessage(call.providerCallId);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Skip manager TTS for Twilio notify answered events

maybeSpeakInitialMessageOnAnswered now unconditionally calls speakInitialMessage for Twilio, but outbound Twilio notify calls already deliver metadata.initialMessage through provider-side notify TwiML (generateNotifyTwiml served from TwilioProvider.initiateCall/generateTwimlResponse). Because Twilio status callbacks explicitly include answered, this path now runs on every notify call and can replay the greeting (or override the original <Hangup/> flow with a second TTS update), which changes call behavior and duration for existing Twilio notify users.

Useful? React with 👍 / 👎.

dawi369 pushed a commit to dawi369/davis that referenced this pull request Mar 3, 2026
OWALabuy pushed a commit to kcinzgg/openclaw that referenced this pull request Mar 4, 2026
zooqueen pushed a commit to hanzoai/bot that referenced this pull request Mar 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: voice-call Channel integration: voice-call size: XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: voice-call plugin: inboundGreeting not used for Twilio inbound calls

2 participants