supermemory/apps/docs/integrations/agno.mdx
MaheshtheDev 672defc08b docs: move SDK snippets to the shipped v5 call shape and finish the namespace rename (#1772)
Rewrites 339 TypeScript calls across 50 pages from the rc.5 `method({ namespace, body })` form to the shipped `method(namespace, { ... })` form, and aligns field names with the live v5 spec: `attach` to `include`, `authUrl` to `authorization`, `lastSync` to `latestRun`, `deletedCount` to `count`, and the paginated `namespaces.list()`.

Renames container tags to namespaces across concepts, connectors, integrations and snippets. The namespace pages keep container tag in the description, search keywords and a rename note so old searches still land, and the v3 reference page points at v5.

The migration guide's SDK table now covers both 5.0.0 SDKs, and the SDK integration page uses the real client options (`baseUrl`, `timeoutInSeconds`, `maxRetries`) and error classes.
2026-10-06 17:06:38 +00:00

380 lines
9.8 KiB
Text

---
title: "Agno"
sidebarTitle: "Agno"
description: "Add persistent memory to Agno agents with Supermemory"
icon: "/icons/hugeicons/brain-01.svg"
---
Agno agents are stateless by default. Each conversation starts fresh. Supermemory changes that - your agents can remember users, recall past conversations, and build on previous interactions.
## What you can do
- Give agents access to user profiles and conversation history
- Store agent interactions for future sessions
- Let agents search memories to answer questions with context
## Setup
Install the packages:
```bash
pip install agno supermemory python-dotenv
```
Set up your environment:
```bash
# .env
SUPERMEMORY_API_KEY=your-supermemory-api-key
OPENAI_API_KEY=your-openai-api-key
```
<Note>Get your Supermemory API key from [console.supermemory.ai](https://console.supermemory.ai).</Note>
## Basic integration
Fetch user context before running an agent, then store the interaction after.
```python
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from supermemory import Supermemory
from dotenv import load_dotenv
load_dotenv()
memory = Supermemory()
def get_user_context(user_id: str, query: str) -> str:
"""Pull user profile and relevant memories."""
profile = memory.profile(user_id).profile
memories = memory.search(user_id, query=query, limit=5).results
static = [m.memory for m in profile.static]
dynamic = [m.memory for m in profile.dynamic]
return f"""
User background:
{chr(10).join(static) if static else 'No profile yet.'}
Recent activity:
{chr(10).join(dynamic) if dynamic else 'Nothing recent.'}
Related memories:
{chr(10).join([m.memory or m.chunk for m in memories[:5]]) if memories else 'None.'}
"""
def create_agent(user_id: str, task: str) -> Agent:
"""Create an agent with user context."""
context = get_user_context(user_id, task)
return Agent(
name="assistant",
model=OpenAIChat(id="gpt-4o"),
description=f"""You are a helpful assistant.
Here's what you know about this user:
{context}
Use this to personalize your responses.""",
markdown=True
)
def chat(user_id: str, message: str) -> str:
"""Run the agent and store the interaction."""
agent = create_agent(user_id, message)
response = agent.run(message)
# Save for next time
memory.add(
user_id,
content=f"User: {message}\nAssistant: {response.content}",
dreaming="instant"
)
return response.content
```
---
## Core concepts
### User profiles
Supermemory keeps two buckets of user info:
- **Static facts**: Things that stay consistent (name, preferences, expertise)
- **Dynamic context**: What they're focused on lately
```python
result = memory.profile("user_123")
print([m.memory for m in result.profile.static]) # ["Vegetarian", "Allergic to nuts"]
print([m.memory for m in result.profile.dynamic]) # ["Learning Italian cuisine", "Meal prepping"]
```
### Storing memories
Save interactions so future sessions have context:
```python
def store_chat(user_id: str, user_msg: str, agent_response: str):
memory.add(
user_id,
content=f"User asked: {user_msg}\nAgent said: {agent_response}",
metadata={"type": "conversation"},
dreaming="instant"
)
```
### Searching memories
Look up past interactions:
```python
results = memory.search(
"user_123",
query="pasta recipes we discussed",
search_mode="hybrid", # Searches memories + document chunks
limit=5
)
for r in results.results:
print(r.memory or r.chunk)
```
---
## Example: personal assistant with memory
An assistant that actually knows who it's talking to. Preferences stick around. Past conversations inform new ones.
```python
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from supermemory import Supermemory
from dotenv import load_dotenv
load_dotenv()
class PersonalAssistant:
def __init__(self):
self.memory = Supermemory()
def get_context(self, user_id: str, query: str) -> dict:
"""Fetch user profile and relevant history."""
profile = self.memory.profile(user_id).profile
memories = self.memory.search(user_id, query=query, threshold=0.5).results
return {
"profile": [m.memory for m in profile.static],
"recent": [m.memory for m in profile.dynamic],
"history": [m.memory or m.chunk for m in memories[:3]]
}
def build_description(self, context: dict) -> str:
"""Turn context into agent description."""
parts = ["You are a helpful personal assistant."]
if context["profile"]:
parts.append(f"About this user: {', '.join(context['profile'])}")
if context["recent"]:
parts.append(f"They're currently: {', '.join(context['recent'])}")
if context["history"]:
parts.append(f"Past conversations: {'; '.join(context['history'])}")
parts.append("Reference what you know about them when relevant.")
return "\n\n".join(parts)
def create_agent(self, context: dict) -> Agent:
return Agent(
name="assistant",
model=OpenAIChat(id="gpt-4o"),
description=self.build_description(context),
markdown=True
)
def chat(self, user_id: str, message: str) -> str:
"""Handle a message and remember the interaction."""
context = self.get_context(user_id, message)
agent = self.create_agent(context)
response = agent.run(message)
# Store for future sessions
self.memory.add(
user_id,
content=f"User: {message}\nAssistant: {response.content}",
metadata={"type": "chat"},
dreaming="instant"
)
return response.content
def teach(self, user_id: str, fact: str):
"""Store a preference or fact about the user."""
self.memory.add(
user_id,
content=fact,
metadata={"type": "preference"},
dreaming="instant"
)
if __name__ == "__main__":
assistant = PersonalAssistant()
# Teach it some preferences
assistant.teach("user_1", "Prefers concise answers")
assistant.teach("user_1", "Works in software engineering")
# Chat
response = assistant.chat("user_1", "What's a good way to learn Rust?")
print(response)
```
---
## Using Agno tools with memory
Give your agent tools that can search and store memories directly.
```python
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.tools import tool
from supermemory import Supermemory
memory = Supermemory()
@tool
def search_memory(query: str, user_id: str) -> str:
"""Search for information in the user's memory.
Args:
query: What to look for
user_id: The user's ID
"""
results = memory.search(user_id, query=query, limit=5)
if not results.results:
return "Nothing relevant found in memory."
return "\n".join([r.memory or r.chunk for r in results.results])
@tool
def remember(content: str, user_id: str) -> str:
"""Store something important about the user.
Args:
content: What to remember
user_id: The user's ID
"""
memory.add(user_id, content=content, dreaming="instant")
return f"Remembered: {content}"
agent = Agent(
name="memory_agent",
model=OpenAIChat(id="gpt-4o"),
tools=[search_memory, remember],
description="""You are an assistant with memory.
When users share preferences or important info, use the remember tool.
When they ask about past conversations, search your memory first.""",
markdown=True
)
```
---
## Image context with memory
Agno handles images too. When users share photos, you can store what the agent saw for later.
```python
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.media import Image
from pathlib import Path
from supermemory import Supermemory
memory = Supermemory()
def analyze_and_remember(user_id: str, image_path: str, question: str) -> str:
"""Analyze an image, answer a question, and store the context."""
agent = Agent(
name="vision_agent",
model=OpenAIChat(id="gpt-4o"),
description="You analyze images and answer questions about them.",
markdown=True
)
# Get the agent's analysis
response = agent.run(question, images=[Image(filepath=Path(image_path))])
# Store the interaction with image context
memory.add(
user_id,
content=f"User shared an image and asked: {question}\nAnalysis: {response.content}",
metadata={"type": "image_analysis", "image": image_path},
dreaming="instant"
)
return response.content
```
---
## Metadata for filtering
Tags let you narrow down searches:
```python
# Store with metadata
memory.add(
"user_123",
content="User prefers dark mode interfaces",
dreaming="instant",
metadata={
"type": "preference",
"category": "ui",
"source": "onboarding"
}
)
# Search with filters
results = memory.search(
"user_123",
query="interface preferences",
filter={
"operator": "and",
"operands": [
{"field": "type", "operator": "eq", "value": "preference"},
{"field": "category", "operator": "eq", "value": "ui"}
]
}
)
```
---
## Related docs
<CardGroup cols={2}>
<Card title="User profiles" icon="/icons/hugeicons/user.svg" href="/recall/user-profiles">
How automatic profiling works
</Card>
<Card title="Search" icon="/icons/hugeicons/search-01.svg" href="/recall/search">
Filtering and search modes
</Card>
<Card title="LangChain" icon="/icons/hugeicons/link-01.svg" href="/integrations/langchain">
Memory for LangChain apps
</Card>
<Card title="CrewAI" icon="/icons/hugeicons/user-multiple.svg" href="/integrations/crewai">
Multi-agent systems with memory
</Card>
</CardGroup>