--- title: "Agno memory: user memories, chat history and recall" description: "Agno memory keeps facts about each user_id and chat history per session in the agent's database. Add timestamped recall with source excerpts through a tool or MCPTools." canonical: https://past.dev/integrations/agno last-updated: 2026-10-09 --- # Add memory to Agno agents Source: https://past.dev/integrations/agno Agno memory keeps three kinds of state. User memories are facts about a user, written by a model and scoped by user_id across sessions. Chat history and session state are scoped by session_id. All three live in the database the agent is configured with. A tool that calls past.dev over HTTP adds timestamped ingestion and recall that returns ranked documents with dates and source excerpts. ## Agno memory scope The [memory guide](https://docs.agno.com/memory/overview) separates three features. **Memory** holds facts about a user, scoped to `user_id` across sessions. **Chat history** holds messages from previous runs, scoped to `session_id`. **Session state** holds application data that code or tools manage, also per session. All of it lives in the database passed as `db`, with memories in the `agno_memories` table by default. Two settings write user memories. `update_memory_on_run=True` processes each input into memories automatically. `enable_agentic_memory=True` gives the model an `update_user_memory` tool and lets it decide; when both are set, the agentic mode takes precedence. - **A memory is text about a user.** The guide recommends memory for preferences, profile details and recurring goals. It documents no event time and no validity period for a memory. - **Scope is one user.** Memories follow a `user_id`. A fact about an account or a team has no documented place beyond the user who stated it. - **Updates are undocumented.** The guide does not state whether a changed fact replaces a memory or keeps the earlier one. ## The integration: two tools An Agno agent takes plain Python functions in `tools`. The docstring becomes the description and the type hints become the schema ([Python function tools](https://docs.agno.com/tools/creating-tools/python-functions)). The `@tool` decorator from `agno.tools` adds options such as confirmation and result caching. A `run_context: RunContext` parameter is injected at execution time and omitted from the schema sent to the model, and `run_context.user_id` is the `user_id` of the run ([tool built-in parameters](https://docs.agno.com/tools/overview#tool-built-in-parameters)). ```python import os, requests from agno.agent import Agent from agno.run import RunContext BASE = "https://api.past.dev/api/v1" HEADERS = {"Authorization": f"Bearer {os.environ['PAST_API_KEY']}"} def remember(text: str, happened_at: str, run_context: RunContext) -> str: """Store timestamped source text, readable by the whole project, authored by the current user. Args: text (str): The source text. happened_at (str): ISO 8601 time the text was written or the event occurred. """ return requests.post(f"{BASE}/ingest", headers=HEADERS, json={ "content": text, "timestamp": happened_at, "identity": run_context.user_id, }).text def recall(question: str, run_context: RunContext) -> str: """Return ranked documents with dates and source excerpts for the current user. Args: question (str): The question to answer from memory. """ return requests.post(f"{BASE}/recall", headers=HEADERS, json={ "query": question, "identity": run_context.user_id, }).text agent = Agent( model=model, # any Agno model tools=[remember, recall], instructions="Call recall before you answer questions about people, decisions or history.", ) response = agent.run("What did we decide about the Q4 budget?", user_id="demo-user") ``` Keep user memories for preferences. Route source records through `remember` with the time they happened, and pass the signed-in user's id as `user_id` on each run. Agno keys its own user memories on the same value. > **Identity** > > The application sets the identity. The model never chooses it. Recall returns what the identity in the request may read, so take the identity from the signed-in user in code, and keep it out of every value that the model fills. Recall returns ranked documents with dates and source excerpts. The application decides whether those documents support an answer, contain a disagreement, or are insufficient; HTTP failures are handled separately. ## Or connect the MCP server Agno's `MCPTools` from `agno.tools.mcp` connects to a remote server with `transport="streamable-http"` and a `url` ([MCP tools](https://docs.agno.com/tools/mcp/overview)). The project's end-user MCP server then gives the agent `recall`, `answer` and `who_am_i`, plus `remember` while the project's write toggle is on, with no tool code to write. 1. Turn on the project's end-user MCP server on **Build › MCP server** in the console. 2. Mint an access link there, or with the account server's `create_mcp_access_link` tool. The link has the form `https://api.past.dev/mcp//link/`. It is one URL that is one identity, and the server answers it with no sign-in step. 3. Keep the link in a secret store, such as the `PAST_MCP_URL` environment variable that the code below reads. The secret in its path is the credential. ```python import asyncio, os from agno.agent import Agent from agno.tools.mcp import MCPTools async def main(): async with MCPTools(transport="streamable-http", url=os.environ["PAST_MCP_URL"]) as past: agent = Agent(model=model, tools=[past]) # model: any Agno model await agent.aprint_response("What did we decide about the Q4 budget?") asyncio.run(main()) ``` Every call through the link runs as its identity, with that identity's audiences. Mint one link per install, so that a revoked link stops one agent only. When the agent serves several people, mint one link per end user, and connect each request with the link of the user who makes it. Never share one link between users. `remember` writes to the identity's own private audience, and only that identity recalls it. Send data that the whole project must recall through the ingest call. The [end-user server documentation](/docs/mcp/serving-your-own-users) describes the tools, the links and revocation. ## When to use which | Requirement | Agno | past.dev via tool | | --- | --- | --- | | Continue a session | Chat history per session_id | No | | Preferences of one user | User memories per user_id | Recall as that user's identity | | Records from email, tickets and documents with their dates | No documented event time | `timestamp` on ingest | | What was true on a date | No documented query | `queryTimestamp` on recall | | Recall result | Memory text | Ranked documents with dates and source excerpts | The [quickstart](/docs/memory-api/quickstart) shows how to ingest, wait until ingestion completes, and recall. The [benchmarks](/benchmarks) document how recall quality is measured. [Facts that change over time](/guides/facts-that-change-over-time) covers the general temporal model. ## Frequently asked questions ### Does Agno have long-term memory? Yes. Agno stores facts about a user, scoped by user_id, in the agent's database and reads them in later sessions. A model writes them on each run, or through a memory tool when agentic memory is on. ### Do I keep Agno memory when I add past.dev? Yes. Agno memory fits preferences and profile details. past.dev fits source records that need their original dates, stable source ids, and recall with source excerpts across agents and applications. ## Related - [Memory for Pydantic AI](https://past.dev/integrations/pydantic-ai) - [Memory for CrewAI](https://past.dev/integrations/crewai) - [Memory for Strands Agents](https://past.dev/integrations/strands-agents) - [Long-term memory](https://past.dev/glossary/long-term-memory) - [Quickstart](https://past.dev/docs/memory-api/quickstart)