Consolidating an n8n AI agent's memory: from chat threads to durable facts
Published 5 August 2026 · 6 min read
Your n8n AI agent has been running for three months with a Postgres Chat Memory, and the n8n_chat_histories table already weighs in at hundreds of thousands of rows. Every new conversation replays a window of exchanges billed in tokens, the context gets diluted, latency climbs — and despite all that storage, the agent still doesn't "know" anything: the short window forgets, and the full history is far too large to replay. Our previous guides cover plugging in a session memory and choosing persistent storage. This article tackles the step almost everyone skips: the consolidation process — periodically turning the raw history into compact, durable, reusable knowledge.
The problem: a growing history is not a memory
Persisting conversations in PostgreSQL solves volatility, not accumulation. Three symptoms appear as the table grows:
- Token cost: the context window replays the last N exchanges on every call; with long, frequent conversations, this becomes the agent's largest expense.
- Diluted context: the decisive piece of information ("the customer cancelled the Pro plan in May") drowns in pleasantries and digressions. The model sees it, but no longer weighs it.
- Cross-session amnesia: the window only covers one session. What the user explained three weeks ago no longer exists for the agent, even though it sits right there in the table.
Storing more solves nothing: you need to store differently. A transcript is a recording; a memory is a selection.
The principle: do what the brain does during sleep
Memory consolidation is a well-documented biological mechanism. The landmark review by Susanne Diekelmann and Jan Born, "The memory function of sleep", published in 2010 in Nature Reviews Neuroscience (Google Scholar), shows that during slow-wave sleep, the brain replays the day's experiences temporarily stored in the hippocampus, redistributes the essentials to the neocortex in a more abstract form, and lets the rest fade away. Replay, summarize, keep only what matters: that is exactly the pipeline to build.
The parallel is more than a metaphor. The study by Wanjun Zhong and co-authors presented at AAAI 2024, "MemoryBank: Enhancing Large Language Models with Long-Term Memory" (Google Scholar), applies this scheme to an LLM chatbot: dialogues are condensed into daily summaries and then into a durable user portrait, and a forgetting mechanism inspired by the Ebbinghaus curve lets memories that are neither recalled nor reinforced fade out. The result: a conversational companion that stays coherent over time without replaying months of transcripts.
The n8n architecture: two workflows, two rhythms
Workflow 1 — the agent, mostly unchanged
The conversational agent keeps its short session memory (a 10-15 exchange window) for the thread of the dialogue. You add access to the consolidated facts — either injected into the system prompt (see below) or exposed as a recall tool the agent calls when it needs to. Nothing else changes: consolidation is invisible on the conversation side.
Workflow 2 — nightly consolidation
A second workflow, fired every night by a Schedule Trigger (3 a.m., off-peak), runs through five steps:
- Read yesterday's sessions: a query on the chat memory table, grouped by session key, filtered to closed conversations (no message for a few hours).
- Summarize each session: one LLM call per session produces a 3-5 sentence, decision-oriented summary — who, what, outcome. Here, the techniques from our guide to summarizing long documents apply as is.
- Extract structured facts: an Information Extractor node (or an LLM with a Structured Output Parser) turns the summary into typed facts: preferences, decisions, customer information.
- Deduplicate and update: before inserting, check whether an equivalent fact already exists for this user. If it's identical, skip it; if it contradicts, mark the old one as replaced (
superseded_at) rather than deleting it. - Purge or archive: consolidated sessions are moved to a short-retention archive table, then deleted from the hot table.
The facts table, in Supabase or any PostgreSQL (n8n's native Data Tables also work for small volumes):
create table agent_facts (
id bigint generated always as identity primary key,
user_key text not null, -- same value as the agent's Session Key
category text not null, -- preference | decision | client_info
fact text not null,
source_session text not null, -- originating session: anti-hallucination traceability
valid_from timestamptz default now(),
superseded_at timestamptz -- null = active fact
);
create unique index idx_facts_active
on agent_facts (user_key, category, md5(fact))
where superseded_at is null;
And the extraction prompt, where every line is a guardrail:
You receive the summary of a conversation between a customer and our assistant.
Extract only durable facts, as JSON:
- category: "preference", "decision" or "client_info"
- fact: one short, self-contained sentence in the present tense
- quote: the exact sentence from the conversation that supports the fact
Rules:
- Extract NOTHING that was not explicitly said (no inference).
- Ignore pleasantries, hypotheticals, and questions left unanswered.
- If there is no durable fact: return an empty array. That is a normal result.
A fact returned without a quote is rejected by the workflow: it's the simplest test against hallucinated facts. To go further, vectorize the fact column with pgvector so facts can be recalled by semantic similarity — the same mechanics as in our RAG guide with Supabase, applied to per-user facts instead of documents.
Reinjection: making the facts useful
Two options, which can be combined. The simplest: inject the N most recent active facts (or those most similar to the incoming message) into the agent's system prompt, with their date:
{{ "Known facts about this user:\n" + $('Search facts').all()
.map(i => `- [${i.json.valid_from.slice(0,10)}] ${i.json.fact}`)
.join('\n') }}
The more flexible one: expose the search over agent_facts as a "search my memory" tool the agent invokes itself when the question calls for it. Systematic injection guarantees the essential facts are always present; the tool avoids paying tokens for facts irrelevant to the question at hand. In practice: 3-5 facts injected by default, the rest through the tool.
Hygiene: a memory that knows how to forget
- TTL per category: a contact preference is worth years, a purchase intent a few weeks. Give each category its own lifespan, and let the nightly workflow flag expired facts.
- Contradictions: never store two active contradictory facts. The newer one overrides the older via
superseded_at— the version history remains queryable, only the active fact gets recalled. - Right to erasure: consolidated facts are personal data just as much as the transcripts. An erasure request must purge the facts table, the archive, and any embeddings — the circuit described in our guide to handling GDPR requests with n8n is directly applicable.
The pitfalls
- Consolidating too early or too often: summarizing a conversation still in progress freezes provisional facts ("is hesitating between plans A and B") that will be wrong by the evening. Wait for session closure, consolidate once a night.
- Trusting the extraction: without a quote requirement and a ban on inference, the LLM will fill in the silences. "Asks about the price of the annual plan" becomes "prefers annual billing".
- Keeping everything "just in case": retaining the raw history after consolidation recreates the original problem, in duplicate. The value of consolidation comes as much from what it deletes as from what it extracts.
- One workflow for everything: mixing conversation and consolidation in the same workflow couples two incompatible rhythms (real time vs. nightly batch) and makes every message pay for the consolidation.
Summary
An agent memory that works is not a database that grows, it's a cycle: a short session memory for the thread, a nightly consolidation that summarizes, extracts, deduplicates, and purges, and a table of timestamped facts reinjected at the right moment. It's the same motion as the brain during sleep — replay, abstract, forget the rest — and it can be built entirely with standard n8n nodes. The most technical building block, vectorized storage and similarity-based recall, is exactly what the RAG Assistant Pack (€119) ships: its embeddings and pgvector search workflows can be repointed at your agent_facts table in an hour, and your agent gains what separates it from a real assistant — a memory that learns every night.
FAQ
Frequently asked questions
How often should you consolidate an n8n AI agent's memory?
Once a night is the right default: yesterday's sessions are closed, the volume stays manageable, and the LLM cost of consolidation is smoothed out. Consolidating on every message is expensive and freezes facts from conversations still in progress; consolidating once a month lets the raw history balloon and delays the agent's learning. Only adjust if your volume demands it: hourly for very high traffic, weekly for a lightly used internal agent.
Should you delete the raw history after consolidation?
Purge or archive it, but don't keep it as is. Once summaries and facts have been extracted, the raw history is only useful for debugging and traceability: move it to a cold table (or object storage) with a short retention period, then delete. Keeping it indefinitely cancels the benefit of consolidation and creates a GDPR liability, since transcripts almost always contain personal data.
How do you prevent the LLM from inventing facts during consolidation?
Three guardrails: require an exact quote of the source sentence for every extracted fact (a fact without a quote is rejected), explicitly forbid inference in the extraction prompt (extract only what was said, not what is likely), and store the originating session ID with each fact so it can be verified afterwards. A hallucinated fact will resurface in every future conversation with the confidence of a certainty: write-time filtering is the only point where stopping it is cheap.
Bundle FlowKit Complet
€269