AI agents often need more than the information available in a single request. A user may ask an agent to create a report, review a document, call a tool, continue a previous task, or make a decision based on an earlier conversation.
If the agent does not retain useful context, every request starts from the same point.
For example, a user might first tell an agent:
I am preparing a monthly sales report for the North region.
Later, the same user asks:
Add the latest order data to the report.
The second request depends on the first one. The agent needs to know which report and region the user is referring to.
This is where agent memory becomes useful.
MariaDB can be used to store structured agent memory, including conversation context, user preferences, task state, decisions, tool results, and other information that should remain available between requests.
The important part is deciding what should be remembered, how long it should be stored, and when it should be included in the next model request.
What Is Agent Memory?
Agent memory is persistent information that an AI agent can retrieve after the current request has ended.
Without persistent memory:
Request 1
|
v
Agent
|
v
Response
|
v
Context lost
With persistent memory:
Request 1
|
v
Agent
|
+---- Save useful context
|
v
Response
Request 2
|
v
Load relevant memory
|
v
Agent
|
v
Response
The database provides persistence, while the application decides how that memory is used.
Memory Is Not the Same as Conversation History
Conversation history is one form of memory, but it is not the entire memory system.
Consider these different types of information:
Memory Type | Example | Typical Lifetime |
|---|
Conversation history | User messages | Session |
User preference | Preferred report format | Long term |
Task state | Report generation in progress | Until task completes |
Tool result | Customer lookup result | Short term |
Decision | User approved a configuration | Long term |
Summary | Previous conversation summary | Session or long term |
Agent state | Current workflow step | Task lifetime |
Storing all of these records in one table can make the application difficult to manage.
A better design separates memory according to its purpose.
Design a MariaDB Memory Model
A simple design can contain several tables.
agent_sessions
--------------
session_id
user_id
status
created_at
updated_at
agent_messages
--------------
message_id
session_id
role
content
created_at
agent_memories
--------------
memory_id
user_id
memory_type
memory_key
memory_value
created_at
updated_at
agent_tasks
-----------
task_id
session_id
status
current_step
updated_at
This structure allows the application to store different types of agent state independently.
For example, a user preference can remain available after a conversation ends, while a temporary task state can expire when the task finishes.
Store Useful Memory, Not Everything
A common mistake is assuming that the agent should remember every message forever.
That approach creates several problems:
Database storage grows quickly.
Retrieval becomes slower.
The model receives irrelevant context.
Old information can conflict with new information.
Privacy and retention become harder to manage.
Instead, define what information has long-term value.
For example:
Useful memory:
Preferred language
Preferred report format
Ongoing project
Important user preference
Approved business rule
Temporary context:
Last tool result
Current workflow step
Intermediate calculation
The application should decide which information belongs in persistent memory.
Store Memory as Structured Data
Avoid storing every memory item as an unstructured text paragraph.
For example:
User prefers concise reports.
can be represented as:
memory_type = preference
memory_key = report_style
memory_value = concise
A structured representation makes memory easier to update.
Another example:
memory_type = project
memory_key = active_project
memory_value = sales_dashboard
The agent can retrieve this information without processing a large block of text.
Create a Memory Record
A simple application can insert memory using SQL.
For example:
INSERT INTO agent_memories
(
user_id,
memory_type,
memory_key,
memory_value,
created_at,
updated_at
)
VALUES
(
?,
'preference',
'report_style',
'concise',
CURRENT_TIMESTAMP,
CURRENT_TIMESTAMP
);
The application should use parameterized queries rather than building SQL strings from user input.
Update Existing Memory
Memory is often changed rather than simply inserted.
For example, a user may initially prefer detailed reports and later request concise reports.
The application should update the existing preference instead of creating conflicting records.
Conceptually:
Existing:
report_style = detailed
User changes preference
New:
report_style = concise
A unique constraint can help prevent duplicate memory keys for the same user and memory type.
For example:
CREATE UNIQUE INDEX ux_agent_memory
ON agent_memories(user_id, memory_type, memory_key);
This gives the application a clear identity for each memory item.
Retrieve Memory Before Calling the AI Model
The typical request flow becomes:
User Request
|
v
Load Relevant Memory
|
v
Load Recent Conversation
|
v
Build Model Context
|
v
Call AI Model
|
v
Process Response
|
v
Update Memory
|
v
Return Response
The model does not directly query MariaDB.
The application retrieves the required information and decides what should be sent to the model.
This keeps database access under application control.
Example Memory Retrieval
A query might retrieve the user's current preferences:
SELECT
memory_type,
memory_key,
memory_value
FROM agent_memories
WHERE user_id = ?
ORDER BY updated_at DESC;
The application can then convert the result into model context.
For example:
User preferences:
- Report style: concise
- Preferred language: English
- Default region: North
Only relevant memories should be included in the prompt.
Do Not Send All Memory to the Model
A user may have hundreds of historical memory records.
Sending all of them with every request is inefficient.
Instead, use memory selection.
For example, if the user asks about a sales report, retrieve memories related to:
report format
region
active project
sales preferences
There is no reason to include unrelated information such as an old support conversation.
This distinction becomes increasingly important as an agent becomes more capable.
Store Conversation History Separately
Conversation history should normally remain separate from long-term memory.
For example:
agent_messages
--------------
message_id
session_id
role
content
created_at
A conversation might contain:
User:
Create a sales report.
Agent:
What region should I use?
User:
North.
Agent:
I will use the North region.
The application can retain the conversation while separately storing a useful memory:
active_report_region = North
This avoids forcing the model to reconstruct important facts from the entire conversation.
Use Summaries for Long Conversations
Long conversations can eventually exceed the practical context window of an AI model.
A common approach is to create a summary.
Full Conversation
|
v
Summary Generation
|
v
Stored Session Summary
The database can store the summary:
CREATE TABLE agent_session_summaries
(
session_id BIGINT PRIMARY KEY,
summary TEXT NOT NULL,
updated_at TIMESTAMP NOT NULL
);
The application can then use the summary together with recent messages.
A practical context might contain:
Session summary
+
Last 10 messages
+
Relevant long-term memories
+
Current task state
This is usually more manageable than sending the complete conversation.
Track Memory Source
Memory should have a source whenever possible.
For example:
memory_type
memory_key
memory_value
source
created_at
updated_at
The source could identify whether the memory came from:
User statement
Application rule
Agent observation
Imported profile data
Approved workflow
This becomes useful when an application needs to determine whether a memory is trustworthy.
For example, a user explicitly stating a preference is different from an AI model guessing a preference.
Avoid Treating AI Inference as User Fact
An agent may infer:
The user probably prefers detailed reports.
That should not automatically become permanent memory.
A safer flow is:
AI inference
|
v
Candidate memory
|
v
Validation or confirmation
|
v
Persistent memory
This reduces the risk of storing incorrect assumptions about users.
Add Memory Expiration
Not every memory should remain forever.
For example:
Temporary task state
Expires after task completion
Session context
Expires after retention period
User preference
May remain longer
Tool result
May expire quickly
A memory table can contain an expiration field:
ALTER TABLE agent_memories
ADD COLUMN expires_at TIMESTAMP NULL;
The application can then remove or ignore expired records.
For example:
DELETE FROM agent_memories
WHERE expires_at IS NOT NULL
AND expires_at < CURRENT_TIMESTAMP;
The exact retention strategy should match the application's requirements.
Handle Concurrent Agent Requests
Two requests may update the same memory at almost the same time.
For example:
Request A
|
+-- Reads preference = detailed
|
+-- Updates preference = concise
Request B
|
+-- Reads preference = detailed
|
+-- Updates preference = short
Without concurrency control, the final state may not be what the application expects.
Use appropriate database constraints and update strategies.
For important state, consider optimistic concurrency using a version column.
memory_id
version
memory_value
updated_at
An update can verify that the version has not changed before writing the new value.
Store Agent Task State
Memory is also useful for long-running agent workflows.
Suppose an agent performs:
1. Read customer request
2. Validate account
3. Call billing tool
4. Generate result
5. Send notification
The database can store the current state:
task_id
status
current_step
last_successful_step
updated_at
If the process fails after step 3, the application can resume from the stored state instead of starting from the beginning.
Store Tool Results Carefully
Agents often call external tools.
For example:
Agent
|
+-- CRM Tool
|
+-- Billing Tool
|
+-- Search Tool
Tool results can be useful during a task, but storing every raw response permanently may create unnecessary storage and privacy concerns.
Store only the information needed for:
Large temporary payloads can have a shorter retention period.
Protect Sensitive Memory
Agent memory can contain highly sensitive information.
Examples include:
Customer information
Internal business rules
Conversation content
Tool responses
Account information
Private preferences
Use appropriate database security controls.
Important considerations include:
Do not expose the complete memory table to an AI model or application component that does not require it.
Multi-Tenant Memory Isolation
For applications serving multiple customers, every persistent memory record should be associated with the correct tenant.
For example:
agent_memories
--------------
tenant_id
user_id
memory_type
memory_key
memory_value
Retrieval should always apply the appropriate tenant filter.
SELECT
memory_type,
memory_key,
memory_value
FROM agent_memories
WHERE tenant_id = ?
AND user_id = ?;
This prevents accidental memory leakage between customers.
Tenant filtering should be enforced in application code and, where practical, supported by the database design.
Common Mistakes
Storing Everything as Memory
Not every conversation message deserves permanent storage as long-term memory.
Separate conversation history from useful persistent facts.
Sending All Memory to the Model
Retrieve only information relevant to the current request.
Allowing the Model to Write Memory Without Validation
AI-generated assumptions can be wrong. Important long-term memories should be validated before being persisted.
Using One Large Session Document
A large document containing the entire conversation, task state, preferences, and tool results becomes difficult to update and query.
Use separate structures for different memory types.
Ignoring Expiration
Temporary information can remain in the database indefinitely unless retention rules are defined.
Missing Tenant Filters
A memory system without strict tenant isolation can expose one customer's context to another customer.
Best Practices
Separate short-term context from long-term memory.
Store memory as structured records.
Give each memory a clear type and key.
Keep conversation messages separate from persistent user preferences.
Store source information when practical.
Validate AI-generated memories before persisting them.
Add expiration rules for temporary data.
Use versioning or concurrency control for important state.
Store only the tool results required for future processing.
Apply tenant isolation to every memory query.
Retrieve only relevant memory for each model request.
Summarize long conversations instead of sending complete history.
Monitor memory storage growth and retrieval latency.
Define retention policies before deploying persistent agent memory.
Advantages
Agent context can survive across requests.
Long-running tasks can resume after interruptions.
User preferences can be reused across sessions.
Structured memory is easier to query and update than raw conversation text.
MariaDB can keep business data and related agent state within the same application data architecture.
Persistent task state improves the reliability of multi-step agent workflows.
Disadvantages and Considerations
Memory storage grows as the number of users and sessions increases.
Poor retrieval rules can send irrelevant information to the AI model.
Incorrect memories can affect future responses.
Sensitive conversation data requires careful security and retention controls.
Concurrent requests can create conflicting updates.
Long-term memory needs maintenance, expiration, and cleanup.
When MariaDB Agent Memory Makes Sense
MariaDB is a reasonable option for agent memory when the application already uses a relational database and needs structured persistence for users, conversations, tasks, preferences, and agent state.
It works particularly well when memory has clear relationships with business data.
For example, a customer support agent may need to connect:
Customer
|
+-- Support Cases
+-- Conversations
+-- Preferences
+-- Agent Tasks
+-- Agent Memory
Keeping these relationships in a relational system can make application logic easier to maintain.
However, the database should not become an unrestricted storage location for every model output. A useful memory system requires clear rules about what is stored, how it is retrieved, and when it expires.
Summary
MariaDB can provide a practical persistence layer for AI agent memory when an application needs context to survive beyond a single request.
The most important design decision is to separate different types of memory. Conversation history, user preferences, task state, tool results, and long-term facts have different lifetimes and should not automatically be stored in the same way.
Store useful information as structured records, retrieve only relevant memory before calling the AI model, and validate important memories before treating them as persistent facts. Use expiration rules for temporary data, concurrency controls for changing state, and strict tenant isolation for multi-user applications.
A well-designed memory layer gives an AI agent continuity without requiring the model to remember everything. The database provides persistence, while the application remains responsible for deciding what the agent should remember and when that information should be used.
Join the conversation! Your thoughts help the community grow.