Best Practices

Enagram's memory pipeline is designed to build a persistent, evolving model of an agent's interactions over time. Getting the most from it requires being deliberate about what you send, when you send it, and what you rely on it for.


What memory is for

Enagram is designed to answer one question: what does this agent know about this user, and how should that shape its behaviour going forward?

Good uses of memory:

  • User preferences and communication style — tone, verbosity, language, format preferences revealed through conversation.
  • Stated facts about the user — their role, domain, goals, constraints, recurring topics of interest.
  • Behavioural patterns — things that consistently lead to positive outcomes, corrections the user repeatedly makes, procedures the agent has learned work well.
  • Identity signals — durable characteristics that should influence every interaction, such as expertise level, values, or long-term objectives.
  • Outcomes and corrections — explicit feedback that teaches the pipeline what works and what doesn't.

What memory is not for

Enagram is a cognitive layer, not a data store. It is not a replacement for:

  • Document or knowledge base storage — if your agent needs to retrieve files, PDFs, or large structured documents, use a dedicated vector store or document retrieval system. Enagram is not designed for chunk-level retrieval of static content.
  • Session state — short-term conversational context (the last few turns) belongs in your prompt, not in memory. Enagram operates on patterns across sessions, not within a single turn.
  • Audit logs or compliance records — memory is a probabilistic, salience-weighted system. Items below the commit threshold are discarded, and memories decay over time. Do not rely on it for complete or authoritative records.
  • Structured application data — user account data, preferences stored in a database, permissions, and settings should live in your own data layer. Memory is for learned behavioural context, not authoritative state.

Do not send tool calls to memory

Tool calls — function invocations, API calls, database queries made by your agent — should generally not be sent to Enagram unless you specifically want the agent to learn that it used a tool, and under what circumstances.

The memory pipeline extracts meaning from natural language events. A raw tool call payload ({ "function": "search_docs", "args": { "query": "..." } }) carries little semantic signal and will either be discarded (low salience) or pollute the memory with meaningless procedural noise.

Instead:

  • Send the outcome of a tool call as a natural language event if it is semantically meaningful. For example, if a search returned a result the user found useful, send an outcome: positive event describing what worked.
  • If you want the agent to learn when to use a tool, frame it as a procedure: send a correction or outcome event that describes the context and result in natural language.

Separate memory from document retrieval

A common pattern is to combine Enagram with a vector store (Pinecone, Weaviate, pgvector, etc.). These serve distinct purposes and should not be conflated:

EnagramVector store
PurposeBehavioural memory about a userRetrieval of static content
InputInteraction eventsDocument chunks
OutputWorking memory contextRelevant passages
DecayYes — memories fade over timeNo
LearnsYes — reinforced by outcomesNo

A well-architected agent uses both: retrieve relevant documents from your vector store, retrieve behavioural context from Enagram, and combine both into the system prompt.


Be consistent with session IDs

The session_id field groups events into a session. Enagram uses session boundaries to understand episode structure — events within a session form a coherent episode that gets compiled into memory together.

  • Use a stable, unique identifier per conversation — a UUID generated at the start of each session works well.
  • Do not reuse session IDs across unrelated conversations.
  • Do not use a single global session ID for all interactions — this collapses all events into one episode and degrades memory quality significantly.

Send assistant messages, not just user messages

The pipeline extracts more signal when it can see both sides of the conversation. Sending only user messages means the agent cannot learn from its own responses — it cannot identify what it said that led to a positive outcome, or detect patterns in how it communicates.

Send assistant_message events alongside user_message events for every turn.


Use outcomes to close the loop

Outcomes are the primary feedback signal for the memory pipeline. Without them, the system can observe what happened but cannot learn what worked.

Send an outcome event:

  • When a user explicitly confirms something was helpful.
  • When a user corrects the agent.
  • When a task is completed successfully or unsuccessfully.
  • When the user abandons a conversation — a negative or neutral outcome signals that something did not land.

You do not need a human in the loop to generate outcomes. Your application logic can infer them — for example, if a user clicks "thumbs up", or completes a checkout flow, or closes a support ticket as resolved.


Respect the salience threshold

The commit_threshold configuration controls how selective the pipeline is. Raising it means only high-signal events are stored; lowering it stores more but with more noise.

Avoid the temptation to lower the threshold to "store everything" — a noisy memory degrades working memory quality. The default threshold is calibrated for general conversational agents. Adjust it only if you have a clear reason based on observed memory quality.