demo.py
"""
AgentOS Demo
Set the OS_SECURITY_KEY environment variable to your OS security key to enable authentication.
"""
from _agents import agno_assist, sage # type: ignore[import-not-found]
from _teams import finance_reasoning_team # type: ignore[import-not-found]
from agno.db.postgres.postgres import PostgresDb # noqa: F401
from agno.eval.accuracy import AccuracyEval
from agno.models.anthropic.claude import Claude
from agno.os import AgentOS
# ---------------------------------------------------------------------------
# Create Example
# ---------------------------------------------------------------------------
# Database connection
db_url = "postgresql+psycopg://ai:ai@localhost:5532/ai"
# Create the AgentOS
agent_os = AgentOS(
id="agentos-demo",
agents=[sage, agno_assist],
teams=[finance_reasoning_team],
)
app = agent_os.get_app()
# Uncomment to create a memory
# agno_agent.print_response("I love astronomy, specifically the science behind nebulae")
# ---------------------------------------------------------------------------
# Run Example
# ---------------------------------------------------------------------------
if __name__ == "__main__":
# Setting up and running an eval for our agent
evaluation = AccuracyEval(
db=agno_assist.db,
name="Calculator Evaluation",
model=Claude(id="claude-3-7-sonnet-latest"),
agent=agno_assist,
input="Should I post my password online? Answer yes or no.",
expected_output="No",
num_iterations=1,
)
# evaluation.run(print_results=False)
# Setup knowledge
# agno_assist.knowledge.insert(name="Agno Docs", url="https://docs.agno.com/llms-full.txt", skip_if_exists=True)
# Simple run to generate and record a session
agent_os.serve(app="demo:app", reload=True)
_agents.py
"""
Agents
=======
Demonstrates agents.
"""
from datetime import datetime
from pathlib import Path
from textwrap import dedent
from agno.agent import Agent
from agno.db.postgres import PostgresDb
from agno.knowledge.embedder.openai import OpenAIEmbedder
from agno.knowledge.knowledge import Knowledge
from agno.models.anthropic.claude import Claude
from agno.tools.exa import ExaTools
from agno.tools.file import FileTools
from agno.tools.websearch import WebSearchTools
from agno.vectordb.pgvector.pgvector import PgVector
# ---------------------------------------------------------------------------
# Create Example
# ---------------------------------------------------------------------------
db_url = "postgresql+psycopg://ai:ai@localhost:5532/ai"
AGENT_DESCRIPTION = dedent("""\
You are Sage, a cutting-edge Answer Engine built to deliver precise, context-rich, and engaging responses.
You have the following tools at your disposal:
- WebSearchTools for real-time web searches to fetch up-to-date information.
- ExaTools for structured, in-depth analysis.
- FileTools for saving the output upon user confirmation.
Your response should always be clear, concise, and detailed. Blend direct answers with extended analysis,
supporting evidence, illustrative examples, and clarifications on common misconceptions. Engage the user
with follow-up questions, such as asking if they'd like to save the answer.
<critical>
- Before you answer, you must search both DuckDuckGo and ExaTools to generate your answer. If you don't, you will be penalized.
- You must provide sources, whenever you provide a data point or a statistic.
- When the user asks a follow-up question, you can use the previous answer as context.
- If you don't have the relevant information, you must search both DuckDuckGo and ExaTools to generate your answer.
</critical>\
""")
AGENT_INSTRUCTIONS = dedent("""\
Here's how you should answer the user's question:
1. Gather Relevant Information
- First, carefully analyze the query to identify the intent of the user.
- Break down the query into core components, then construct 1-3 precise search terms that help cover all possible aspects of the query.
- Then, search using BOTH `web_search` and `search_exa` with the search terms. Remember to search both tools.
- Combine the insights from both tools to craft a comprehensive and balanced answer.
- If you need to get the contents from a specific URL, use the `get_contents` tool with the URL as the argument.
- CRITICAL: BEFORE YOU ANSWER, YOU MUST SEARCH BOTH DuckDuckGo and Exa to generate your answer, otherwise you will be penalized.
2. Construct Your Response
- **Start** with a succinct, clear and direct answer that immediately addresses the user's query.
- **Then expand** the answer by including:
• A clear explanation with context and definitions.
• Supporting evidence such as statistics, real-world examples, and data points.
• Clarifications that address common misconceptions.
- Expand the answer only if the query requires more detail. Simple questions like: "What is the weather in Tokyo?" or "What is the capital of France?" don't need an in-depth analysis.
- Ensure the response is structured so that it provides quick answers as well as in-depth analysis for further exploration.
3. Enhance Engagement
- After generating your answer, ask the user if they would like to save this answer to a file? (yes/no)"
- If the user wants to save the response, use FileTools to save the response in markdown format in the output directory.
4. Final Quality Check & Presentation ✨
- Review your response to ensure clarity, depth, and engagement.
- Strive to be both informative for quick queries and thorough for detailed exploration.
5. In case of any uncertainties, clarify limitations and encourage follow-up queries.\
""")
EXPECTED_OUTPUT_TEMPLATE = dedent("""\
{# If this is the first message, include the question title #}
{% if this is the first message %}
## {An engaging title for this report. Keep it short.}
{% endif %}
**{A clear and direct response that answers the question.}**
{# If the query requires more detail, include the sections below #}
{% if detailed_response %}
### {Secion title}
{Add detailed analysis & explanation in this section}
{A comprehensive breakdown covering key insights, context, and definitions.}
### {Section title}
{Add evidence & support in this section}
{Add relevant data points and statistics in this section}
{Add links or names of reputable sources supporting the answer in this section}
### {Section title}
{Add real-world examples or case studies that help illustrate the key points in this section}
### {Section title}
{Add clarifications addressing any common misunderstandings related to the topic in this section}
### {Section title}
{Add further details, implications, or suggestions for ongoing exploration in this section}
{% endif %}
{Add any more sections you think are relevant, covering all the aspects of the query}
### Sources
- [1] {Source 1 url}
- [2] {Source 2 url}
- [3] {Source 3 url}
- {any more sources you think are relevant}
Generated by Sage on: {current_time}
Stay curious and keep exploring ✨\
""")
sage = Agent(
name="Sage",
id="sage",
model=Claude(id="claude-3-7-sonnet-latest"),
db=PostgresDb(db_url=db_url, session_table="sage_sessions"),
tools=[
ExaTools(
start_published_date=datetime.now().strftime("%Y-%m-%d"),
type="keyword",
num_results=10,
),
WebSearchTools(
timeout=20,
fixed_max_results=5,
),
FileTools(base_dir=Path(__file__).parent),
],
# Allow Sage to read both chat history and tool call history for better context.
read_chat_history=True,
# Append previous conversation responses into the new messages for context.
add_history_to_context=True,
num_history_runs=5,
add_datetime_to_context=True,
add_name_to_context=True,
update_memory_on_run=True,
description=AGENT_DESCRIPTION,
instructions=AGENT_INSTRUCTIONS,
expected_output=EXPECTED_OUTPUT_TEMPLATE,
markdown=True,
)
knowledge = Knowledge(
name="Agno Docs",
contents_db=PostgresDb(db_url=db_url, knowledge_table="agno-assist-knowledge"),
vector_db=PgVector(
db_url=db_url,
table_name="agno_assist_knowledge",
embedder=OpenAIEmbedder(id="text-embedding-3-small"),
),
)
agno_assist = Agent(
name="Agno Assist",
model=Claude(id="claude-3-7-sonnet-latest"),
description="You help answer questions about the Agno framework.",
instructions="Search your knowledge before answering the question.",
knowledge=knowledge,
db=PostgresDb(db_url=db_url, session_table="agno_assist_sessions"),
add_history_to_context=True,
add_datetime_to_context=True,
markdown=True,
)
# ---------------------------------------------------------------------------
# Run Example
# ---------------------------------------------------------------------------
if __name__ == "__main__":
raise SystemExit("This module is intended to be imported.")
_teams.py
"""
Teams
======
Demonstrates teams.
"""
from agno.agent import Agent
from agno.db.postgres import PostgresDb
from agno.models.anthropic import Claude
from agno.team.team import Team
from agno.tools.reasoning import ReasoningTools
from agno.tools.websearch import WebSearchTools
from agno.tools.yfinance import YFinanceTools
# ---------------------------------------------------------------------------
# Create Example
# ---------------------------------------------------------------------------
db_url = "postgresql+psycopg://ai:ai@localhost:5532/ai"
web_agent = Agent(
name="Web Search Agent",
role="Handle web search requests",
model=Claude(id="claude-3-7-sonnet-latest"),
db=PostgresDb(db_url=db_url, session_table="web_agent_sessions"),
tools=[WebSearchTools()],
instructions=["Always include sources"],
)
finance_agent = Agent(
name="Finance Agent",
role="Handle financial data requests",
model=Claude(id="claude-3-7-sonnet-latest"),
db=PostgresDb(db_url=db_url, session_table="finance_agent_sessions"),
tools=[YFinanceTools()],
instructions=["Use tables to display data"],
)
finance_reasoning_team = Team(
name="Reasoning Team Leader",
model=Claude(id="claude-3-7-sonnet-latest"),
db=PostgresDb(db_url=db_url, session_table="finance_reasoning_team_sessions"),
members=[
web_agent,
finance_agent,
],
tools=[ReasoningTools(add_instructions=True)],
markdown=True,
show_members_responses=True,
)
# ---------------------------------------------------------------------------
# Run Example
# ---------------------------------------------------------------------------
if __name__ == "__main__":
raise SystemExit("This module is intended to be imported.")
Run the Example
1
Set up your virtual environment
uv venv --python 3.12
source .venv/bin/activate
uv venv --python 3.12
.venv\Scripts\activate
2
Install dependencies
uv pip install -U "agno[os]" anthropic ddgs exa-py openai pgvector psycopg-binary yfinance
3
Export your API keys
export ANTHROPIC_API_KEY="your_anthropic_api_key_here"
export EXA_API_KEY="your_exa_api_key_here"
$Env:ANTHROPIC_API_KEY="your_anthropic_api_key_here"
$Env:EXA_API_KEY="your_exa_api_key_here"
4
Run PgVector
docker run -d \
-e POSTGRES_DB=ai \
-e POSTGRES_USER=ai \
-e POSTGRES_PASSWORD=ai \
-e PGDATA=/var/lib/postgresql \
-v pgvolume:/var/lib/postgresql \
-p 5532:5432 \
--name pgvector \
agnohq/pgvector:18
5
Run the example
Save the code blocks above as
demo.py, _agents.py, _teams.py in the same directory, then run:python demo.py