# How to prevent duplicate emails in AI Agent workflow when ready\_to\_email stays true

**URL:** <https://community.n8n.io/t/how-to-prevent-duplicate-emails-in-ai-agent-workflow-when-ready-to-email-stays-true/297603>\
**Category:** Questions\
**Tags:** node, workflow-building\
**Created:** [May 31, 2026, 1:09pm UTC](https://community.n8n.io/t/how-to-prevent-duplicate-emails-in-ai-agent-workflow-when-ready-to-email-stays-true/297603 "2026-05-31T13:09:39Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Hadiluno](https://dub1.discourse-cdn.com/n8n/user_avatar/community.n8n.io/hadiluno/32/176328_2.png) [@Hadiluno](https://community.n8n.io/u/Hadiluno)\
**Post date:** [May 31, 2026, 1:09pm UTC](https://community.n8n.io/t/how-to-prevent-duplicate-emails-in-ai-agent-workflow-when-ready-to-email-stays-true/297603/1 "2026-05-31T13:09:39Z")

</div>

## Describe the problem/error/question

Hi everyone,  
I’ve built a recruitment chatbot using the AI Agent node with Google Gemini, Telegram Trigger, Postgres Chat Memory, and Structured Output Parser. The bot interviews users in Algerian Darija and collects structured profile data (name, study field, skills, etc.).  
The workflow:  
Telegram Trigger → AI Agent → Postgres Memory → Structured Output Parser → IF node (checks ready\_to\_email === true) → Mailtrap (sends report to VP) → Send Message back to user  
The problem:  
Once the profile is complete, the AI sets ready\_to\_email: true and sends the email. But on the next user message, the AI still outputs ready\_to\_email: true (because the profile stays complete), so the IF node fires again and another duplicate email gets sent. This happens on every subsequent message.  
What I’ve tried:  
Added an email\_sent boolean flag to the JSON schema and told the AI to set it to true after the first email, and never set ready\_to\_email: true again after that  
Updated the IF node to check both ready\_to\_email === true AND email\_sent === false  
The AI sometimes forgets to set email\_sent or still outputs ready\_to\_email: true on later turns  
My question:  
Is there a better way to make sure the email node only fires once per conversation? I thought about using a database to store a flag, or maybe there’s a built-in n8n node that acts as a one-time gate? I found the “Execute Once” option but I believe that only works within a single workflow execution, not across multiple messages.  
Any advice on the cleanest way to handle this?  
Thanks!

## What is the error message (if any)?

## Please share your workflow

## Share the output returned by the last node

## Information on your n8n setup

- **n8n version: 2.22.4**
- **Database (default: SQLite): Postgresql (supabase)**
- **n8n EXECUTIONS\_PROCESS setting (default: own, main):**
- **Running n8n via (Docker, npm, n8n cloud, desktop app):n8n cloud**
- **Operating system: windows**

---

<div class="post-metadata">

**Author:** ![achamm](https://dub1.discourse-cdn.com/n8n/user_avatar/community.n8n.io/achamm/32/143734_2.png) [@achamm](https://community.n8n.io/u/achamm)\
**Post date:** [May 31, 2026, 1:10pm UTC](https://community.n8n.io/t/how-to-prevent-duplicate-emails-in-ai-agent-workflow-when-ready-to-email-stays-true/297603/2 "2026-05-31T13:10:41Z")

</div>

@Hadiluno cleanest fix is dont trust the LLM to remember email-sent state — externalize it. since u already have Supabase Postgres connected, add a 1-column table and gate the email node on it:

```sql
CREATE TABLE sent_emails (
  session_id TEXT PRIMARY KEY,
  sent_at TIMESTAMP DEFAULT NOW()
);

```

then drop these 2 nodes into ur workflow — one **before** the IF, one **after** Mailtrap:

then in ur existing IF node, change the condition to AND together:

- `{{ $('Structured Output Parser').item.json.ready_to_email }}` === `true`
- `{{ $('Check Email Sent').all().length }}` === `0`

now the LLM can flip ready\_to\_email a hundred times — the gate lives in the DB, not the model. quick Q: ur using telegram chat.id as the session key for the Postgres Chat Memory right? if so the same id works as the email-sent key, no extra plumbing.

---

<div class="post-metadata">

**Author:** ![kjooleng](https://dub1.discourse-cdn.com/n8n/user_avatar/community.n8n.io/kjooleng/32/184045_2.png) [@kjooleng](https://community.n8n.io/u/kjooleng)\
**Post date:** [May 31, 2026, 1:26pm UTC](https://community.n8n.io/t/how-to-prevent-duplicate-emails-in-ai-agent-workflow-when-ready-to-email-stays-true/297603/3 "2026-05-31T13:26:28Z")

</div>

Hi @Hadiluno

The problem is that you are asking the AI to act as a database. AI models are great at conversation, but they are “probabilistic,” meaning they can forget or ignore specific instructions over time. When you ask it to remember that an email was already sent, it eventually slips up and triggers the “ready” flag again because the user’s profile is still technically complete.

The solution is to move the “Email Sent” flag out of the AI’s head and into a real database table. Instead of trusting the AI to track the status, you create a simple list in Postgres that tracks each user’s ID and whether their email has been sent. This creates a “single source of truth” that never forgets.

In your workflow, you would add a step at the beginning to check this database for the user’s status. Then, your IF node will only send the email if two things are true: the AI says the profile is ready AND the database says the email hasn’t been sent yet. Once the email is sent, the workflow immediately updates the database to “true,” effectively locking the gate.

This approach is much cleaner because it simplifies the AI’s job. You can remove all the confusing “email\_sent” instructions from your prompt, allowing the AI to focus entirely on the interview. This makes the bot more reliable, reduces errors, and ensures that your VP only receives one professional report per candidate.

To implement this, you first need to run this SQL command in your Postgres database to create the status tracking table:

```sql
CREATE TABLE user_status (
    chat_id TEXT PRIMARY KEY,
    email_sent BOOLEAN DEFAULT FALSE
);

```

Here is the workflow

_ **Note:** You will need to re-select your Postgres credentials after importing._

---

<div class="post-metadata">

**Author:** ![Hadiluno](https://dub1.discourse-cdn.com/n8n/user_avatar/community.n8n.io/hadiluno/32/176328_2.png) [@Hadiluno](https://community.n8n.io/u/Hadiluno)\
**Post date:** [May 31, 2026, 2:19pm UTC](https://community.n8n.io/t/how-to-prevent-duplicate-emails-in-ai-agent-workflow-when-ready-to-email-stays-true/297603/4 "2026-05-31T14:19:44Z")

</div>

THANK YOU GUYS SO MUCH FOR THE HELP, IT’S WORKING NOW!!!, this issue was pissing me off for days. 💛💛

---

<div class="post-metadata">

**Author:** ![kjooleng](https://dub1.discourse-cdn.com/n8n/user_avatar/community.n8n.io/kjooleng/32/184045_2.png) [@kjooleng](https://community.n8n.io/u/kjooleng)\
**Post date:** [May 31, 2026, 2:21pm UTC](https://community.n8n.io/t/how-to-prevent-duplicate-emails-in-ai-agent-workflow-when-ready-to-email-stays-true/297603/5 "2026-05-31T14:21:06Z")

</div>

@Hadiluno please mark relevant answer as the solution, thank you!!!

---

<div class="post-metadata">

**Author:** ![achamm](https://dub1.discourse-cdn.com/n8n/user_avatar/community.n8n.io/achamm/32/143734_2.png) [@achamm](https://community.n8n.io/u/achamm)\
**Post date:** [May 31, 2026, 2:22pm UTC](https://community.n8n.io/t/how-to-prevent-duplicate-emails-in-ai-agent-workflow-when-ready-to-email-stays-true/297603/6 "2026-05-31T14:22:45Z")

</div>

Your welcome! Happy me and @kjooleng could help!

---

<div class="post-metadata">

**Author:** ![system](https://dub1.discourse-cdn.com/n8n/user_avatar/community.n8n.io/system/32/195824_2.png) [@system](https://community.n8n.io/u/system)\
**Post date:** [June 7, 2026, 2:23pm UTC](https://community.n8n.io/t/how-to-prevent-duplicate-emails-in-ai-agent-workflow-when-ready-to-email-stays-true/297603/7 "2026-06-07T14:23:07Z")

</div>

Closed on June 7, 2026, 2:23pm UTC

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.
