Skip to main content
Uses: Mem0 Platform (MemoryClient) · System of record: Supabase (Postgres + Auth) · Access layer: the hosted Mem0 MCP server. You’ll build: a company brain your whole org (and every agent) writes to and queries, ending with a new-hire onboarding demo.
Companies lose knowledge constantly: why you picked Postgres over Mongo, who owns billing, the deploy rule only one engineer remembers. A company brain captures this and answers questions about it, for every employee and every agent, and keeps it after people leave. We’ll build one on Mem0 Platform (the managed memory layer, so there’s no vector DB to run) with Supabase as the system of record (where your employees, teams, and source documents actually live) and the Mem0 MCP server as the wire that lets Claude Code, Cursor, or a Slack bot all reach the same brain.
How Platform and Supabase divide the work. Mem0 Platform manages storage and extraction server-side, you do not point it at your own database. Supabase is your app’s source of truth and identity provider; we ingest knowledge from Supabase into the brain and use Supabase Auth to decide who’s asking. (If you want to self-host the vector store instead, that’s the OSS path, see the Supabase vector store reference.)

Architecture

Memory splits by entity. An individual is a user_id (their Supabase Auth id). Shared knowledge lives on an agent_id: the company-wide brain is org:acme, and each team is its own agent, e.g. team:payments. A person’s own facts route to their user_id; company and team facts route to the agent. This split is what lets one search return “my” context alongside the shared org knowledge.

Prerequisites

About 20 minutes.

Step 1: Get your Mem0 Platform API key

Sign in at app.mem0.ai and copy a key from Dashboard → API Keys. The key is scoped to your org and project; Mem0 resolves both server-side, so you never pass IDs by hand.

Step 2: Create the Supabase system of record

In the Supabase SQL editor, create the tables your company already thinks in: people, teams, and a knowledge table the brain will ingest from. Identity reuses Supabase Auth’s built-in auth.users.
Grab your project URL and service-role key from Settings → API (the ingestion job runs server-side and needs to read every scope).

Step 3: Project setup

Step 4: Configure the brain

Create brain.py. This constructs the Platform client and teaches it what to remember. The key is the two instruction sets: custom_instructions governs a person’s own (user_id) memories, and agent_custom_instructions governs shared (agent_id) memories, phrased in the third person so company facts read “The company…”, not “The user’s organization…”. custom_categories files each memory under a useful label.
Run it once to apply the project settings:

Step 5: Ingest company knowledge from Supabase

This is where Supabase and the brain connect. Create ingest.py: read un-synced rows from knowledge, add each to the Platform brain under its scope, then mark it synced. Platform add() is asynchronous, it returns an event_id you can poll, so we include a small wait_for helper.
Re-running is safe, mem0_synced_at gates it, so a nightly cron can keep the brain in step with Supabase.

Step 6: Ask the brain

Create ask.py. It searches everything relevant to the asker: their own (user_id) memories plus the shared company and team (agent_id) memories. This has to be an OR, each memory row belongs to exactly one entity, so a flat filter or an AND of a user_id and an agent_id matches nothing.
Search returns every relevant memory, so a question resolves across separate facts, here it pulls both the owning team and the person:

Step 7: Sharper retrieval

Platform search is hybrid (semantic + keyword) and filterable. Combine a keyword pass with a category filter to answer precise questions:
Filters use keyword operators (in, gte, contains, …) and AND/OR/NOT, so you can scope by date, category, or metadata, for example the company’s policies added this quarter:

Step 8: Expose the brain to every agent (MCP)

A brain only your script can reach isn’t a company brain. Mem0’s hosted MCP server lets any agent (Claude Code, Cursor, a Slack bot) query and contribute to the same brain. The endpoint is https://mcp.mem0.ai/mcp, and the supported way to connect is the mcp-add helper, which registers the server and runs Mem0’s OAuth login so no key ever lands in a config file.
Complete the browser login on first connect. Now the agent has the brain’s memory tools (add_memory, search_memories, and more) available in-editor.
With this, an engineer asks the brain from their editor and a teammate asks it from Slack, one shared memory behind both.

Step 9: Onboard a new hire (the payoff)

This is what a company brain is for. Dana joins, and her identity comes from Supabase Auth, which maps straight to her Mem0 user_id. She asks the questions every new hire asks and gets real answers on day one, drawn from the shared company (and her team’s) brain, plus anything she’s told it herself.
The same ask() blends the shared company facts with Dana’s own preference, because the OR filter spans both her user_id and the org and team agent_ids. Dana onboarded herself by asking, drawing on the shared brain the rest of the team had been filling.

Production notes

user_id vs agent_id. An individual is a user_id; shared brains (company, team) are agent_ids. Keeping them separate is what gives you the third-person “The company…” framing and lets a person’s own context sit alongside org knowledge. Put a secret like a webhook key on a team agent, never the company agent, or everyone can recall it, and mirror the boundary in Supabase with a Row Level Security policy on knowledge.
Search must OR the scopes. A memory row belongs to exactly one entity, so filters={"OR": [{"user_id": ...}, {"agent_id": "org:acme"}, {"agent_id": "team:..."}]}. A flat filter, or an AND of a user_id and an agent_id, returns nothing.
add() is asynchronous. It returns {event_id, status: "PENDING"} and extraction finishes a moment later, poll GET /v1/event/{event_id}/ (as in Step 5) when you need to know a write has landed before searching for it.
Where the entity ID goes differs by call. search() and get_all() take the scope inside filters={...} (a top-level user_id=/agent_id= is rejected). add() and delete_all() are the opposite, they take it as a top-level keyword: client.delete_all(agent_id="team:payments"). Deletes are asynchronous too, so a get_all right after a delete_all can still show rows for a few seconds.

Where to take it next

  • Auto-feed the brain from PR descriptions, RFCs, and incident write-ups so it grows without anyone thinking about it, just insert into Supabase knowledge and let the cron ingest.
  • Scope by real identity end to end: verify the Supabase JWT, read sb.auth.get_user(jwt).user.id for the user_id, look up the person’s team, and OR their user_id with the company and team agent_ids on every recall.
  • Give teams a private view with Supabase RLS so team: knowledge is only readable by that team.

Mem0 MCP Server

Connect any agent or editor to the brain over MCP.

Custom Categories & Instructions

Steer exactly what the brain extracts and how it’s filed.
Using Mem0? Star us on GitHub to help more developers discover memory for AI apps.