#20992: fix(tts): apply TTS processing to agentCommand outbound delivery path
commands
size: XS
Cluster:
Voice Call and TTS Improvements
## Summary
- The `deliverAgentCommandResult` path (cron announce, `sessions-send`, etc.) bypasses `dispatchReplyFromConfig`, so `[[tts:...]]` directive tags were never stripped and no audio was synthesised for these payloads
- Add `maybeApplyTtsToPayload` before outbound delivery so TTS tags are processed regardless of the delivery path
- Build `normalizedPayloads` from TTS-processed content so JSON envelope and return value reflect actually-delivered content
Split out from #20685 to keep that PR focused on feishu media support.
## Test plan
- [ ] Configure a cron/session-send agent with `[[tts:...]]` tags in output
- [ ] Verify TTS tags are stripped from delivered text
- [ ] Verify audio is synthesised and included as media in the outbound payload
- [ ] Verify `--json` output reflects TTS-processed content (not raw directive markup)
- [ ] Verify normal inbound reply flow is unaffected (no double processing)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
This PR fixes a bug where TTS directive tags (`[[tts:...]]`) were not being processed in the `deliverAgentCommandResult` code path used by cron announce and `sessions-send` commands. The fix applies TTS processing before outbound delivery and ensures JSON output reflects the actually-delivered content.
**Key changes:**
- Moved the empty payloads check earlier to avoid processing empty arrays
- Added `maybeApplyTtsToPayload` call before outbound delivery to process TTS tags for commands that bypass `dispatchReplyFromConfig`
- Updated to use TTS-processed payloads for both JSON normalization and actual delivery
- Added a follow-up fix to skip TTS synthesis when `deliveryTarget` is unresolved, avoiding unnecessary API calls when delivery will not occur
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge with minimal risk
- The changes are well-structured and focused on a specific bug fix. The logic correctly applies TTS processing before delivery, the early return for empty payloads is properly handled, and the follow-up fix appropriately guards against unnecessary API calls. The code follows existing patterns and includes clear explanatory comments.
- No files require special attention
<sub>Last reviewed commit: 3e34f2d</sub>
<!-- greptile_other_comments_section -->
<sub>(4/5) You can add custom instructions or style guidelines for the agent [here](https://app.greptile.com/review/github)!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#21110: fix(tts): deliver audio via structured mediaUrl instead of MEDIA: t...
by hydro13 · 2026-02-19
82.4%
#16089: fix(tts): clarify directive syntax in prompts and strip malformed tags
by kmixter · 2026-02-14
79.1%
#21513: Agents: track TTS media in duplicate filter state
by DevvGwardo · 2026-02-20
78.7%
#17244: fix: strip TTS tags from agent replies before delivery (#14652)
by robbyczgw-cla · 2026-02-15
76.9%
#19439: fix(tts): pass audioAsVoice flag through tool result pipeline
by brandonwise · 2026-02-17
76.7%
#13383: fix(cron): route text-only payloads through direct delivery
by Masha-L · 2026-02-10
76.6%
#19489: fix(voice-call): add echo suppression for TTS playback
by kalichkin · 2026-02-17
76.4%
#8317: fix(tts): add dynamic timeout and retry logic for ElevenLabs TTS
by camtang26 · 2026-02-03
75.3%
#19073: feat(voice-call): streaming TTS, barge-in, silence filler, hangup, ...
by odrobnik · 2026-02-17
75.1%
#6522: fix(cron): deliver original message when agent response is heartbea...
by sidmohan0 · 2026-02-01
74.9%