Storage Control
Control what session data gets persisted to your database
Before running the examples, create and activate a virtual environment:
uv pip install agno openai sqlalchemy
export OPENAI_API_KEY="your-api-key"As sessions accumulate data, your database can grow quickly. Agno gives you fine-grained control over what gets persisted with three storage flags:
store_media- Images, videos, audio, and file uploadsstore_tool_messages- Tool calls and their resultsstore_history_messages- Duplicate history messages loaded into the current run
Storage control works identically for Agents and Teams. This page shows examples for both.
How Storage Control Works
These flags filter the stored copy of a run. They do not prevent its current model call from receiving supplied media or tool results, and token metrics still reflect actual usage. Later runs can only replay what remains in storage. Paused or resumable runs have additional preservation rules for continuation data.
When you optimise what messages you store in the database, it might cause hallucinations on the LLM, if any of the messages are essential to the conversation history. If you don't rely too heavily on history, you can safely optimise storage.
For example, if you remove tool call messages, it won't be available in subsequent runs where history is enabled, which could cause the LLM to think that tool was never used.
Important: store_tool_messages=False removes tool-call and result pairs
When you disable tool message storage, Agno removes both the tool result and the assistant message that made the tool call. This is required to maintain valid message sequences that model providers expect.
Your metrics will still show the actual tokens used, including the removed tool messages.
Storage Flags Reference
| Flag | Default | What It Controls | Impact When Disabled |
|---|---|---|---|
store_media | True | Images, videos, audio, files uploaded by users | Media not persisted to database |
store_tool_messages | True | Tool calls and their results (also removes corresponding assistant messages) | Tool execution details not stored, saves significant space |
store_history_messages | False | Copies marked from_history in the current run | Duplicate copies omitted; original earlier run records remain |
Disable Media Storage
Large media uploads (images, PDFs, audio) can dominate your session tables. store_media=False drops them entirely. To keep the media but move it out of the database, set media_storage instead.
from agno.agent import Agent
from agno.models.openai import OpenAIResponses
from agno.db.sqlite import SqliteDb
agent = Agent(
model=OpenAIResponses(id="gpt-5.2"),
db=SqliteDb(db_file="tmp/agent.db"),
store_media=False,
)During a run the model still receives the media (and tools can still process it); the flag only affects what is written to the database afterward.
Keep the Media, Move It Off the Database
The S3 examples require uv pip install "agno[s3]" and an existing bucket with read, write, and delete permissions. Replace my-bucket and configure credentials using the S3 guide.
Keep store_media=True (the default) with media_storage to offload media. store_media=False disables offload and removes the media. Agno uploads the bytes to S3, GCS, or the local filesystem and stores a reference in the row.
from agno.agent import Agent
from agno.db.sqlite import SqliteDb
from agno.media.storage import S3MediaStorage
from agno.models.openai import OpenAIResponses
agent = Agent(
model=OpenAIResponses(id="gpt-5.5"),
db=SqliteDb(db_file="tmp/agent.db"),
media_storage=S3MediaStorage(bucket="my-bucket"),
)See Media Storage for backends, credentials, and deletion.
Disable Tool Storage
Tool calls can easily bloat storage (think web-scraped pages or large API payloads). Toggle store_tool_messages=False to remove both the tool result and the assistant message that triggered it from the persisted run. Metrics still show the real token usage.
from agno.agent import Agent
from agno.models.openai import OpenAIResponses
from agno.db.sqlite import SqliteDb
from agno.tools.hackernews import HackerNewsTools
agent = Agent(
model=OpenAIResponses(id="gpt-5.2"),
tools=[HackerNewsTools()],
db=SqliteDb(db_file="tmp/agent.db"),
store_tool_messages=False,
)Considerations
- Removing tool messages keeps the provider-friendly message ordering intact (no stray tool roles)
- When auditing tool behavior later, re-run the tool or log its output somewhere else before the run completes
- Pair this with
store_media=Falsewhen tools return binary payloads you don't need in the session record
History Storage
store_history_messages=False removes duplicate copies tagged from_history from each new stored run. Original messages remain in their original run records, so normal session history and programmatic transcript access work with the default.
Set store_history_messages=True when you also need the loaded history copies inside each individual run record, for example to inspect that run's model context:
from agno.agent import Agent
from agno.models.openai import OpenAIResponses
from agno.db.sqlite import SqliteDb
agent = Agent(
model=OpenAIResponses(id="gpt-5.2"),
db=SqliteDb(db_file="tmp/agent.db"),
add_history_to_context=True,
num_history_runs=3,
store_history_messages=True,
)When to Enable It
Enable it to retain the history copies used by an individual run for debugging. Reading the original conversation across runs does not require it. The duplicated messages can substantially increase storage for long conversations.
Combining Storage Flags
You can use multiple flags together to optimize your storage strategy:
from agno.agent import Agent
from agno.models.openai import OpenAIResponses
from agno.db.sqlite import SqliteDb
agent = Agent(
model=OpenAIResponses(id="gpt-5.2"),
db=SqliteDb(db_file="tmp/agent.db"),
store_media=False, # Media discarded
store_tool_messages=False, # Tool results not needed
store_history_messages=False, # Omit duplicate loaded history
)Disable media or tool storage only when later replay and inspection do not need those values. Keep store_media=True when offloading media. Leave store_history_messages=False to avoid duplication while retaining each original run's messages.