Agno is a Python SDK for building, running, and managing agent platforms. You use it to create AI agents in a handful of lines, compose them into multi-agent teams and deterministic workflows, give them tools, memory, and knowledge, and then run the whole thing as a production HTTP service with tracing, scheduling, human approvals, and role-based access control — all in your own infrastructure.
This guide is task-oriented: it shows you how to install Agno, build your first agent, and progressively add every capability the framework offers. Architecture, deployment internals, security hardening, and the full configuration reference live in the companion Admin Guide.
Note
Agno is an SDK and library, not a command-line application. You build agents in Python and run them as scripts or services. The only shipped CLI (
ag/agno) belongs to the separateagno-infrapackage and is used for scaffolding and deploying AgentOS projects — see Deploying with theagCLI.
Table of Contents
- What Is Agno
- Quick Start
- Installation
- Core Concepts
- Building Agents
- Models and Providers
- Tools and Toolkits
- Knowledge and RAG
- Memory
- Sessions, State, and History
- Structured Input and Output
- Reasoning
- Guardrails, Hooks, and Human-in-the-Loop
- Multi-Agent Teams
- Workflows
- Running as a Service: AgentOS
- Deploying with the
agCLI - Common Recipes
- Troubleshooting
- Frequently Asked Questions
- Reference
1. What Is Agno
Agno lets you own your entire agent stack. You keep control of your data, context, tools, permissions, memory, and human-review loops; you run the platform in your own cloud; and you manage it through a single control plane.
At its heart, Agno gives you three composable primitives:
| Primitive | Import | What it does |
|---|---|---|
| Agent | from agno.agent import Agent |
A single model + instructions + tools + memory + knowledge. The fundamental unit. |
| Team | from agno.team import Team |
A group of agents (or nested teams) coordinated by a leader, in one of four execution modes. |
| Workflow | from agno.workflow import Workflow |
A deterministic, step-based pipeline (sequences, loops, branches, parallel fan-out) over agents and functions. |
Around those primitives, Agno provides everything a production agent platform needs:
- 50+ model providers behind one
Modelinterface — OpenAI, Anthropic, Google, Groq, Mistral, Ollama, AWS Bedrock, Azure, and dozens more. - ~130 pre-built toolkits — web search, finance data, code execution, databases, Slack, GitHub, Gmail, and many others.
- Knowledge / RAG with readers, chunkers, embedders, rerankers, and 18+ vector databases.
- Memory that persists user facts across sessions.
- Storage for sessions, runs, memory, knowledge, and traces in your own database (PostgreSQL, MySQL, SQLite, MongoDB, Redis, DynamoDB, and more).
- AgentOS — a FastAPI runtime that exposes your agents as a production API with SSE/WebSocket streaming, JWT-based RBAC, OpenTelemetry tracing, cron scheduling, human-approval gates, and chat interfaces for Slack, Telegram, WhatsApp, AG-UI, and A2A.
Tip
If you only want a chatbot in a script, you need just the
agnopackage and one model provider. If you want to serve agents over HTTP for a product, addagno[os]. If you want to deploy that to a cloud, addagno-infra. Each layer is opt-in.
2. Quick Start
Install Agno with a model provider
OpenAI
pip install -U agno openai
export OPENAI_API_KEY=sk-...
Anthropic
pip install -U "agno[anthropic]"
export ANTHROPIC_API_KEY=sk-ant-...
Google Gemini
pip install -U "agno[google]"
export GOOGLE_API_KEY=...
Your first agent
Create finance_agent.py:
from agno.agent import Agent
from agno.models.openai import OpenAIChat
agent = Agent(
model=OpenAIChat(id="gpt-4o"),
instructions="You are a concise financial analyst. Facts only, no speculation.",
markdown=True,
)
agent.print_response("Explain what a P/E ratio is in two sentences.", stream=True)
Run it:
python finance_agent.py
The price-to-earnings (P/E) ratio measures a company's current share price
relative to its earnings per share. A higher P/E suggests investors expect
higher future growth, while a lower P/E may indicate a more conservatively
valued or slower-growing company.
Note
print_response()renders the answer to your terminal (with live streaming whenstream=True). For programmatic use, callagent.run(...), which returns aRunOutputobject you can inspect — see Building Agents.
Add a tool
Tools let the model fetch live data or take actions. Here the agent uses real Yahoo Finance data:
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.tools.yfinance import YFinanceTools
agent = Agent(
model=OpenAIChat(id="gpt-4o"),
tools=[YFinanceTools(all=True)],
instructions="You are a finance analyst. Always note the data timestamp.",
add_datetime_to_context=True,
markdown=True,
)
agent.print_response("Give me a quick investment brief on NVIDIA", stream=True)
pip install yfinance # or: pip install "agno[yfinance]"
python finance_agent.py
That is the whole loop: a model, instructions, and tools. Everything else in this guide builds on this pattern.
3. Installation
Requirements
| Requirement | Detail |
|---|---|
| Python | 3.7+ (requires-python = ">=3.7,<4"). Type hints target 3.9+; 3.10+ recommended. |
| OS | OS-independent (Linux, macOS, Windows). |
| Core dependencies | pydantic, pydantic-settings, httpx, typer, rich, gitpython, pyyaml, python-dotenv (installed automatically). |
| Model provider | At least one (e.g. openai, anthropic, google-genai) — installed via extras. |
The base agno package is intentionally lightweight. Model providers, tools, databases, vector stores, and the server runtime are all optional extras you add as needed.
Install the base package
pip install -U agno
Extras matrix
Install extras with pip install "agno[<extra>]". You can combine them: pip install "agno[openai,os,pgvector]".
Model providers
| Extra | Installs | Provider |
|---|---|---|
agno[openai] |
openai |
OpenAI |
agno[anthropic] |
anthropic |
Anthropic Claude |
agno[google] |
google-genai |
Google Gemini |
agno[groq] |
groq |
Groq |
agno[mistral] |
mistralai |
Mistral |
agno[ollama] |
ollama |
Ollama (local) |
agno[aws-bedrock] |
boto3, aioboto3 |
AWS Bedrock |
agno[azure] |
azure-ai-inference |
Azure AI |
agno[cohere] |
cohere |
Cohere |
agno[ibm] |
ibm-watsonx-ai |
IBM watsonx |
agno[litellm] |
litellm |
LiteLLM gateway |
agno[meta] |
llama-api-client |
Meta Llama API |
agno[lmstudio] |
lmstudio |
LM Studio |
agno[portkey] |
portkey-ai |
Portkey |
agno[models] |
all of the above (curated set) | Everything |
Warning
As of this writing, the
agno[models]meta-extra temporarily excludeslitellmandmistralaibecause of upstream PyPI supply-chain incidents (see the Admin Guide's security section). Install them individually only if you have verified the upstream package.
Server runtime, storage, and infrastructure
| Extra | Installs | Purpose |
|---|---|---|
agno[os] |
fastapi[standard], uvicorn, sqlalchemy, PyJWT, opentelemetry-sdk, croniter, pytz |
The AgentOS FastAPI runtime |
agno[scheduler] |
croniter, pytz |
Cron scheduling |
agno[sql] / agno[postgres] / agno[sqlite] / agno[mysql] |
SQLAlchemy + driver | Relational session/run storage |
agno[async_postgres] / agno[async_mongo] |
asyncpg / motor |
Async storage drivers |
agno[redis] |
redis, redisvl |
Redis storage |
agno[gcs] / agno[firestore] |
Google Cloud storage backends | |
agno[infra] / agno[docker] / agno[aws] |
agno-infra (+ extras) |
Deployment tooling |
Vector databases (agno[vectordbs] for all)
agno[pgvector], agno[chromadb], agno[lancedb], agno[qdrant], agno[milvusdb], agno[weaviate], agno[mongodb], agno[pinecone], agno[couchbase], agno[cassandra], agno[clickhouse], agno[singlestore], agno[surrealdb], agno[upstash], agno[redis].
Knowledge / document readers (agno[knowledge] for all)
agno[pdf], agno[docx], agno[pptx], agno[csv], agno[excel], agno[text], agno[markdown], agno[docling], agno[chonkie] (chunking).
Interfaces and integrations
| Extra | Purpose |
|---|---|
agno[slack] |
Slack chat interface |
agno[telegram] |
Telegram interface |
agno[whatsapp-crypto] |
WhatsApp encryption support |
agno[agui] |
AG-UI protocol integration |
agno[a2a] |
Agent-to-Agent (A2A) protocol |
agno[mcp] |
Model Context Protocol tools |
Observability
agno[opentelemetry], agno[langfuse], agno[arize], agno[weave], agno[openlit].
Tip
Tool extras follow the same pattern —
agno[exa],agno[github],agno[gmail],agno[duckdb],agno[firecrawl], and many more. Installagno[tools]to pull a curated bundle, or add individual tool extras as you adopt them.
Set provider credentials
Most providers read an API key from an environment variable. Agno loads a .env file automatically (via python-dotenv):
# .env
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
GOOGLE_API_KEY=...
4. Core Concepts
| Concept | Description |
|---|---|
| Agent | The atomic unit: one Model, instructions, optional tools, memory, knowledge, and a database for persistence. Runs via run() / arun() / print_response(). |
| Model | A provider-backed LLM wrapper (OpenAIChat, Claude, Gemini, …). Implements a common interface so agents are provider-agnostic. |
| Tool / Toolkit | A function (or class of functions) the model can call. Toolkits bundle related functions (e.g. YFinanceTools). |
| Team | A leader agent plus members, run in coordinate, route, broadcast, or tasks mode. |
| Workflow | A deterministic graph of Steps with control-flow primitives (Loop, Parallel, Condition, Router, Steps). |
| Knowledge | A searchable corpus (RAG): documents → chunks → embeddings → vector DB, queried at run time. |
| Memory | Long-lived facts about a user, captured and recalled across sessions. |
| Session | A conversation thread, identified by session_id, persisted in a Db. Carries history and session_state. |
| Db | A storage backend (PostgreSQL, SQLite, MySQL, MongoDB, Redis, DynamoDB, …) for sessions, runs, memory, knowledge metadata, and traces. |
| AgentOS | A FastAPI app that serves your agents/teams/workflows as a production API with auth, tracing, scheduling, and chat interfaces. |
These objects compose. An Agent can have knowledge, memory, tools, and a db. A Team contains Agents. A Workflow orchestrates Agents, Teams, and plain functions. An AgentOS exposes any of them over HTTP.
5. Building Agents
The Agent constructor is where almost all configuration happens. It accepts roughly 150 keyword arguments, grouped by capability below. Every argument is keyword-only and optional except where noted.
from agno.agent import Agent
from agno.models.openai import OpenAIChat
agent = Agent(
name="Support Agent",
model=OpenAIChat(id="gpt-4o"),
description="A helpful customer-support assistant.",
instructions=[
"Answer in plain language.",
"If you don't know, say so.",
],
markdown=True,
)
Running an agent
| Method | Returns | Use |
|---|---|---|
agent.run(input, ...) |
RunOutput |
Synchronous run; inspect .content, .messages, .metrics. |
await agent.arun(input, ...) |
RunOutput |
Async run. |
agent.print_response(input, stream=True) |
— | Pretty-print to terminal (great for demos). |
await agent.aprint_response(...) |
— | Async pretty-print. |
agent.cli_app() |
— | Launch an interactive REPL chat loop in the terminal. |
agent.continue_run(...) |
RunOutput |
Resume a run that was paused (e.g. for human approval). |
result = agent.run("What is the capital of France?")
print(result.content) # "Paris"
Important
If your instructions, tools, or system message are defined as async callables, you must use
arun()/aprint_response(). Callingrun()will raiseInstructions function is async, use agent.arun() instead.
Identity and model
| Argument | Type | Default | Description |
|---|---|---|---|
model |
Model | str |
None |
The LLM. Pass a model object or a "provider:id" string (e.g. "openai:gpt-4o"). |
fallback_models |
list[Model | str] |
None |
Models tried in order if the primary fails. |
fallback_config |
FallbackConfig |
None |
Advanced error-specific fallback routing. |
name |
str |
None |
Human-readable agent name. |
id |
str |
autogenerated | Stable agent ID. |
Instructions and system message
| Argument | Type | Default | Description |
|---|---|---|---|
description |
str |
None |
Added to the start of the system message. |
instructions |
str | list[str] | Callable |
None |
The agent's task instructions. |
expected_output |
str |
None |
Describes the desired output shape. |
additional_context |
str |
None |
Extra text appended to the system message. |
system_message |
str | Callable | Message |
None |
Override the entire system message. |
markdown |
bool |
False |
Instruct the model to format output as Markdown. |
add_datetime_to_context |
bool |
False |
Inject the current datetime (enables "tomorrow"-style reasoning). |
add_location_to_context |
bool |
False |
Inject the current location. |
add_name_to_context |
bool |
False |
Tell the agent its own name. |
use_instruction_tags |
bool |
False |
Wrap instructions in <instructions> tags. |
Tools
| Argument | Type | Default | Description |
|---|---|---|---|
tools |
list[Toolkit | Callable | Function | dict] | Callable |
None |
Tools the model may call. Can be a factory returning tools at run time. |
tool_call_limit |
int |
None |
Max tool calls per run. |
tool_choice |
str | dict |
None |
"auto", "none", or force a specific function. |
tool_hooks |
list[Callable] |
None |
Middleware wrapped around each tool call. |
See Tools and Toolkits.
Knowledge (RAG)
| Argument | Type | Default | Description |
|---|---|---|---|
knowledge |
Knowledge |
None |
A knowledge base to search. |
search_knowledge |
bool |
True |
Give the agent a tool to search knowledge (Agentic RAG). Active only when knowledge is set. |
add_knowledge_to_context |
bool |
False |
Inject retrieved references directly into the prompt. |
knowledge_filters |
dict | list[FilterExpr] |
None |
Metadata filters applied to searches. |
enable_agentic_knowledge_filters |
bool |
False |
Let the agent choose filters itself. |
knowledge_retriever |
Callable |
None |
Custom retrieval function replacing the default search. |
See Knowledge and RAG.
Memory
| Argument | Type | Default | Description |
|---|---|---|---|
memory_manager |
MemoryManager |
None |
Custom memory manager. |
enable_agentic_memory |
bool |
False |
Let the agent manage user memories via tools. |
update_memory_on_run |
bool |
False |
Create/update user memories at the end of each run. |
add_memories_to_context |
bool |
None |
Inject stored memories into the prompt. |
See Memory.
Sessions, state, and history
| Argument | Type | Default | Description |
|---|---|---|---|
db |
BaseDb | AsyncBaseDb |
None |
Database for persisting sessions, runs, and memory. |
session_id |
str |
autogenerated | Conversation thread identifier. |
user_id |
str |
None |
Default user for this agent. |
session_state |
dict |
None |
Mutable state persisted across runs in the session. |
add_session_state_to_context |
bool |
False |
Include session_state in the prompt. |
enable_agentic_state |
bool |
False |
Give the agent tools to update session_state. |
add_history_to_context |
bool |
False |
Include prior messages from the session. |
num_history_runs |
int |
None |
How many past runs to include. |
search_past_sessions |
bool |
False |
Add a tool to search previous sessions. |
enable_session_summaries |
bool |
False |
Generate session summaries at run end. |
See Sessions, State, and History.
Structured output
| Argument | Type | Default | Description |
|---|---|---|---|
input_schema |
Type[BaseModel] |
None |
Validate the run input against a Pydantic model. |
output_schema |
Type[BaseModel] | dict |
None |
Coerce the response into a Pydantic model / JSON schema. |
parse_response |
bool |
True |
Convert the model output into output_schema. |
structured_outputs |
bool |
None |
Use the provider's native structured-output mode. |
use_json_mode |
bool |
False |
Describe the schema in the prompt instead of native enforcement. |
parser_model |
Model |
None |
A secondary model that parses the primary model's output. |
See Structured Input and Output.
Reasoning
| Argument | Type | Default | Description |
|---|---|---|---|
reasoning |
bool |
False |
Enable step-by-step reasoning. |
reasoning_model |
Model |
None |
A dedicated model for the reasoning phase. |
reasoning_min_steps / reasoning_max_steps |
int |
1 / 10 |
Bounds on reasoning steps. |
See Reasoning.
Hooks and guardrails
| Argument | Type | Default | Description |
|---|---|---|---|
pre_hooks |
list[Callable | BaseGuardrail | BaseEval] |
None |
Run after the session loads, before processing. |
post_hooks |
list[Callable | BaseGuardrail | BaseEval] |
None |
Run after output is generated, before it returns. |
See Guardrails, Hooks, and Human-in-the-Loop.
Streaming and retries
| Argument | Type | Default | Description |
|---|---|---|---|
stream |
bool |
None |
Stream the response token-by-token. |
stream_events |
bool |
None |
Stream intermediate events (tool calls, reasoning steps). |
retries |
int |
0 |
Retry attempts on failure. |
delay_between_retries |
int |
1 |
Seconds between retries. |
exponential_backoff |
bool |
False |
Double the delay each retry. |
Telemetry and debug
| Argument | Type | Default | Description |
|---|---|---|---|
telemetry |
bool |
True |
Send minimal anonymous usage telemetry. Disable per-agent or globally with AGNO_TELEMETRY=false. |
debug_mode |
bool |
False |
Verbose debug logging. |
debug_level |
1 | 2 |
1 |
Debug verbosity. |
Caution
Telemetry is currently synchronous and can add latency to
agent.run(). If you need the lowest possible per-call latency, settelemetry=False(orAGNO_TELEMETRY=false). See Troubleshooting.
6. Models and Providers
Agno wraps every provider behind a common Model interface. Import the class for your provider and pass it as model=:
from agno.models.openai import OpenAIChat
from agno.models.anthropic import Claude
from agno.models.google import Gemini
agent = Agent(model=Claude(id="claude-sonnet-4-5"))
Provider class reference
| Provider | Import | Class(es) |
|---|---|---|
| OpenAI | agno.models.openai |
OpenAIChat, OpenAIResponses, OpenAILike |
| Anthropic | agno.models.anthropic |
Claude |
agno.models.google |
Gemini |
|
| Groq | agno.models.groq |
Groq |
| Mistral | agno.models.mistral |
MistralChat |
| Ollama (local) | agno.models.ollama |
Ollama, OllamaResponses |
| AWS Bedrock | agno.models.aws |
AwsBedrock, Claude |
| Azure | agno.models.azure |
AzureOpenAI, AzureAIFoundry |
| Cohere | agno.models.cohere |
Cohere |
| DeepSeek | agno.models.deepseek |
DeepSeek |
| xAI | agno.models.xai |
xAI |
| Vertex AI | agno.models.vertexai |
Claude |
Agno additionally ships providers for Cerebras, Cloudflare, Fireworks, Hugging Face, IBM watsonx, LiteLLM, LM Studio, llama.cpp, Meta, NVIDIA, Nebius, OpenRouter, Perplexity, Portkey, Requesty, SambaNova, Together, vLLM, and more — over 45 in total. Each lives under agno.models.<provider>.
The provider:id shorthand
Instead of importing a class, you can pass a model string. Agno resolves the provider and instantiates the right class:
agent = Agent(model="openai:gpt-4o")
agent = Agent(model="anthropic:claude-sonnet-4-5")
Warning
The string must be
"<provider>:<model_id>". A bare model name raises:ValueError: Invalid model string format: 'gpt-4o'. Model strings should be in format '<provider>:<model_id>' e.g. 'openai:gpt-4o'.
Fallback models
Provide alternates that are tried automatically when the primary model errors:
agent = Agent(
model=OpenAIChat(id="gpt-4o"),
fallback_models=["anthropic:claude-sonnet-4-5", "google:gemini-2.5-flash"],
)
7. Tools and Toolkits
Tools are functions the model can call. Agno ships ~130 pre-built toolkits and lets you write your own.
Using a built-in toolkit
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.tools.duckduckgo import DuckDuckGoTools
agent = Agent(
model=OpenAIChat(id="gpt-4o"),
tools=[DuckDuckGoTools()],
instructions="Search the web and cite your sources.",
)
agent.print_response("What happened in tech news today?", stream=True)
Toolkit catalog (selected)
| Category | Toolkits |
|---|---|
| Web search | DuckDuckGoTools, GoogleSearchTools, BraveSearchTools, ExaTools, TavilyTools, BaiduSearchTools, LinkupTools |
| Web scraping | Crawl4aiTools, FirecrawlTools, Newspaper4kTools, BrowserbaseTools, JinaReaderTools, TrafilaturaTools |
| Finance | YFinanceTools, FinancialDatasetsTools, OpenBBTools |
| Code & compute | PythonTools, DockerTools, E2BTools, DaytonaTools, DuckDbTools, CalculatorTools |
| Files & data | FileTools, CsvTools, LocalFileSystemTools, Neo4jTools, GoogleBigQueryTools |
| Productivity | GmailTools, GoogleCalendarTools, GoogleSheetsTools, NotionTools, TodoistTools, LinearTools, JiraTools |
| Communication | SlackTools, DiscordTools, EmailTools, WebexTools |
| Dev platforms | GithubTools, GitlabTools, BitbucketTools, ConfluenceTools |
| Media | DalleTools, ElevenLabsTools, FalTools, GiphyTools, LumaLabTools, MoviePyVideoTools, OpenCVTools |
| Knowledge/memory | KnowledgeTools, MemoryTools, Mem0Tools |
| Protocols | MCPTools (Model Context Protocol), McpToolboxTools |
Tip
Many toolkits expose an
all=Trueflag (e.g.YFinanceTools(all=True)) to enable every function, or accept granular flags to expose only what you need. Most require their extra: e.g.pip install "agno[github]"forGithubTools.
Writing a custom tool
Any plain Python function with type hints and a docstring becomes a tool:
from agno.agent import Agent
from agno.models.openai import OpenAIChat
def get_weather(city: str) -> str:
"""Return the current weather for a city.
Args:
city: The city name, e.g. "London".
"""
return f"It is 18°C and sunny in {city}."
agent = Agent(model=OpenAIChat(id="gpt-4o"), tools=[get_weather])
agent.print_response("What's the weather in Tokyo?")
The docstring becomes the tool description and the type hints define the JSON schema the model fills in.
Limiting and controlling tool use
agent = Agent(
model=OpenAIChat(id="gpt-4o"),
tools=[get_weather],
tool_call_limit=3, # at most 3 tool calls per run
tool_choice="auto", # let the model decide (default when tools present)
)
Model Context Protocol (MCP)
Connect to MCP servers to expose their tools to your agent:
pip install "agno[mcp]"
from agno.tools.mcp import MCPTools
agent = Agent(model=OpenAIChat(id="gpt-4o"), tools=[MCPTools(command="npx -y @modelcontextprotocol/server-filesystem /data")])
Caution
If MCP toolkit initialization fails, older versions could spin the CPU. Always wrap MCP setup in error handling and pin a recent Agno release (see Troubleshooting).
8. Knowledge and RAG
Knowledge gives an agent a searchable corpus. At run time the agent retrieves relevant chunks and grounds its answer in them (Retrieval-Augmented Generation).
The pipeline
Documents → Reader → Chunker → Embedder → Vector DB → (search at run time)
| Stage | Module | Examples |
|---|---|---|
| Reader | agno.knowledge.reader |
PDF, DOCX, PPTX, CSV, Markdown, text, web |
| Chunker | agno.knowledge.chunking |
fixed-size, semantic, code-aware (via chonkie) |
| Embedder | agno.knowledge.embedder |
OpenAI, Google, Cohere, Hugging Face, FastEmbed, Jina, Fireworks, Azure |
| Reranker | agno.knowledge.reranker |
improve retrieval ordering |
| Vector DB | agno.vectordb |
see below |
Vector database support
PgVector, ChromaDb, LanceDb, Qdrant, Milvus, Weaviate, MongoDb, Pinecone, Couchbase, Cassandra, Clickhouse, SingleStore, SurrealDb, UpstashDb, Redis, plus LangChain and LlamaIndex adapters.
Example: PDF knowledge with pgvector
pip install "agno[pdf,pgvector,openai]"
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.knowledge.knowledge import Knowledge
from agno.vectordb.pgvector import PgVector
knowledge = Knowledge(
vector_db=PgVector(
table_name="docs",
db_url="postgresql+psycopg://ai:ai@localhost:5532/ai",
),
)
# Load content (run once)
knowledge.add_content(path="./handbook.pdf")
agent = Agent(
model=OpenAIChat(id="gpt-4o"),
knowledge=knowledge,
search_knowledge=True, # agentic RAG: the agent searches when needed
instructions="Answer using the handbook. Cite the relevant section.",
)
agent.print_response("What is our refund policy?", stream=True)
Note
With
search_knowledge=True(the default whenknowledgeis set), the agent gets a search tool and decides when to query — this is Agentic RAG. Setadd_knowledge_to_context=Trueinstead to always inject retrieved chunks into every prompt.
Knowledge filters
Restrict searches by document metadata:
agent = Agent(
model=OpenAIChat(id="gpt-4o"),
knowledge=knowledge,
knowledge_filters={"department": "finance"},
)
Set enable_agentic_knowledge_filters=True to let the agent choose filters dynamically.
9. Memory
Memory captures durable facts about a user — preferences, history, context — and recalls them in future sessions. Unlike session_state (scoped to one conversation), memories persist across sessions for a user_id.
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.db.sqlite import SqliteDb
agent = Agent(
model=OpenAIChat(id="gpt-4o"),
db=SqliteDb(db_file="agent.db"),
user_id="user_123",
enable_agentic_memory=True, # the agent manages memories with tools
add_memories_to_context=True, # recall them in the prompt
)
agent.print_response("Remember that I'm vegetarian and allergic to peanuts.")
# ... later, in a new session ...
agent.print_response("Suggest a dinner recipe.") # respects dietary facts
| Mode | Argument | Behaviour |
|---|---|---|
| Agentic | enable_agentic_memory=True |
The agent decides what to remember via tools. |
| Automatic | update_memory_on_run=True |
Memories are extracted at the end of every run. |
| Recall | add_memories_to_context=True |
Stored memories are injected into the prompt. |
Important
Memory requires a
db. Without one, there is nowhere to persist memories between sessions.
10. Sessions, State, and History
Sessions
A session is one conversation thread, identified by session_id and persisted in a db. Reuse a session_id to continue a conversation:
from agno.db.sqlite import SqliteDb
agent = Agent(
model=OpenAIChat(id="gpt-4o"),
db=SqliteDb(db_file="agent.db"),
session_id="chat_42",
add_history_to_context=True,
num_history_runs=5,
)
agent.print_response("My name is Sam.")
agent.print_response("What's my name?") # "Sam" — history is in context
Session state
session_state is a mutable dict persisted with the session. Use it for counters, preferences, or scratch data:
agent = Agent(
model=OpenAIChat(id="gpt-4o"),
db=SqliteDb(db_file="agent.db"),
session_state={"cart": []},
add_session_state_to_context=True,
enable_agentic_state=True, # let the agent mutate the state via tools
)
| Argument | Effect |
|---|---|
session_state |
Initial state dict. |
add_session_state_to_context |
Include state in the prompt. |
enable_agentic_state |
Give the agent tools to update state. |
overwrite_db_session_state |
Replace stored state instead of merging (default merges). |
History controls
| Argument | Effect |
|---|---|
add_history_to_context |
Include prior messages. |
num_history_runs |
Number of past runs to include. |
num_history_messages |
Number of past messages to include. |
search_past_sessions |
Add a tool to search older sessions. |
enable_session_summaries |
Summarize sessions for compact recall. |
11. Structured Input and Output
Typed output
Pass a Pydantic model as output_schema to get validated structured data instead of free text:
from pydantic import BaseModel
from agno.agent import Agent
from agno.models.openai import OpenAIChat
class StockAnalysis(BaseModel):
ticker: str
sentiment: str
target_price: float
agent = Agent(model=OpenAIChat(id="gpt-4o"), output_schema=StockAnalysis)
result = agent.run("Analyze NVDA")
analysis = result.content # a StockAnalysis instance
print(analysis.ticker, analysis.target_price)
| Argument | Effect |
|---|---|
output_schema |
Pydantic model / JSON schema to coerce output into. |
structured_outputs |
Use the provider's native structured-output enforcement (e.g. OpenAI). |
use_json_mode |
Describe the schema in the prompt instead of native enforcement (for providers without it). |
parser_model |
A second model that parses the primary output into the schema. |
Typed input
Validate inputs before the run with input_schema:
class AnalysisRequest(BaseModel):
ticker: str
horizon_days: int
agent = Agent(model=OpenAIChat(id="gpt-4o"), input_schema=AnalysisRequest)
agent.run(AnalysisRequest(ticker="AAPL", horizon_days=30))
Warning
When
input_schemais set, input is required and validated. Passing a mismatched type raisesCannot validate <type> against input_schema. Expected dict or <Model> instance.
12. Reasoning
Enable explicit step-by-step reasoning to improve accuracy on hard problems:
agent = Agent(
model=OpenAIChat(id="gpt-4o"),
reasoning=True,
reasoning_min_steps=2,
reasoning_max_steps=8,
)
agent.print_response("If a train leaves at 3pm going 60mph...", stream=True)
You can dedicate a separate model to the reasoning phase (often a stronger or cheaper model):
agent = Agent(
model=OpenAIChat(id="gpt-4o"),
reasoning_model=Claude(id="claude-sonnet-4-5"),
reasoning=True,
)
13. Guardrails, Hooks, and Human-in-the-Loop
Pre and post hooks
Hooks run custom logic around the agent's processing. Use them for validation, logging, redaction, or evaluation:
def redact_pii(run_input, **kwargs):
# mutate or inspect the input before processing
...
agent = Agent(
model=OpenAIChat(id="gpt-4o"),
pre_hooks=[redact_pii],
)
pre_hooks run after the session loads but before the model is called; post_hooks run after output is generated but before it is returned. Hooks may be plain callables, BaseGuardrail subclasses, or BaseEval evaluators.
Guardrails
Subclass BaseGuardrail to enforce policies (e.g. block spam or off-topic requests):
from agno.guardrails import BaseGuardrail
class SpamGuardrail(BaseGuardrail):
def check(self, run_input, **kwargs):
if "buy now" in str(run_input).lower():
raise ValueError("Spam detected")
agent = Agent(model=OpenAIChat(id="gpt-4o"), pre_hooks=[SpamGuardrail()])
Human-in-the-loop and approvals
Agno can pause a run to wait for human confirmation (for example, before a destructive tool call), then resume with continue_run(). This pattern powers approval gates in AgentOS, where the /approvals API surfaces pending actions. See the Admin Guide for the server-side approval workflow.
14. Multi-Agent Teams
A Team has a leader and a list of members (agents or nested teams). The leader coordinates the members according to the team's mode.
from agno.agent import Agent
from agno.team import Team
from agno.models.openai import OpenAIChat
researcher = Agent(name="Researcher", role="Finds facts", model=OpenAIChat(id="gpt-4o"),
tools=[DuckDuckGoTools()])
writer = Agent(name="Writer", role="Writes prose", model=OpenAIChat(id="gpt-4o"))
team = Team(
name="Content Team",
members=[researcher, writer],
model=OpenAIChat(id="gpt-4o"),
instructions="Research the topic, then write a short article.",
)
team.print_response("Write about the James Webb Space Telescope.", stream=True)
Team modes
| Mode | Behaviour |
|---|---|
coordinate (default) |
The leader picks members, crafts subtasks, and synthesizes their responses into a final answer. |
route |
The leader routes the request to the single best specialist and returns that member's response directly. |
broadcast |
The leader sends the same task to all members simultaneously. |
tasks |
Autonomous loop: the leader decomposes the goal into a shared task list, delegates, and iterates until done (bounded by max_iterations). |
from agno.team import Team
team = Team(members=[...], mode="route") # or "coordinate", "broadcast", "tasks"
Useful Team arguments
| Argument | Default | Description |
|---|---|---|
members |
required | List of agents / nested teams. |
mode |
coordinate |
Execution mode (above). |
respond_directly |
False |
Leader returns member output without re-processing. |
delegate_to_all_members |
False |
Delegate to every member instead of a subset. |
add_team_history_to_members |
False |
Share team-level history with members. |
share_member_interactions |
False |
Let members see each other's request/response. |
max_iterations |
10 |
Loop bound for tasks mode. |
Teams accept most of the same memory, knowledge, session, and db arguments as agents.
Note
In
coordinatemode with persistence, ensure yourdbis configured so member sessions survive process restarts; otherwise resuming a paused team run may fail to find a member's prior session.
15. Workflows
Workflows give you deterministic orchestration: explicit control flow over agents, teams, and functions. Unlike a team (where the LLM leader decides routing), a workflow's structure is code you define.
Building blocks
| Primitive | Import | Purpose |
|---|---|---|
Workflow |
from agno.workflow import Workflow |
The container. |
Step |
from agno.workflow import Step |
A single unit (runs an agent, team, or function). |
Steps |
from agno.workflow import Steps |
A named sequence of steps. |
Loop |
from agno.workflow import Loop |
Repeat steps until a condition holds. |
Parallel |
from agno.workflow import Parallel |
Run steps concurrently and fan-in. |
Condition |
from agno.workflow import Condition |
Run steps only if a predicate is true. |
Router |
from agno.workflow import Router |
Pick a branch dynamically. |
Sequential workflow example
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.workflow import Workflow, Step
researcher = Agent(name="Researcher", model=OpenAIChat(id="gpt-4o"), tools=[DuckDuckGoTools()])
writer = Agent(name="Writer", model=OpenAIChat(id="gpt-4o"))
workflow = Workflow(
name="Article Pipeline",
steps=[
Step(name="research", agent=researcher),
Step(name="write", agent=writer),
],
)
workflow.print_response("Write an article about black holes.", stream=True)
Each step receives a StepInput (the prior step's output plus shared context) and returns a StepOutput. You can mix agents, teams, and plain functions as step executors.
Parallel and conditional flow
from agno.workflow import Workflow, Step, Parallel, Condition
workflow = Workflow(
name="Multi-source research",
steps=[
Parallel(
Step(name="web", agent=web_agent),
Step(name="news", agent=news_agent),
),
Step(name="synthesize", agent=writer),
],
)
CEL expressions
Conditions and routers can use CEL expressions for declarative logic (pip install "agno[cel]"). Validate them with validate_cel_expression().
Tip
Use a Team when you want the model to decide how to delegate; use a Workflow when you need a repeatable, auditable pipeline with explicit branches, loops, and parallelism.
16. Running as a Service: AgentOS
AgentOS turns your agents into a production FastAPI application — 50+ REST endpoints with SSE and WebSocket streaming, plus optional auth, tracing, scheduling, and chat interfaces.
pip install "agno[os]"
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.db.sqlite import SqliteDb
from agno.os import AgentOS
agent = Agent(
name="Assistant",
model=OpenAIChat(id="gpt-4o"),
db=SqliteDb(db_file="agentos.db"),
)
agent_os = AgentOS(agents=[agent])
app = agent_os.get_app() # a FastAPI app
# Run with: uvicorn main:app --reload --port 7777
uvicorn main:app --port 7777
Visit http://localhost:7777/docs for the interactive OpenAPI explorer.
What AgentOS exposes
| Domain | Endpoints (prefix) | Purpose |
|---|---|---|
| Agents / Teams / Workflows | /agents, /teams, /workflows |
Run and manage your components. |
| Sessions | /sessions |
List and inspect conversations. |
| Memory | /memory |
User memories. |
| Knowledge | /knowledge |
Manage knowledge bases. |
| Metrics / Traces | /metrics, /traces |
Observability data. |
| Evals | /evals |
Evaluation runs. |
| Schedules | /schedules |
Cron jobs. |
| Approvals | /approvals |
Human-in-the-loop gates. |
| Registry | /registry |
Discover registered components. |
| Health | /health |
Liveness. |
Key AgentOS options
| Argument | Default | Purpose |
|---|---|---|
agents / teams / workflows / knowledge |
None |
What to serve (at least one, or a db, is required). |
db |
None |
Default database for components without their own. |
authorization |
False |
Enable JWT-based RBAC. |
interfaces |
[] |
Chat interfaces (Slack, Telegram, WhatsApp, AG-UI, A2A). |
tracing |
False |
Enable OpenTelemetry tracing. |
scheduler |
False |
Enable the cron scheduler. |
enable_mcp_server |
False |
Expose the OS itself as an MCP server. |
a2a_interface |
False |
Expose agents over the A2A protocol. |
cors_allowed_origins |
None |
Additional CORS origins. |
config |
None |
Path to a YAML config or an AgentOSConfig. |
Chat interfaces
Expose an agent through a messaging platform:
from agno.os.interfaces.slack import Slack
agent_os = AgentOS(
agents=[agent],
interfaces=[Slack(agent=agent)],
)
Available interfaces: Slack, Telegram, WhatsApp, AG-UI, A2A.
Important
AgentOS persistence, auth, scheduling, and deployment are covered in depth in the Admin Guide. This section is the user-facing overview.
17. Deploying with the ag CLI
The separate agno-infra package provides the ag (alias agno) command-line tool for scaffolding and deploying AgentOS projects to Docker and AWS.
pip install "agno-infra" # or: pip install "agno[infra]"
Commands
All deployment commands live under ag infra:
| Command | Purpose |
|---|---|
ag infra create |
Create a new AgentOS codebase from a starter template. |
ag infra up |
Create/start the infrastructure resources (containers, AWS resources). |
ag infra down |
Stop and remove resources. |
ag infra patch |
Update running resources. |
ag infra restart |
Restart resources. |
ag infra config |
Show the active infrastructure config. |
ag infra delete |
Delete an infrastructure configuration. |
ag infra create --name my-agentos
cd my-agentos
ag infra up
Note
agno-infratargets Docker and AWS (ECS, load balancers, RDS, S3, and more). Because Agno deploys as a container, you can also run it on any platform that runs containers — Railway, GCP, Fly, etc. See the Admin Guide for deployment architecture.
18. Common Recipes
A research agent with web search and citations
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.tools.exa import ExaTools
agent = Agent(
model=OpenAIChat(id="gpt-4o"),
tools=[ExaTools()],
instructions=["Always cite sources with URLs.", "Be concise."],
add_datetime_to_context=True,
markdown=True,
)
agent.print_response("Summarize recent advances in battery technology.", stream=True)
A persistent chat assistant
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.db.sqlite import SqliteDb
agent = Agent(
model=OpenAIChat(id="gpt-4o"),
db=SqliteDb(db_file="chat.db"),
session_id="user-sam",
add_history_to_context=True,
enable_user_memories=True,
markdown=True,
)
agent.cli_app() # interactive REPL
A structured data extractor
from pydantic import BaseModel
from agno.agent import Agent
from agno.models.openai import OpenAIChat
class Invoice(BaseModel):
vendor: str
total: float
due_date: str
agent = Agent(model=OpenAIChat(id="gpt-4o"), output_schema=Invoice)
invoice = agent.run("Vendor: Acme, $1,250 due 2026-07-01").content
A multi-agent team served over HTTP
from agno.os import AgentOS
agent_os = AgentOS(teams=[content_team])
app = agent_os.get_app()
# uvicorn main:app --port 7777
19. Troubleshooting
Error: Invalid model string format: 'gpt-4o'
Cause: A model passed as a string must be "<provider>:<model_id>".
Solution: Use "openai:gpt-4o", or pass a model object: OpenAIChat(id="gpt-4o").
Prevention: Prefer model objects in code; reserve strings for config files.
Error: Model provider '<x>' is not supported.
Cause: The provider prefix in your model string isn't recognized. Solution: Check the provider name against the provider reference; install the corresponding extra.
Error: '<package>' not installed. Please install using 'pip install agno[<extra>]'
Cause: You used a tool, model, or backend whose optional dependency isn't installed (e.g. mistralai, PyJWT, filetype).
Solution: Install the named extra, e.g. pip install "agno[mistral]" or pip install "agno[os]".
Prevention: Install the extras for every provider/tool/db you use up front.
Error: Either agents, teams, workflows, knowledge bases or a database must be provided.
Cause: AgentOS(...) was constructed with nothing to serve.
Solution: Pass at least one of agents=, teams=, workflows=, knowledge=, or db=.
Error: Instructions function is async, use 'agent.arun()' instead
Cause: You used an async callable for instructions / system_message / a tool, then called the sync run().
Solution: Use await agent.arun(...) / await agent.aprint_response(...).
Error: At least one JWT verification key or JWKS file is required when validate=True
Cause: JWT auth is enabled in AgentOS but no verification key is configured.
Solution: Set JWT_VERIFICATION_KEY or JWT_JWKS_FILE (env vars), or pass verification_keys / jwks_file. See the Admin Guide.
Error: Input required when input_schema is set
Cause: input_schema is configured but no input was passed to run().
Solution: Provide an input matching the schema (a dict or a model instance).
High latency on every agent.run()
Cause: Telemetry currently runs synchronously and can add ~1s per call.
Solution: Set telemetry=False on the agent, or globally: export AGNO_TELEMETRY=false.
CPU spins to 100% after MCP setup fails
Cause: A failed MCP toolkit initialization could corrupt the cancel scope in older releases.
Solution: Upgrade to the latest Agno; wrap MCPTools(...) setup in try/except and ensure servers are reachable before connecting.
Knowledge base isn't searched
Cause: With a pre-supplied messages array (rather than a single input), the knowledge search tool may not be triggered automatically.
Solution: Pass a natural-language query as input, ensure search_knowledge=True, or set add_knowledge_to_context=True to always inject references.
Multi-turn conversation breaks
Cause: Some patch releases have regressed multi-turn handling.
Solution: Pin a known-good version, confirm db + add_history_to_context=True are set, and reuse the same session_id across turns.
20. Frequently Asked Questions
Q: Is Agno a hosted service or a library? A library/SDK you run yourself. There is a companion control-plane UI and managed offering, but the framework runs entirely in your own infrastructure.
Q: Do I need an API key?
You need credentials for whichever model provider you use (e.g. OPENAI_API_KEY). Agno itself doesn't require an account to run agents locally.
Q: How is a Team different from a Workflow? A Team lets the LLM leader decide how to delegate (dynamic). A Workflow is deterministic code-defined control flow (sequences, loops, branches, parallelism). Use teams for open-ended delegation, workflows for repeatable pipelines.
Q: Can I switch model providers without rewriting my agent?
Yes. Swap the model= argument (or the "provider:id" string). The rest of the agent definition is provider-agnostic.
Q: Where is conversation history stored?
In the db you attach to the agent (SQLite, PostgreSQL, MySQL, MongoDB, Redis, DynamoDB, and more). Without a db, runs are stateless.
Q: What's the difference between session state and memory?
session_state is scoped to one conversation; memory holds durable facts about a user_id recalled across sessions.
Q: How do I disable telemetry?
Set telemetry=False on the agent/AgentOS, or export AGNO_TELEMETRY=false.
Q: Can agents call my own functions?
Yes — any typed, docstringed Python function passed in tools= becomes a callable tool.
Q: Does Agno support local models? Yes, via Ollama, LM Studio, llama.cpp, and vLLM providers.
Q: How do I serve agents over HTTP?
Wrap them in AgentOS(...) and run the returned FastAPI app with uvicorn. See Running as a Service.
Q: How do I add streaming?
Pass stream=True to run() / print_response(). For intermediate events (tool calls, reasoning), add stream_events=True.
Q: Can I structure agent output as JSON?
Yes — set output_schema to a Pydantic model. The result's .content will be a validated instance.
Q: Which Python versions are supported? 3.7+ per the package metadata; 3.10+ is recommended for the best typing experience.
21. Reference
Import map (public API)
| You want | Import |
|---|---|
| An agent | from agno.agent import Agent |
| A team | from agno.team import Team, TeamMode, Task |
| A workflow | from agno.workflow import Workflow, Step, Steps, Loop, Parallel, Condition, Router |
| A model | from agno.models.<provider> import <Class> |
| A toolkit | from agno.tools.<name> import <Toolkit> |
| A vector DB | from agno.vectordb.<name> import <Class> |
| A database | from agno.db.<backend> import <Class> |
| Knowledge | from agno.knowledge.knowledge import Knowledge |
| The server | from agno.os import AgentOS |
Note
Agno's top-level
agnopackage exposes onlyagno.__version__. Public classes are imported from their submodules as shown above.
Common environment variables
| Variable | Effect |
|---|---|
AGNO_TELEMETRY |
Set to false to disable usage telemetry. |
OPENAI_API_KEY / ANTHROPIC_API_KEY / GOOGLE_API_KEY / … |
Provider credentials. |
JWT_VERIFICATION_KEY / JWT_JWKS_FILE |
AgentOS JWT auth (see Admin Guide). |
Team modes
| Mode | Summary |
|---|---|
coordinate |
Leader delegates subtasks and synthesizes (default). |
route |
Leader routes to one specialist, returns its answer. |
broadcast |
Leader sends the same task to all members. |
tasks |
Autonomous task-list loop until complete. |
Agent run methods
| Method | Sync/Async | Returns |
|---|---|---|
run / arun |
sync / async | RunOutput |
print_response / aprint_response |
sync / async | — (prints) |
cli_app |
sync | — (REPL) |
continue_run |
sync | RunOutput |
Further reading
- Admin Guide — architecture, the monorepo layout, AgentOS deployment, JWT/RBAC, OpenTelemetry, scheduling, storage backends, security hardening, and the complete configuration reference.
- Official docs:
https://docs.agno.com