Repository navigation
fix(twilio): an acknowledgement said before a kept line reaches its question isn't its answer, and indications play whole while the flow keeps the agent uninterrupted - #1493
Conversation
…uestion isn't its answer, and indications play whole while the flow keeps the agent uninterrupted
Two things seen on one dev call (4bcd88e1):
- "Perfect.", said to "Someone will be out within the next three days." while the rest of the line ("... I just texted
it to you. Can you check if you got it?") still played, came in 2.8 s after the line went out and was taken as the
link checked; the request number went out next, before the caller heard the question. For a line played to the end,
an acknowledgement is now dropped as a backchannel tail until the question could have been heard: the words before
it, at the fastest speaking pace (20 characters a second), on top of TooSoonToAnswer. A line the caller may cut into
is left as it was.
- The recap said while the request went in, and the line before it, were each cut off by an interrupt 0 ms into them
with no words after it. An indication said while the flow keeps the agent uninterrupted now plays to the end too.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
✅ AegisCode Code Review Report: PassCounted: 5 Low. None of them blocks this change. Low · .../BotSharp.Plugin.Twilio/Services/ConversationRelayLines.cs:22 · business-logic: A lowercase initial does not necessarily indicate an abbreviation continuation.A lowercase initial does not necessarily indicate an abbreviation continuation. For example, in "I just texted you a link. did you get it?", the question is merged into the preceding statement, making the first question-bearing sentence index zero and returning an empty prefix. This contradicts the intended calculation using "the words before the first question" and can remove the additional acknowledgement delay. Normally capitalized questions remain supported. Suggested fix: [Needs Review - Inconclusive] Restrict continuation merging to recognized abbreviation boundaries, such as internal periods in a.m. and p.m., rather than treating every lowercase-starting piece as a continuation. Low · .../BotSharp.Plugin.Twilio/Services/ConversationRelaySession.cs:37 · Constant naming: Constant 'FastestSpokenCharsPerSecond' (line 37) is not UPPER_CASEConstant 'FastestSpokenCharsPerSecond' (line 37) is not UPPER_CASE Suggested fix: [Validated by static analysis] Rename 'FastestSpokenCharsPerSecond' to 'FASTEST_SPOKEN_CHARS_PER_SECOND' Low · .../BotSharp.Plugin.Twilio/Services/ConversationRelaySession.cs:91 · style: NoteLine now has four parameters, exceeding the C# standard's three-parameter limit, and introduces…NoteLine now has four parameters, exceeding the C# standard's three-parameter limit, and introduces another boolean flag. The current implementation is understandable, but the growing combination of timing and playback options makes call sites harder to maintain. Suggested fix: [Needs Review - Inconclusive] Group the line's timing and playback metadata into a small options or state object so NoteLine stays within the parameter limit without accumulating independent boolean flags. Low · .../BotSharp.Plugin.Twilio/Services/ConversationRelaySession.cs:385 · Line length: This line is 127 characters long; the maximum is 125This line is 127 characters long; the maximum is 125 Suggested fix: [Validated by static analysis] Wrap the line so that no line exceeds 125 characters Low · .../BotSharp.Plugin.Twilio/Services/ConversationRelaySession.cs:484 · Line length: This line is 126 characters long; the maximum is 125This line is 126 characters long; the maximum is 125 Suggested fix: [Validated by static analysis] Wrap the line so that no line exceeds 125 characters |
There was a problem hiding this comment.
🟡 Changes recommended
Three moderate issues remain: compound questions can still be misclassified, streamed kept lines do not preserve their keep state, and prerecorded indication prompts remain interruptible.
3 open issues
What changed in this PR
This pull request improves Twilio ConversationRelay timing and playback so acknowledgements are not treated as answers before an uninterrupted line reaches its question, and indications can play fully when uninterrupted speech is required.
Changes:
- Adds pre-question timing based on the text preceding the first question.
- Tracks whether the latest line must play uninterrupted.
- Applies uninterrupted playback behavior to spoken indications.
| File | Description |
|---|---|
| src/Plugins/BotSharp.Plugin.Twilio/Services/ConversationRelaySession.cs | Updates acknowledgement filtering, uninterrupted line state tracking, and indication playback behavior. |
| src/Plugins/BotSharp.Plugin.Twilio/Services/ConversationRelayLines.cs | Adds parsing for text occurring before the first question to support playback timing. |
Review effort: Lite
| var first = sentences.FindIndex(s => s.EndsWith('?')); | ||
| return first <= 0 ? string.Empty : string.Join(" ", sentences.Take(first)); |
| { | ||
| if (!_relay.DropBackchannelTails || _lastLineHeardSome || _lastLine == null || !_lastLine.Contains('?') | ||
| || DateTime.UtcNow >= _lastLineSentUtc + TooSoonToAnswer) | ||
| || DateTime.UtcNow >= _lastLineSentUtc + TooSoonToAnswer + UntilQuestionPlays()) |
| var keep = ReadKeepUninterrupted(); | ||
| foreach (var segment in indication.Split('|')) | ||
| { | ||
| var text = segment.Trim(); |

Why
Two things seen on one dev call:
TooSoonToAnswer(1 s), so it was taken as "yes, I got the link", and the request number went out before the caller heard the question.What
IsBackchannelTailnow waits until its question could have been heard:TooSoonToAnswerplus the words before the first question at the fastest speaking pace (20 characters a second,ConversationRelayLines.BeforeFirstQuestion). Only acknowledgements are dropped, as before; anything more than that is never dropped, and a line the caller may cut into is unchanged (Twilio stops it where they speak).ConversationRelayStates.KeepUninterrupted) plays to the end too.Tests
16 session tests over a fake WebSocket (not in the repo, which has no Twilio test project), run on this branch rebased on master:
BeforeFirstQuestionkeeps times such as "8 a.m. and 5 p.m.?" in one sentence.🤖 Generated with Claude Code