Agno: multi-agent system framework

2한나·2025년 9월 21일

Agno란?

Agno는 memory, knowledge, reasoning을 갖춘 멀티 에이전트 시스템을 구축하기 위한 full stack framework

Agno를 사용하면 5단계 agent system을 만들 수 있다.

level 1: tool과 instruction을 가진 Agent

  • 간단한 tool 호출 에이전트
  • 특징: 단일 에이전트, 주어진 도구와 지침만 사용
  • ex) 주식 가격 질문
    YFinance API(도구)를 사용해 “주가를 가져와 표로 정리하라”라는 지침을 따라 동작

level 2: knowlege와 storage를 가진 Agent

  • 문서 기반 Q&A 에이전트
  • 특징: RAG(지식 베이스)와 저장소 활용
  • ex) 회사 메뉴얼 질문
    사전에 저장된 사내 문서에서 검색 → 답변 생성

level 3: memory와 reasoning을 가진 Agent

  • 특징: 특정 과거/행동 기억 + 추론 능력
  • ex) 지난주에 추천해준 주식에 대한 질문
    → Agent는 저장된 지난 대화를 꺼냄
    → Reasoning을 통해 대회 히스토리를 이해하고 추론함

level 4: reason하고 collaborate하는 Agent Team

  • 여러 Agent가 협력
  • ex) 팀 구성
    • 웹검색 Agent: 최신 뉴스 수집

    • 재무 Agent: 주가 데이터 분석

    • 리포트 Agent: 내용을 종합해 문서 작성

      웹 뉴스 + 주식 데이터 + 분석을 합친 완성된 보고서 출력

level 5: state와 determinism을 가진 Agent Workflows

  • 상태를 유지하며 deterministic한 workflow 실행
  • ex) 보험 클레임 처리 워크플로
    1. 사용자가 신고 접수 → 상태 저장 (step1)

    2. 사진 증거 검증 에이전트 실행 (step2)

    3. 규정과 대조해 보상 금액 산정 (step3)

    4. 최종 승인 및 결과 통보 (step4)

      이 모든 과정이 정해진 순서와 조건에 따라 재현 가능하게 실행


왜 Agno인가?

주요 특징

1. Model Agnostic

  • OpenAI, Anthropic, Google, Mistral, Llama 계열 등 다양한 모델 제공자를 하나의 인터페이스로 지원

2. Highly performant

  • 에이전트 생성 속도 약 3μs, 평균 메모리 사용량 약 6.5KB.
    → 에이전트 생성/관리 overhead를 최소화해 대량 동시 에이전트 워크플로에서 유리

3. Reasoning 우선 설계

추론을 구현하기 위해 세 가지 방법 지원

  1. Reasoning Models: Anthropic Claude 같은 추론 특화 모델을 사용해 단계적 사고/계획/검증을 모델 레벨에서 수행
    • 복잡한 추론이 필요할때, 별도 도구 없이도 계획→실행→검토의 품질을 높이고 싶을 때 사용
  2. Reasoning Tools: Agno에서 제공하는 ReasoningTools를 붙여, 모델이 중간 사고 단계를 더 체계적으로 밟도록 유도
    • 일반 모델(OpenAI 등)을 쓰되, 생각의 특(계획→실행→검토→보고)를 강제하고 싶을 때 사용
  3. Chain-of-Thought(CoT) 커스텀 방식: Agno가 자체적으로 구현한 chain of thought 패턴으로, 모델이 내부 스크래치패드에서 단계별로 사고하되 최종 결과만 외부로 노출함
    • 일관된 포맷(ex JSON 보고서)로만 출력해야 할 때 사용

4. Native Multimodal

  • 입출력에 test/image/audio/video와 같은 다양한 모달을 붙일 수 있음

5. 고급 Multi-Agent 아키텍처

  • 역할이 다른 여러 에이전트를 협업시켜 복잡도를 분산시킴 (검색/분석/평가/리포팅 등)
  • 단일 에이전트가 다루기엔 tool/context가 과도할 경우 분할
  • 실행 중 실시간 검색 가능
  • 20개 이상의 vector DB와 연동 (ChromaDB, MongoDB, PgVector(Postgres), Qdrant 등)
  • 최신 문서/내부 데이터 기반의 정확한 답변 필요시 사용 가능

7. Built-in Memory & Session Storage

사용자별 대회 맥락/선호/이전 결론을 저장해 다음 대화에 반영

  • Built-in Memory (기본 메모리): 에이전트가 현재 실행 사이클 동안의 대화/메시지 히스토리를 들고 있는 휘발성 메모리. 스크립트가 끝나거나 요청이 종료되면 사라짐
  • Session Storage: 위 Built-in Memory와 session state를 DB나 file에 영구 저장해 다음 요청에서도 같은 session을 이어서 대화할 수 있게 해줌
    • 저장소 드라이버는 지정할 수 있음
    • 지원되는 storage driver: SQLite, PostgreSQL, Redis, MongoDB, DynamoDB, SingleStore, In-Memory, YAML, JSON 등

8. Structured Outputs

JSON 형태 등 구조화된 결과 반환 가능

  1. 모델의 Structured Outputs 기능 그대로 사용
    • OpenAI, Claude와 같이 structured ouput을 지원하는 모델에서는 response_model={PydanticModel} 을 지정하면 됨
  2. JSON Mode (강제)
    • 어떤 모델이든 JSON만 출력하도록 강제
    • use_json_mode=True 로 설정

9. Pre-built FastAPI Route

  • 에이전트를 REST API로 바로 노출할 수 있는 FastAPI 라우터를 기본 제공 → 에이전트를 만든 뒤, /docs (Swagger)에서 바로 호출/테스트하고, 운영, 배포까지 빠르게 할 수 있음
  • 방법
  1. 템플릿 사용하기
    1. Agent API: FastAPI + Postgres로 구성된 경량 REST API 서버
      Docker로 띄우고 http://localhost:8000/docs에서 바로 테스트 가능
    2. Agent APP: FastAPI(API) + Streamlit(관리 UI) + Postgres가 포함된 예제 앱.
      로컬 Docker 실행 또는 ag ws up으로 구동해 테스트 가능
  2. 내 Fast API 앱에 통합하기
    1. FastAPIApp으로 에이전트를 감싸 빠르게 엔드포인트를 제공할 수 있음
      : register_agent_routes(app, agent) 로 라우트 등록

10. 모니터링

에이전트/팀/워크플로의 실시간 세션과 성능을 웹 대시보드 (app.agno.com)에서 확인할 수 있음

  • 생성한 에이전트에 대해 monitoring=True 라고 설정하면 에이전트의 세션이 대시보드에 올라감
  • export AGNO_MONITOR=true 환경변수로 모든 에이전트의 모니터링을 활성화할 수도 있음

Agno Installation

pip install -U agno

Level 1

# 1. Import
from agno.agent import Agent
from agno.models.anthropic import Claude
from agno.tools.duckduckgo import DuckDuckGoTools

# 2. Agent 구성
agent = Agent(
    model=Claude(id="claude-sonnet-4-20250514"),
    tools=[DuckDuckGoTools()],
    instructions="Use tables to display data. Don't include any other text.",
    markdown=True,
)

# 3. 실행
agent.print_response("What is the stock price of Apple?", stream=True)

1. Import

from agno.agent import Agent
from agno.models.anthropic import Claude
from agno.tools.duckduckgo import DuckDuckGoTools
  • Agent: Agno의 핵심 객체. “모델 + 도구 + 지침”을 한 덩어리 에이전트로 묶음
  • Claude: Anthropic의 LLM(여기선 claude-sonnet-4-20250514 모델)을 쓰기 위한 래퍼
  • DuckDuckGoTools: DuckDuckGo 검색/뉴스를 실시간으로 조회하는 웹 도구

Agno에서 제공하는 Tool

  • 주요 도구
    1. ReasoningTools: 체계적인 사고를 도와주는 추론 보조 도구
    2. DuckDuckGoTools: 실시간 웹 검색 및 뉴스 제공
    3. YFinanceTools: 주가, 기업 정보, 기업 뉴스 등 금융 데이터 제공
    4. CalulatorTools: 사칙연산, 제곱, 소수 판별 같은 수학 계산 도구
    5. GoogleSearchTools: 구글 검색 도구 제공
    6. GithubTools: Github 레포지토리 검색, PR/issue 조회, 생성 등 지원
    7. 커스텀 도구: @tool 데코레이터 사용 또는 Toolkit 클래스를 상속해 만들 수 있음

2. Agent 구성

agent = Agent(
    model=Claude(id="claude-sonnet-4-20250514"),
    tools=[DuckDuckGoTools()],
    instructions="Use tables to display data. Don't include any other text.",
    markdown=True,
)
  1. model=Claude(...)
    • 실제로 답변을 생성하는 LLM 지정
    • id="claude-sonnet-4-20250514" : 사용할 Claude 버전
  2. tools=[...]
    • DuckDuckGoTools(search=True, news=True) : 에이전트가 웹 검색/ 뉴스 검색을 수행하도록 함
      • 내부적으로 DukDukGo를 호출해 최신 기사/링크/요약을 가져오고, 모델은 이 도구 결과를 바탕으로 답변함
  3. instructions="Use tables to display data." : 상위지침 가이드
    • 데이터를 table로 보임을 강제해 결과가 table 형식으로 나오도록 유도함
  4. markdown=True : 에이전트 출력이 마크다운 형식임을 명시

3. 실행

agent.print_response("What is the stock price of Apple?", stream=True)
  • 에이전트가 실행됨
  • 진행 순서
    1. prompt 받음
    2. DuckDuckGoTools 가 최신 뉴스 검색/요약
    3. 결과를 표(마크다운) 형식으로 정리
  • stream=True: 모델의 토큰 생성 과정을 실시간으로 출력

Level 2

# 1. Import
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

# 2. 지식베이스(RAG) 구성
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),
    ),
)

# 3. 세션 저장소 설정
storage = SqliteStorage(table_name="agent_sessions", db_file="tmp/agent.db")

# 4. 에이전트 구성
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,
)

# 5. 최조 인덱싱 + 실행
if __name__ == "__main__":
    agent.knowledge.load(recreate=False)
    agent.print_response("What is Agno?", stream=True)

실행 과정

  1. 문서 URL(Agno 문서)을 내려받아 벡터DB(LanceDB)에 임베딩해 지식베이스로 만들기
  2. 세션 저장소(SQLite)를 붙여 대화 이력을 유지
  3. Claude 모델을 사용해 답변 전에 지식베이스를 검색(RAG)하고, 결과만 마크다운으로 출력
  4. 첫 실행 시 knowledge.load()로 인덱스를 구축하고, 이후엔 주석 처리하여 재사용

1. Import

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
  • Agent: Agno의 핵심 객체. “모델 + 도구 + 지침”을 한 덩어리 에이전트로 묶음
  • OpenAIEmbedder: 임베딩 생성기
    • OpenAI의 모델을 이용해 텍스트를 벡터로 바꿔줌
  • UrlKnowledge: 지식베이스(RAG) 래퍼
    • 웹 URL에서 문서를 가져와 → 텍스트 청크로 분할 → 임베딩 → 벡터DB에 저장
    • agno.knowledge에서는 url 외에도 csv, docx, langchain, pdf, text, markdown, webside, youtube 등을 지원함
  • Claude: Anthropic의 LLM(여기선 claude-sonnet-4-20250514 모델)을 쓰기 위한 래퍼

2. 지식베이스(RAG) 구성

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),
    ),
)
  • UrlKnowledge : 주어진 URL들의 콘텐츠를 다운로드 → 청크 분할 → 임베딩 → 벡터DB에 저장 하는 Wrapper
  • LanceDb: 로컬 벡터DB
    • uri="tmp/lancedb" : 현재 프로젝트 폴더 아래 tmp/lancedb에 DB파일 생성
    • table_name="agno_docs" : 테이블 이름. 같은 경로/이름이면 이후 실행에서 재사용함
    • search_type=SearchType.hybrid : 하이브리드 검색 (키워드 + 벡터 유사도) 사용
  • OpenAIEmbedder: 문서를 벡터화하는 모듈
    • id="text-embedding-3-small" : OpenAI 임베딩 모델

3. 세션 저장소 설정

storage = SqliteStorage(table_name="agent_sessions", db_file="tmp/agent.db")
  • SqliteStorage : session/history/state를 로컬 SQLite로 저장
  • 세션이 종료된 이후 같은 db_file 을 사용하면 같은 세션을 이어갈 수 있음

4. 에이전트 구성

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,
)
  • model=Claude(...)
    • 실제로 답변을 생성하는 LLM 지정
    • id="claude-sonnet-4-20250514" : 사용할 Claude 버전
  • instrucuins=[...] : 상위 지침
    • "Search your knowledge before answering the question." → RAG 강제
    • "Only include the output in your response. No other text." → 결과만 깔끔히
  • knowledge=knowledge : 위에서 만든 지식베이스(RAG)를 context 주입에 사용
  • storage=storage : SQLite 세션 저장소 연결
  • add_datetime_to_instructions=True : 시스템 지침에 현재 날짜/시간 포함
  • add_history_to_messages=True, num_history_runs=3: 최근 3번의 history를 대화 메시지에 주입 → 맥락 유지
  • markdown=True : 에이전트 출력이 마크다운 형식임을 명시

5. 최조 인덱싱 + 실행

if __name__ == "__main__":
    agent.knowledge.load(recreate=False)
    agent.print_response("What is Agno?", stream=True)
  • knowledge.load(recreate=False)
    • 첫 실행: URL 문서를 내려받아 청크 → 임베딩 → LanceDB에 upsert
    • 이후 실행: 이미 index가 있으면 스킵
  • print_response("What is Agno?", stream=True)
    • 사용자의 질문을 모델에 전달
    • RAG 검색 → 관련 청크 주입 → 답변 생성
    • stream=True 진행상황 바로바로 출력

Level 3

# 1. import
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.duckduckgo import DuckDuckGoTools

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),
        DuckDuckGoTools(search=True, 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,
    )

Memory

LLM이 문장을 분석 → 중요한 사실만 추출 → 표준 JSON 구조로 변환 → DB에 저장

  • 사용자 입력
"My favorite stocks are NVIDIA and TSLA"
  • JSON 구조
{
  "user": "ava",
  "fact": "좋아하는 주식 = NVIDIA, TSLA",
  "date": "2025-09-09"
}

ReasoningTools

  • ReasoningTools: 중간 사고 과정(계획/검증 등)을 잘 하도록 추론 보조 지침을 주입하는 툴
  • ReasoningTools(add_instructions=True) : 추론 지침을 자동으로 prompt에 추가해 모델이 단계적을 사고하도록 함
    • DEFAULT_INSTRUCTIONS
      You have access to the `think` and `analyze` tools to work through problems step-by-step and structure your thought process. You must ALWAYS `think` before making tool calls or generating a response.
      
              1. **Think** (scratchpad):
                  - Purpose: Use the `think` tool as a scratchpad to break down complex problems, outline steps, and decide on immediate actions within your reasoning flow. Use this to structure your internal monologue.
                  - Usage: Call `think` before making tool calls or generating a response. Explain your reasoning and specify the intended action (e.g., "make a tool call", "perform calculation", "ask clarifying question").
      
              2. **Analyze** (evaluation):
                  - Purpose: Evaluate the result of a think step or a set of tool calls. Assess if the result is expected, sufficient, or requires further investigation.
                  - Usage: Call `analyze` after a set of tool calls. Determine the `next_action` based on your analysis: `continue` (more reasoning needed), `validate` (seek external confirmation/validation if possible), or `final_answer` (ready to conclude).
                  - Explain your reasoning highlighting whether the result is correct/sufficient.
      
              ## IMPORTANT GUIDELINES
              - **Always Think First:** You MUST use the `think` tool before making tool calls or generating a response.
              - **Iterate to Solve:** Use the `think` and `analyze` tools iteratively to build a clear reasoning path. The typical flow is `Think` -> [`Tool Calls` if needed] -> [`Analyze` if needed] -> ... -> `final_answer`. Repeat this cycle until you reach a satisfactory conclusion.
              - **Make multiple tool calls in parallel:** After a `think` step, you can make multiple tool calls in parallel.
              - **Keep Thoughts Internal:** The reasoning steps (thoughts and analyses) are for your internal process only. Do not share them directly with the user.
              - **Conclude Clearly:** When your analysis determines the `next_action` is `final_answer`, provide a concise and accurate final answer to the user.

0개의 댓글