#20164: fix(webchat): strip reply directive tags before rendering assistant messages
app: web-ui
size: S
Cluster:
Model Reasoning Fixes
## Problem
Closes #20063
In webchat (and `openclaw-control-ui`), assistant messages that include `[[reply_to_current]]` or `[[reply_to: <id>]]` reply directive tags are rendered with the raw tag text visible to the user:
```
[[reply_to_current]] Here is my response...
```
These tags are routing directives that instruct the gateway where to send a quoted/threaded reply on supported channels (Telegram, Discord, etc.). They are stripped during outbound delivery on those channels, but the webchat UI's `extractText()` pipeline never applied equivalent stripping.
## Root Cause
`ui/src/ui/chat/message-extract.ts` `extractText()` applies `stripThinkingTags()` for assistant messages, but has no equivalent step for inline directive tags. The backend stripping in `src/utils/directive-tags.ts` (`parseInlineDirectives`) is never called on the UI side.
## Fix
- **`ui/src/ui/format.ts`**: Add `stripReplyTags()` — a mirror of `REPLY_TAG_RE` from `directive-tags.ts` — to strip `[[reply_to_current]]` and `[[reply_to: <id>]]` patterns.
- **`ui/src/ui/chat/message-extract.ts`**: Apply `stripReplyTags()` after `stripThinkingTags()` for all assistant message content paths (string, array, `.text` fallback).
- **`ui/src/ui/chat/message-extract.test.ts`**: Add test cases covering all stripping scenarios.
## Behaviour
| Before | After |
|--------|-------|
| `[[reply_to_current]] Here is my response.` | `Here is my response.` |
| `[[ reply_to: abc123 ]] Here is my response.` | `Here is my response.` |
Non-assistant messages (user, system) are unaffected.
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Adds UI-side stripping of `[[reply_to_current]]` and `[[reply_to: <id>]]` directive tags from assistant messages in the webchat UI, mirroring the backend stripping already done during outbound channel delivery. The fix adds a `stripReplyTags()` function in `ui/src/ui/format.ts` and applies it in all three content extraction paths of `extractText()` in `message-extract.ts`.
- The regex in the UI (`REPLY_TAG_RE`) correctly mirrors the backend pattern from `src/utils/directive-tags.ts`, minus the capture group since the UI only needs stripping, not ID extraction.
- Stripping is applied consistently across all assistant message content paths (string, array, `.text` fallback) and correctly excluded from non-assistant (user/system) messages.
- Test coverage is solid, covering `reply_to_current`, `reply_to: <id>`, whitespace variants, user message passthrough, and content arrays.
- Note: `[[audio_as_voice]]` is another directive tag that is similarly not stripped in the UI, but this is out of scope for the reported issue (#20063).
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge — it adds display-only stripping of directive tags with no risk to backend logic or data flow.
- The change is narrow and well-scoped: a single new pure function (stripReplyTags) applied consistently in one file. The regex correctly mirrors the backend pattern. Tests cover all relevant scenarios. No side effects on non-assistant messages. No changes to backend logic or data models.
- No files require special attention.
<sub>Last reviewed commit: 64e6c77</sub>
<!-- greptile_other_comments_section -->
**Context used:**
- Context from `dashboard` - CLAUDE.md ([source](https://app.greptile.com/review/custom-context?memory=fd949e91-5c3a-4ab5-90a1-cbe184fd6ce8))
<!-- /greptile_comment -->
Most Similar PRs
#23073: fix(ui): strip reply directive tags from assistant messages in WebC...
by x4v13r1120 · 2026-02-22
91.1%
#23144: fix(ui): strip reply directive tags from assistant messages in WebC...
by echoVic · 2026-02-22
90.9%
#17244: fix: strip TTS tags from agent replies before delivery (#14652)
by robbyczgw-cla · 2026-02-15
83.1%
#22832: fix: strip [[reply_to_current]] directive from chat history
by willkriski · 2026-02-21
82.7%
#23370: fix: strip [[reply_to_current]] tags from WebChat + validate invoke...
by alexmelges · 2026-02-22
82.4%
#23246: fix(gateway): strip reply directive tags from finalized webchat mes...
by SidQin-cyber · 2026-02-22
81.2%
#16733: fix(ui): avoid injected newlines when tool output is hidden
by jp117 · 2026-02-15
81.2%
#18876: fix(outbound): strip DSML function-call markup before delivery
by BinHPdev · 2026-02-17
79.7%
#8334: fix(webchat): Filter NO_REPLY messages from chat history
by vishaltandale00 · 2026-02-03
77.6%
#20231: fix: strip untrusted metadata blocks from chat history
by MisterGuy420 · 2026-02-18
77.1%