How to Give Your Scheduled AI Agent Memory With Supabase (the Full DIY Pattern)
Your scheduled agent runs at 6am, does its job, and dies. At 6am tomorrow it wakes up a stranger. Every preference learned, every decision made, every failure diagnosed: gone. The n8n session-key trick helps for simple cases, but when an agent needs to remember facts across weeks of runs, you need a real database outside the agent. For automation operators, the default DIY answer is Supabase: free-tier Postgres, the pgvector extension, a REST API you can hit from anywhere, and nodes already sitting in n8n and Make.
Here is the full pattern: what to store, the schema, the save step, the recall step, and the honest bill for the plumbing.
The pattern in one paragraph
Two steps wrapped around the agent's run. Save: at the end of each run, extract what is worth remembering and upsert it into a table keyed by agent name and memory key. Recall: at the start of each run, query that table and inject the results into the system prompt. The agent never "remembers" in any human sense; it reads its own notes before every shift. Simple, boring, and it works.
Step 1: the schema
Keep it small on purpose. One table for durable key-value memories, and later a second one for semantic chunks if you want similarity search:
create table agent_memories (
id uuid primary key default gen_random_uuid(),
agent_name text not null,
memory_key text not null,
content text not null,
importance int default 1,
created_at timestamptz default now(),
updated_at timestamptz default now(),
unique (agent_name, memory_key)
);
memory_key is where the design lives. A stable key like client-acme/preferences gives one agent one memory per key. Keying per client or per workflow is what stops ten clients' preferences from bleeding into each other. If you take one thing from this article, make it this: the key design is the memory design.
Step 2: the save step
The end of the run is where most DIY memory dies, because "save everything" turns into a 400-row junk drawer within a month. Be selective. Ask the agent, or a cheaper model, to extract only durable facts: decisions made, names and preferences stated, things that failed and why. Then upsert:
supabase.table("agent_memories").upsert({
"agent_name": "daily-briefing",
"memory_key": f"client-{client_id}/preferences",
"content": extracted_facts,
}, on_conflict="agent_name,memory_key").execute()
The extraction prompt is the real work here. You are writing the instructions that decide what counts as worth remembering, and tuning that prompt is a maintenance job, not a one-time setup. Every new failure mode in your automations becomes a new category of fact to extract.
Step 3: the recall step
At the start of the next run, read the rows back and prepend them to the system prompt under a header like ## What you know from previous runs. Exact key lookups are free and instant. The agent wakes up with its notes in context and picks up where it left off.
For small memory stores, this is the whole system. Exact lookups scale fine into the thousands of rows. You only need the fancier version below when the agent must find relevant memories by meaning rather than by key.
Going further: semantic recall with pgvector
Enable the vector extension and add a chunks table:
create extension if not exists vector;
create table agent_memory_chunks (
id uuid primary key default gen_random_uuid(),
agent_name text not null,
content text not null,
embedding vector(1536),
created_at timestamptz default now()
);
Store an embedding per chunk, then retrieve with a Postgres function:
create or replace function match_memories(
query_embedding vector(1536),
p_agent text,
match_count int default 5
)
returns table (content text, similarity float)
language sql stable
as $$
select content, 1 - (embedding <=> query_embedding) as similarity
from agent_memory_chunks
where agent_name = p_agent
order by embedding <=> query_embedding
limit match_count;
$$;
Call it from the agent's pre-run step and inject the top matches into the prompt. Now the agent recalls by meaning: "the client who complained about invoice formatting" surfaces even when nobody typed those exact words.
The honest bill for the plumbing
Supabase is free to start, but DIY memory charges in labor, not dollars:
- The extraction prompt is yours to maintain. Every new failure mode in your automations is a new category of fact to extract. This tuning never ends.
- Nothing forgets on its own. Supabase has no opinion about stale memories. Last quarter's "we are pausing the newsletter" sits next to this week's "newsletter is back" unless you build invalidation. Add an importance score or a reviewed-at column plus a scheduled cleanup, or the agent starts quoting outdated facts with confidence.
- Context growth is still your problem. Injecting thirty memories into every prompt costs tokens on every run. Budget a cap: top N by recency plus importance, never the whole table.
- The service key is a loaded gun. Scheduled jobs usually run with the Supabase service_role key, which bypasses row-level security. Scope keys per agent, rotate them, and never let the agent itself hold the key that can drop the table.
- Overlapping runs race. Two scheduled runs firing at once can upsert the same key concurrently. Postgres handles the write conflict, but your extraction logic may not. Idempotent keys and schedules that cannot overlap save you here.
None of these are reasons to avoid Supabase. They are the reasons a weekend project becomes a second job when you run ten agents instead of one.
When DIY is right, and when it is not
Use the Supabase pattern when you already own the stack, your memory needs are shaped oddly enough that a generic service fights you, or compliance says the data lives in your Postgres and nowhere else. It is a real database: you can query it, back it up, and introspect the agent's brain with plain SQL. That debuggability is genuinely hard to give up.
Reach for a hosted memory service when you would rather spend the plumbing time on the automations themselves: no schema to maintain, no extraction prompt to tune, no stale-memory cleanup job, and memory that follows the agent across tools instead of living in one project's database. This is the tradeoff Vilix AI is built around. It is cloud-hosted, so you manage zero infrastructure, and the same memory follows you over MCP whether the agent runs in Claude, Codex, Cursor, OpenClaw, or Hermes. It stores full conversation history, not just extracted facts, so nothing is lost to a bad extraction prompt. There is a free plan that stays free, a 7-day Pro trial that needs no credit card, and you can export everything in a portable format or delete individual memories or wipe the account instantly, anytime. The honest tradeoff: you are trusting a service with the memory instead of owning the Postgres yourself. If your compliance setup forbids that, the DIY pattern above is the right call.
Either way, the agent stops waking up a stranger. Pick the memory home you will actually maintain, because an unmaintained memory is worse than none: it teaches the agent to confidently quote last quarter.
Top comments (0)