The same word, "memory," often hides three different problems. An agent needs to know which record is true, find text that resembles the question, and understand that a relationship changed since the last conversation. Putting everything into embeddings solves only one part.
To choose between Graphiti, vector RAG, and PostgreSQL, separate the source of truth from the retrieval index and the representation of relationships. In practice, the easiest architecture to operate starts with the database you can already audit. Add a graph only when the query truly depends on time, relationships, or history.
If your question is still how an agent finds files and symbols, see the article about codebase RAG for coding agents. If the issue is temporal memory, the earlier piece on Graphiti and long-term memory explains the concept before this comparison.

Quick decision
- Use PostgreSQL for relational facts, current state, permissions, and audit trails.
- Use vector RAG when the question needs content that is semantically similar.
- Use Graphiti when entities and relationships change and history belongs in the answer.
- Combine the layers without letting the retrieval index become the source of truth.
What does each option actually store?
In 2026, Graphiti's official documentation describes a temporal graph with entities, relationships, facts, and source episodes (Graphiti, "Overview", retrieved 2026-07-30). PostgreSQL stores explicit rows and relations. Vector RAG stores representations used to find similarity. The right choice depends on the kind of question the agent must answer.
| Option | Best memory unit | Question it answers well | Main risk |
|---|---|---|---|
| PostgreSQL | Record, state, or event | "What is the current state of this task?" | Requiring semantic queries that were never modeled |
| Vector RAG | Searchable chunk or document | "What content resembles this question?" | Returning similar text that is stale or unrelated |
| Graphiti | Entity, relationship, episode, and validity | "What changed between these people, systems, or decisions?" | Operating extraction, a graph database, and update policy |
The common mistake is asking which tool has the best memory. The useful question is which structure preserves the evidence you will need to review later. A ticket can live in PostgreSQL, have an embedding for search, and appear in the graph as a relationship between a service, a decision, and an incident. No layer needs to pretend it does another layer's job.
When should PostgreSQL be the agent's memory?
In 2026, PostgreSQL should be the primary memory when the system needs transactions, permission filters, current state, and history that another person can inspect with SQL. The official documentation separates tsvector and tsquery for text search, while the relational model keeps the business rule (PostgreSQL, "Full Text Search", retrieved 2026-07-30).
This path works for support, operations, and coding agents that need to read tasks, decisions, approvals, or test results. The database row becomes the contract. The agent receives a short projection, while the application can open the complete record when it needs to investigate.
CREATE TABLE agent_memory (
id uuid PRIMARY KEY,
subject_id text NOT NULL,
kind text NOT NULL,
content jsonb NOT NULL,
source_uri text NOT NULL,
valid_from timestamptz NOT NULL,
valid_until timestamptz,
created_at timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX agent_memory_subject_idx
ON agent_memory (subject_id, kind, valid_until);
The source_uri field prevents an orphan sentence from becoming truth just because the model retrieved it. valid_until lets you retire a fact without deleting the history. The application still decides whether conflicting records should be rejected, versioned, or sent for human review.
Use full-text search for terms, service names, identifiers, and decisions that depend on lexical matching. If the question is "which migration created the status column?", text search and database metadata are often more useful than approximate similarity.
When retrieval needs to reach the agent through narrow tools, the post about codebase RAG with MCP shows a similar boundary between on-demand search and loaded context.
Citable capsule: PostgreSQL is a good source of truth for agent memory when the system needs transactions, permissions, current state, and auditable provenance. Text search can locate terms and identifiers, but validity, conflict, and access decisions remain in the relational model, outside the agent's prompt.
When is vector RAG enough?
In 2026, vector RAG is enough when the task is to retrieve semantically close chunks and validity can be controlled by ingestion. The pgvector README documents exact search, approximate HNSW and IVFFlat indexes, and combination with PostgreSQL full-text search (pgvector, "README", retrieved 2026-07-30).
This option works well for documentation, runbooks, architecture decisions, and code examples that do not need a relationship network to make sense. The agent asks, the application retrieves candidates, and the model receives chunks with an identifier and source.
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE memory_chunks (
id bigserial PRIMARY KEY,
source_uri text NOT NULL,
content text NOT NULL,
embedding vector NOT NULL,
updated_at timestamptz NOT NULL
);
CREATE INDEX memory_chunks_embedding_idx
ON memory_chunks USING hnsw (embedding vector_cosine_ops);
The vector dimension in the example is left to the migration. If you fix a dimension, check the value produced by your provider before creating the index. The index improves retrieval, but it does not know whether the text is still valid, whether the user has permission, or whether a newer document replaced it.
For that reason, filter by scope before building context. Check subject_id, repository, environment, classification, and date. Then combine semantic search with exact terms when the question contains file names, incidents, classes, or API identifiers.
When an agent crosses many sessions and needs only the relevant evidence, RemoteCode helps Claude Code and Codex continue agentic flows with less repeated context. It is the author's own tool and is mentioned here as an option for reducing resent context. It does not replace a database, authorization, or memory verification.
Citable capsule: Vector RAG retrieves similar content, not memory governance. pgvector can combine vector search with PostgreSQL full-text search, but the application still needs to filter access, record the source, control updates, and prevent an old chunk from being presented as current state.
When is Graphiti worth the complexity?
In 2026, Graphiti is worth the complexity when the answer depends on relationships that change and on queries at a specific point in time. Its official documentation describes incremental episode ingestion, provenance, temporal fact invalidation, and hybrid search across semantic, text, and graph signals (Graphiti, "Overview", retrieved 2026-07-30).
Imagine an agent that must answer which service depended on a queue before a migration, which decision replaced another, or who approved an exception while it was still valid. A vector can find related documents. A graph can represent the relationship and its lifecycle, as long as the data model and ingestion are correct.
Graphiti is not a shortcut for putting an entire codebase into a graph. The official project requires a compatible graph database and an LLM provider for extraction and embeddings (Graphiti, "README", retrieved 2026-07-30). That creates more things to configure, observe, and test.
Use a graph when the relationship is part of the query, not merely a visual detail. If the question is "which document mentions a timeout?", start with text or vector search. If it is "which service depended on this queue when the decision was made?", temporal relationships may justify Graphiti.

Citable capsule: Graphiti is a temporal memory choice for agents when entities, relationships, and facts change over time. The framework records source episodes and offers hybrid retrieval, but it requires a graph backend and a clear policy for extraction, invalidation, permissions, and observability.
A hybrid architecture separates truth, search, and relationships
A hybrid architecture keeps a source of truth and creates derived indexes for different questions. The transactional record stays in PostgreSQL. The embedding points to searchable chunks. The graph represents temporal relationships when the domain needs them. The agent's answer carries references to these layers instead of carrying loose text alone.
type MemoryEvidence = {
id: string;
sourceUri: string;
text: string;
validFrom: string;
validUntil: string | null;
score?: number;
};
type MemoryProvider = {
search(input: {
subjectId: string;
query: string;
at?: string;
}): Promise<MemoryEvidence[]>;
record(input: {
subjectId: string;
sourceUri: string;
content: string;
}): Promise<{ id: string }>;
};
The contract does not reveal which database answered. It requires every result to have an identifier, source, and validity. The implementation can query SQL first, use hybrid search next, and call Graphiti only when the question asks for a relationship or history.
The supervisor should also distinguish reading from writing. A search tool can return evidence. A write tool must validate content, require sourceUri, record who requested the change, and prevent a model output from replacing a fact without approval.
Citable capsule: A hybrid memory architecture keeps PostgreSQL as the source of truth, uses vector RAG to locate content, and reserves Graphiti for temporal relationships. The agent need not know which layer answered, but it must receive evidence with an identifier, origin, and validity so the application can verify the context.
How do you verify memory before calling the model?
Verify memory in two stages: the application checks scope, validity, and origin first; then the agent receives only results that can be cited. This separation lowers the risk of plausible text dominating the context. The return value should let a test reproduce the query and inspect the record that was used.
Use this checklist on the retrieval path:
- Normalize the subject, repository, or tenant identifier.
- Limit the query to sources the execution can read.
- Remove facts whose validity ended, unless the question asks for history.
- Retrieve candidates by text, vector, or temporal relationship.
- Attach
sourceUri, an identifier, and validity dates to each result. - Reject answers without evidence or mark the output as unverified.
The test should not ask only whether the model answered. It should confirm that a state change retires the old fact, that a source without permission never appears, and that a historical question still finds the correct version. For coding agents, also record the commit, file, or architecture decision used.
When retrieval fails, do not raise the context limit by reflex. First determine whether a source is missing, a filter discarded the right result, or the index returned a similar chunk. Those point to four different fixes: ingestion, authorization, query, or ranking.
This diagnosis also applies to the context budget for coding agents: measuring what enters the prompt helps separate missing memory from excess context.
Common mistakes and limits of the comparison
The first mistake is turning Graphiti into a requirement for every agent. A small agent may work better with a table, text search, and metadata. A graph adds value when the relationship changes and must be queried, not when the diagram looks more sophisticated.
The second mistake is treating embeddings as canonical memory. Embeddings are derived indexes. They need updates, deletion, scope, and reprocessing. If a document is revoked, the agent should not keep citing an old vector because semantic search still finds a similar sentence.
The third mistake is mixing past and present in the same answer. The image in this post summarizes the rule: a new fact can invalidate an old one without deleting its origin. When the question gives no point in time, define an explicit policy that prefers current state.
The fourth mistake is hiding memory writes inside a generic tool. Separate search from record, validate arguments, and log the decision. A wrong write is harder to repair than an incomplete search because it contaminates later queries.
The limits matter too. The project documentation describes capabilities and examples, but its benchmarks do not automatically represent your domain. Measure recall, precision, retrieval time, ingestion cost, context volume, and stale-fact rate with questions from your own system.
Frequently asked questions about AI agent memory
Does Graphiti replace a vector database?
Not necessarily. Graphiti offers hybrid retrieval across relationships, text, and semantics, but the product's source of truth can remain in PostgreSQL. The official project describes Graphiti as a temporal graph engine and requires a compatible backend. Choose it when relational history is part of the question, not simply because the agent needs memory.
Is PostgreSQL enough for persistent agent memory?
For many systems, yes. PostgreSQL covers state, transactions, permissions, audits, and text search. With pgvector, it can also keep embeddings and semantic search. It becomes less suitable when queries depend on many temporal relationships that would be artificial in tables. Even then, PostgreSQL can remain the source of truth.
Does vector RAG prevent stale context?
Not by itself. Vector search finds similar content, but it does not know whether a source was revoked, replaced, or blocked for a user. Store origin and validity, filter before building the prompt, and test state changes. If the application needs history, retrieve the correct version instead of trusting the nearest chunk.
Should I expose agent memory through MCP?
MCP can be a useful boundary for search and record tools, but it should not decide what data is true. Validate input on the server, keep reads and writes separate, and return structured evidence. The agent can request context through a tool while PostgreSQL, Graphiti, or another backend applies authorization and update policy.