# AI bot “Retry” creates a duplicate reply instead of regenerating, in public (non-PM) topics

**URL:** https://meta.discourse.org/t/ai-bot-retry-creates-a-duplicate-reply-instead-of-regenerating-in-public-non-pm-topics/407562
**Category:** Bug
**Tags:** ai, ai-bot
**Created:** [July 14, 2026, 11:20am UTC](https://meta.discourse.org/t/ai-bot-retry-creates-a-duplicate-reply-instead-of-regenerating-in-public-non-pm-topics/407562 "2026-07-14T11:20:31Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![Overgrow](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/overgrow/32/478189_2.png) [@Overgrow](https://meta.discourse.org/u/Overgrow)
#### Post date: [July 14, 2026, 11:20am UTC](https://meta.discourse.org/t/ai-bot-retry-creates-a-duplicate-reply-instead-of-regenerating-in-public-non-pm-topics/407562/1 "2026-07-14T11:20:31Z")

</div>

### Severity

Normal — but high-nuisance on busy public topics: repeated Retry clicks flood the topic with duplicate bot posts, so to members it looks like the bot is “posting on its own / stuck in a loop.”

### Platform

- Server: Discourse core `main` (2026.7.x line), reproduced against latest `origin/main` (`dbf5eedac40`, 2026-07-14). `discourse-ai` bundled in core.
- Client: reproduced from multiple browsers/devices (desktop Chrome, Android Chrome, iOS Safari) — it is server-side, so client is irrelevant.

### Description

**Actual result:** In a **public topic** , clicking **Retry** on an AI-bot reply **appends a brand-new bot post** to the topic. The original reply is left untouched, so each Retry adds another post. N retries → N extra posts.

**Expected result:** Retry should **regenerate the existing bot reply in place** (replace its content), the same way it does inside an AI-bot **PM / DM** conversation. No new post should be created.

### Steps to reproduce (from a fresh Discourse)

1. Enable Discourse AI + AI bot; create/enable an AI **agent (persona)** with a bot user, and turn on **“Allow topic mentions”** so it can answer in public topics (`allow_topic_mentions`). Add your user’s group to the agent’s allowed groups and to `ai_bot_allowed_groups`.
2. In a **public** topic, `@mention` the bot in a post so it replies.
3. On the bot’s reply, open the post admin/wrench menu and click **Retry** (the regenerate action → `POST /discourse-ai/ai-bot/post/:post_id/retry`).
4. **Observe:** a _new_ bot reply is appended instead of the existing one being regenerated. Repeat Retry → one extra post each time.
5. For contrast, do the same inside a **PM with the bot** : Retry correctly regenerates in place (no duplicate). The divergence between PM and public topic is the tell.

Reproduces 100% of the time on public topics.

### Root cause (code pointers, current `origin/main`)

- `BotController#retry_response` (`plugins/discourse-ai/app/controllers/discourse_ai/ai_bot/bot_controller.rb`) enqueues `Jobs::CreateAiReply` with **`reply_post_id: post.id`** — i.e. “regenerate this existing post.”
- `Jobs::CreateAiReply` loads it as `reply_post` and passes it to `Playground#reply_to(..., existing_reply_post: reply_post)`.
- In `Playground#reply_to` (`plugins/discourse-ai/lib/ai_bot/playground.rb`):
  - `stream_reply = post.topic.private_message? if stream_reply.nil?` → **`false` for public topics** (~L518).
  - `existing_reply_post` is only consumed inside the **`if stream_reply`** branch (`reply_post = existing_reply_post`, ~L538).
  - The **non-streaming `else` branch** (~L662) unconditionally does `PostCreator.create!(...)`, appending a new post and never touching the post being retried.

So for any non-PM topic, the “regenerate in place” intent from `retry_response` is silently dropped and a duplicate is created instead. (The same asymmetry means public-topic bot replies are non-streaming, which is the pre-existing behaviour; the bug is specifically that Retry’s `existing_reply_post` is ignored on that path.)

### Suggested fix (direction only)

Honour `existing_reply_post` regardless of streaming — e.g. in the non-streaming branch, if `existing_reply_post` is present, `revise` it instead of calling `PostCreator.create!`; or decouple the “reuse existing post” decision from `stream_reply`.

### [Safe mode](https://meta.discourse.org/t/53504?silent=true)

N/A — server-side plugin behaviour, independent of themes/site JS.

---

<div class="post-metadata">

### Author: ![Overgrow](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/overgrow/32/478189_2.png) [@Overgrow](https://meta.discourse.org/u/Overgrow)
#### Post date: [July 14, 2026, 1:49pm UTC](https://meta.discourse.org/t/ai-bot-retry-creates-a-duplicate-reply-instead-of-regenerating-in-public-non-pm-topics/407562/2 "2026-07-14T13:49:49Z")

</div>

Btw I see that “[Safe mode](https://meta.discourse.org/t/53504?silent=true)” was turned automatically into a link.. Can anybody suggest how this is done? 🙂 Thx!

---

<div class="post-metadata">

### Author: ![Moin](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/moin/32/554653_2.png) [@Moin](https://meta.discourse.org/u/Moin)
#### Post date: [July 14, 2026, 2:20pm UTC](https://meta.discourse.org/t/ai-bot-retry-creates-a-duplicate-reply-instead-of-regenerating-in-public-non-pm-topics/407562/3 "2026-07-14T14:20:53Z")

</div>

#watched-words → link  
Ref [Watched Words Reference Guide](https://meta.discourse.org/t/watched-words-reference-guide/241735/)

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [July 14, 2026, 10:09pm UTC](https://meta.discourse.org/t/ai-bot-retry-creates-a-duplicate-reply-instead-of-regenerating-in-public-non-pm-topics/407562/4 "2026-07-14T22:09:55Z")

</div>

Thanks for the report, this should address it

> <https://github.com/discourse/discourse/pull/41715>
>
> Previously, clicking retry on an AI bot reply in a public (non-PM) topic appende…d a brand-new bot post, because \`Playground#reply\_to\` only honored \`existing\_reply\_post\` in the streaming path used by PMs.
> 
> This change revises the existing reply in place in the non-streaming path as well, keeping an edit revision so the previous answer remains visible in the post history, and refreshes the post's LLM/agent custom fields on retry.
> 
> Reported at https://meta.discourse.org/t/407562

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [July 27, 2026, 11:00am UTC](https://meta.discourse.org/t/ai-bot-retry-creates-a-duplicate-reply-instead-of-regenerating-in-public-non-pm-topics/407562/5 "2026-07-27T11:00:52Z")

</div>

This topic was automatically closed after 11 days. New replies are no longer allowed.
