Traditional software follows a pre-programmed sequence of steps. Agents dynamically determine their course of action using a machine learning model, its core components are:
- Model: controls the flow of execution. It decides whether to reason, act or respond.
- Tools: enable an Agent to take actions and interact with external systems.
- Instructions: are how we program the Agent, teaching it how to use tools and respond.
Agents also have memory, knowledge, storage and the ability to reason:
- Reasoning: enables Agents to “think” before responding and “analyze” the results of their actions (i.e. tool calls), this improves reliability and quality of responses.
- Knowledge: is domain-specific information that the Agent can search at runtime to make better decisions and provide accurate responses (RAG). Knowledge is stored in a vector database and this search at runtime pattern is known as Agentic RAG/Agentic Search.
- Storage: is used by Agents to save session history and state in a database. Model APIs are stateless and storage enables us to continue conversations from where they left off. This makes Agents stateful, enabling multi-turn, long-term conversations.
- Memory: gives Agents the ability to store and recall information from previous interactions, allowing them to learn user preferences and personalize their responses.
Let’s build a few Agents to see how they work.
The simplest Agent has a model, a tool and instructions. Let’s build an Agent that can fetch data using the yfinance
library, along with instructions to display the results in a table.
from agno.agent import Agent
from agno.models.anthropic import Claude
from agno.tools.yfinance import YFinanceTools
agent = Agent(
model=Claude(id="claude-sonnet-4-20250514"),
tools=[YFinanceTools(stock_price=True)],
instructions="Use tables to display data. Don't include any other text.",
markdown=True,
)
agent.print_response("What is the stock price of Apple?", stream=True)
Create a virtual environment, install dependencies, export your API key and run the Agent.
Setup your virtual environment
uv venv --python 3.12
source .venv/bin/activate
Install dependencies
uv pip install -U agno anthropic yfinance
Export your Anthropic key
export ANTHROPIC_API_KEY=sk-***
Run the agent
python agent_with_tools.py
Set debug_mode=True
or export AGNO_DEBUG=true
to see the system prompt and user messages.
Level 2: Agents with knowledge and storage
Knowledge: While models have a large amount of training data, we almost always need to give them domain-specific information to make better decisions and provide accurate responses (RAG). We store this information in a vector database and let the Agent search it at runtime.
Storage: Model APIs are stateless and Storage
drivers save chat history and state to a database. When the Agent runs, it reads the chat history and state from the database and add it to the messages list, resuming the conversation and making the Agent stateful.
In this example, we’ll use:
UrlKnowledge
to load Agno documentation to LanceDB, using OpenAI for embeddings.
SqliteStorage
to save the Agent’s session history and state in a database.
from agno.agent import Agent
from agno.embedder.openai import OpenAIEmbedder
from agno.knowledge.url import UrlKnowledge
from agno.models.anthropic import Claude
from agno.storage.sqlite import SqliteStorage
from agno.vectordb.lancedb import LanceDb, SearchType
# Load Agno documentation in a knowledge base
# You can also use `https://docs.agno.com/llms-full.txt` for the full documentation
knowledge = UrlKnowledge(
urls=["https://docs.agno.com/introduction.md"],
vector_db=LanceDb(
uri="tmp/lancedb",
table_name="agno_docs",
search_type=SearchType.hybrid,
# Use OpenAI for embeddings
embedder=OpenAIEmbedder(id="text-embedding-3-small", dimensions=1536),
),
)
# Store agent sessions in a SQLite database
storage = SqliteStorage(table_name="agent_sessions", db_file="tmp/agent.db")
agent = Agent(
name="Agno Assist",
model=Claude(id="claude-sonnet-4-20250514"),
instructions=[
"Search your knowledge before answering the question.",
"Only include the output in your response. No other text.",
],
knowledge=knowledge,
storage=storage,
add_datetime_to_instructions=True,
# Add the chat history to the messages
add_history_to_messages=True,
# Number of history runs
num_history_runs=3,
markdown=True,
)
if __name__ == "__main__":
# Load the knowledge base, comment out after first run
# Set recreate to True to recreate the knowledge base if needed
agent.knowledge.load(recreate=False)
agent.print_response("What is Agno?", stream=True)
Install dependencies, export your OPENAI_API_KEY
and run the Agent
Install new dependencies
uv pip install -U lancedb tantivy openai sqlalchemy
Level 3: Agents with memory and reasoning
- Reasoning: enables Agents to “think” & “analyze”, improving reliability and quality.
ReasoningTools
is one of the best approaches to improve an Agent’s response quality.
- Memory: enables Agents to classify, store and recall user preferences, personalizing their responses. Memory helps the Agent build personas and learn from previous interactions.
from agno.agent import Agent
from agno.memory.v2.db.sqlite import SqliteMemoryDb
from agno.memory.v2.memory import Memory
from agno.models.anthropic import Claude
from agno.tools.reasoning import ReasoningTools
from agno.tools.yfinance import YFinanceTools
memory = Memory(
# Use any model for creating and managing memories
model=Claude(id="claude-sonnet-4-20250514"),
# Store memories in a SQLite database
db=SqliteMemoryDb(table_name="user_memories", db_file="tmp/agent.db"),
# We disable deletion by default, enable it if needed
delete_memories=True,
clear_memories=True,
)
agent = Agent(
model=Claude(id="claude-sonnet-4-20250514"),
tools=[
ReasoningTools(add_instructions=True),
YFinanceTools(stock_price=True, analyst_recommendations=True, company_info=True, company_news=True),
],
# User ID for storing memories, `default` if not provided
user_id="ava",
instructions=[
"Use tables to display data.",
"Include sources in your response.",
"Only include the report in your response. No other text.",
],
memory=memory,
# Let the Agent manage its memories
enable_agentic_memory=True,
markdown=True,
)
if __name__ == "__main__":
# This will create a memory that "ava's" favorite stocks are NVIDIA and TSLA
agent.print_response(
"My favorite stocks are NVIDIA and TSLA",
stream=True,
show_full_reasoning=True,
stream_intermediate_steps=True,
)
# This will use the memory to answer the question
agent.print_response(
"Can you compare my favorite stocks?",
stream=True,
show_full_reasoning=True,
stream_intermediate_steps=True,
)
Run the Agent
You can use the Memory
and Reasoning
separately, you don’t need to use them together.