Interactive Teams Agent <--> AI

Hello,

I have a workflow that uses a Teams conversation as its entry point. I already have several criteria in place to filter requests. Currently, the flow is: one request = one response in Teams, followed by the end of the conversation.

I’ve added an n8n AI agent to leverage data from a database. The simple “one request = one response” flow works fine. Now, I want the user to be able to have a back-and-forth conversation with the agent. For example:

  • User: Give me the address for the client “foobar”.
  • Agent: I have several clients with that name: list of clients. Which one do you want?
  • User: The third one.

My problem is that every message sent by the user is treated as a new one; consequently, the workflow restarts, and the agent “forgets” the previous interaction.

I tried putting the agent inside a loop, but that doesn’t seem to be the right approach :frowning:

Do you have any suggestions?
Thanks in advance.

Information on your n8n setup

  • n8n version: 2.29.9
  • Database (default: SQLite):
  • n8n EXECUTIONS_PROCESS setting (default: own, main):
  • Running n8n via (Docker, npm, n8n cloud, desktop app): Docker
  • Operating system: Linux
1 Like

The loop isn’t the fix, and it’s worth understanding why: each Teams message arrives as a separate execution, and n8n executions are stateless. Nothing survives between them unless you store it somewhere. Looping inside one execution only helps if the whole conversation happens inside that single run, which it doesn’t here, because the user’s next message comes minutes later through a fresh trigger.

What you want is persistent memory keyed by the conversation, not a loop:

Attach a Memory node to the AI Agent (Postgres Chat Memory or Redis Chat Memory rather than the in-memory Simple Memory, which dies with the execution and will not survive Docker restarts either).

Set the session key to the Teams conversation ID, not to a static value. Every message from that same Teams thread then loads the same history, so “the third one” resolves against what the agent said last time. If you use the same key for everyone, users will see each other’s context, so this field is the one to get right.

Keep a window on it (last N messages) so the context doesn’t grow forever and your token costs stay predictable.

One thing worth adding while you’re there: if the user’s answer is ambiguous (“the third one” when the agent listed nothing), the agent should say it doesn’t know rather than guess a client record. Wrong addresses coming back from a database lookup are the failure people notice.

1 Like

@flipflip The Core Key: UUID, use the “Teams UUID”
If you generate a brand new UUID every time the workflow runs, the AI will still treat it as a new chat. The easiest approach is to grab the Unique ID that Microsoft Teams already sends in its payload and use it as your Session ID.

Step-by-Step

  1. Add a Memory node to your AI Agent
    You need to connect a Memory node to the left side of your AI Agent node.

  2. Configure the Session ID in the Memory node
    Click to open the Memory node. You will see a field named Session ID (If you don’t see it, click on Add Field / Parameter and select Session ID).

  3. Map the ID from the Teams Trigger
    In the Session ID field, map the variable coming from your Microsoft Teams Trigger. You have 2 options depending on your needs:

Remember by “Chat Room/Thread” (Recommended):
Extract the Conversation ID from Teams, for example:
{{ $json.conversation.id }} or {{ $json.message.conversation.id }}
(Pros: If chatting in a group/channel, the AI remembers the context of that specific thread)

Remember by “Individual User”:
Extract the User ID of the person typing, for example:
{{ $json.from.id }}
(Pros: No matter which chat room this user types from, the AI will remember the conversation history with this specific person)

How does the system work after this setup?
Request 1: User types “Give me the address for the client foobar”

Teams sends the message with Conversation ID = “abc-123”

The AI Agent receives the message and binds its memory to Session ID “abc-123”

The AI replies “I have several clients… Which one do you want?” (and saves this history)

Request 2: User replies “The third one”

The workflow restarts from the beginning!

But this time, Teams sends the message with the same Conversation ID = “abc-123” (the exact same ID for this conversation loop).

When the Memory node sees the Session ID “abc-123”, it immediately pulls the chat history from Request 1 and feeds it to the AI.

The AI instantly knows that “The third one” refers to the client list from the previous message!

1 Like

Welcome @flipflip!

The key is attaching a memory sub-node to your AI Agent - specifically the “Window Buffer Memory” node. In its “Session ID” field, use the Teams conversation ID: {{ $json.channelId }} or whatever field carries the unique conversation ID from Teams in your trigger data. This way each Teams conversation gets its own memory window and the agent remembers prior exchanges within that same conversation.

Your flow becomes: Teams trigger → AI Agent (with Window Buffer Memory sub-node, session ID = Teams conversation ID) → reply to Teams. Each new message from the user hits the same agent, the memory node loads the previous turns from that session, and the agent picks up the context. The loop approach you tried won’t work here because n8n isn’t designed to pause mid-execution waiting for user input - memory + session key is the right pattern.

Hello everyone,

Thanks for your replies. You were right—using a loop was definitely not the right approach.

I added PostgreSQL-based memory, but I didn’t use the Teams conversation ID because it changes with every message sent or received. Instead, I used the ID of the user profile sending the message.

Now I can utilize the AI ​​agent’s memory while distinguishing between different users.