écrits/tutorial/2026/06
Tutorial7 juin 2026·28 min

Construire des systèmes multi-agents prêts pour la production avec Agno en Python

Apprenez à construire, coordonner et déployer des systèmes d'IA multi-agents avec Agno — le framework Python haute performance autrefois connu sous le nom de Phidata. Ce guide pratique couvre les agents, les équipes, les workflows, la mémoire, les bases de connaissances, puis le déploiement de l'ensemble derrière un serveur FastAPI via AgentOS.

Construire un seul agent d'IA est facile. Construire un système d'agents qui planifient, délèguent, mémorisent et tournent de façon fiable en production, c'est là que la plupart des projets calent. Le framework Agno — autrefois connu sous le nom de Phidata — a été conçu précisément pour combler ce vide. Les agents s'instancient en quelques microsecondes, consomment une fraction de la mémoire des frameworks plus lourds et arrivent tout équipés : mémoire, bases de connaissances, sorties structurées et un runtime de production appelé AgentOS qui encapsule le tout derrière un serveur FastAPI.

Dans ce tutoriel, vous construirez un assistant de recherche qui grandit d'un seul agent vers une équipe coordonnée, puis vers un workflow multi-étapes, et enfin vers une API déployable. À la fin, vous comprendrez les quatre primitives fondamentales d'Agno — l'Agent, l'Équipe (Team), le Workflow et AgentOS — et comment elles se composent.

Prérequis

Avant de commencer, assurez-vous d'avoir :

  • Python 3.10+ installé (python --version)
  • Une familiarité de base avec Python et async/await
  • Une clé d'API OpenAI (ou Anthropic — Agno est agnostique vis-à-vis des modèles)
  • Un terminal et un éditeur de code (VS Code recommandé)

Vous devriez être à l'aise avec les environnements virtuels et la lecture des modèles Pydantic. Aucune expérience préalable des frameworks d'agents n'est requise.

Ce que vous allez construire

Un assistant de recherche progressivement plus riche :

  1. Un seul agent qui cherche sur le web et répond aux questions avec ses sources.
  2. Une équipe où un chef délègue à des agents spécialistes (recherche web + analyse).
  3. Un workflow qui exécute la recherche et l'analyse en parallèle, boucle jusqu'à réunir assez de matière, puis rédige un rapport.
  4. Un déploiement AgentOS exposant tout cela sous forme d'API REST avec des sessions persistantes.

Étape 1 : Mise en place du projet

Créez un dossier de projet et un environnement virtuel :

mkdir agno-research && cd agno-research
python -m venv .venv
source .venv/bin/activate   # Sous Windows : .venv\Scripts\activate

Installez Agno avec un fournisseur de modèle et les outils que nous utiliserons :

pip install -U agno openai ddgs lancedb tantivy

Une note rapide sur le rôle de chaque paquet :

  • agno — le framework lui-même
  • openai — le client du fournisseur de modèle
  • ddgs — alimente WebSearchTools (recherche DuckDuckGo, sans clé d'API)
  • lancedb et tantivy — la base de données vectorielle embarquée pour les bases de connaissances (Étape 5)

Exportez votre clé d'API :

export OPENAI_API_KEY="sk-..."

Astuce : Agno est réellement agnostique vis-à-vis des modèles. Pour utiliser Claude à la place, exécutez pip install anthropic, définissez ANTHROPIC_API_KEY et remplacez OpenAIChat(id="gpt-4o-mini") par Claude(id="claude-sonnet-4-0"). Tout le reste de ce tutoriel demeure identique.

Étape 2 : Votre premier agent

Un Agent Agno est l'unité atomique : un modèle, un jeu d'instructions et, éventuellement, des outils. Créez agent.py :

from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.tools.websearch import WebSearchTools
 
web_agent = Agent(
    name="Web Researcher",
    model=OpenAIChat(id="gpt-4o-mini"),
    tools=[WebSearchTools()],
    instructions=[
        "You are a meticulous research assistant.",
        "Always search the web before answering factual questions.",
        "Cite your sources as a bulleted list at the end.",
    ],
    add_datetime_to_context=True,
    markdown=True,
)
 
web_agent.print_response(
    "What were the biggest open-source AI agent frameworks released in 2026?",
    stream=True,
)

Exécutez-le :

python agent.py

Vous verrez l'agent raisonner, appeler l'outil de recherche et diffuser en flux une réponse formatée et sourcée vers votre terminal. Quelques points méritent d'être soulignés :

  • instructions est une liste de directives courtes. Agno les assemble dans le prompt système — gardez-les impératives et précises.
  • tools n'est qu'une liste d'objets outils. Le modèle décide quand les appeler ; vous n'écrivez jamais la logique d'orchestration à la main.
  • add_datetime_to_context=True injecte la date courante, ce qui ancre les requêtes du type « les plus récents ».
  • print_response(..., stream=True) est le moyen le plus rapide de voir la sortie pendant le développement.

Exécuter les agents par programmation

print_response est destinée aux humains. Dans du vrai code, utilisez run() pour récupérer un objet de réponse :

response = web_agent.run("Summarize the Agno framework in two sentences.")
print(response.content)        # la réponse textuelle

Pour les services à fort débit, chaque méthode a son jumeau asynchrone — arun() et aprint_response() — afin d'attendre plusieurs agents en parallèle.

Étape 3 : Sortie structurée avec Pydantic

Le texte d'un LLM est difficile à consommer par programmation. Agno peut forcer un agent à renvoyer un objet typé en passant un modèle Pydantic via output_schema. Créez structured.py :

from typing import List
from pydantic import BaseModel, Field
 
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.tools.websearch import WebSearchTools
 
 
class TopicBriefing(BaseModel):
    topic: str = Field(..., description="The subject being researched")
    summary: str = Field(..., description="A two-sentence overview")
    key_points: List[str] = Field(..., description="3-5 essential takeaways")
    sources: List[str] = Field(..., description="URLs used for the research")
 
 
briefing_agent = Agent(
    model=OpenAIChat(id="gpt-4o-mini"),
    tools=[WebSearchTools()],
    output_schema=TopicBriefing,
)
 
response = briefing_agent.run("Research the rise of small language models in 2026")
briefing: TopicBriefing = response.content
 
print(briefing.topic)
for point in briefing.key_points:
    print(f"- {point}")
print("Sources:", ", ".join(briefing.sources))

Comme response.content est désormais une véritable instance de TopicBriefing, vous obtenez l'autocomplétion, la validation et zéro analyse de chaîne fragile. Cette seule fonctionnalité rend les agents Agno sûrs à intégrer au sein d'applications plus vastes.

Étape 4 : Coordonner une équipe

Un seul agent est limité. Une Équipe (Team) permet à un modèle chef de déléguer à des membres spécialistes, chacun avec son rôle et ses outils. Le chef décide qui traite quoi et synthétise la réponse finale.

Créez team.py :

from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.team import Team
from agno.tools.websearch import WebSearchTools
from agno.tools.hackernews import HackerNewsTools
 
web_agent = Agent(
    name="Web Agent",
    role="Search the broad web for background and context",
    model=OpenAIChat(id="gpt-4o-mini"),
    tools=[WebSearchTools()],
    instructions="Always include sources.",
)
 
tech_pulse_agent = Agent(
    name="Tech Pulse Agent",
    role="Gauge developer sentiment from Hacker News discussions",
    model=OpenAIChat(id="gpt-4o-mini"),
    tools=[HackerNewsTools()],
    instructions="Summarize what practitioners actually think, not just headlines.",
)
 
research_team = Team(
    name="Research Team",
    model=OpenAIChat(id="gpt-4o"),
    members=[web_agent, tech_pulse_agent],
    instructions=[
        "You coordinate a research team.",
        "Delegate broad context to the Web Agent.",
        "Delegate community sentiment to the Tech Pulse Agent.",
        "Combine both into a balanced briefing with a clear verdict.",
    ],
    show_members_responses=True,
    markdown=True,
)
 
research_team.print_response(
    "Should a startup adopt Agno for its agent stack in 2026?",
    stream=True,
)

Idées clés :

  • Chaque membre possède un role — une description d'une ligne que le chef utilise pour router le travail. Rédigez les rôles comme des fiches de poste, pas comme des instructions.
  • Le chef (research_team) reçoit généralement un modèle plus puissant que les membres, car la coordination et la synthèse sont plus difficiles que les recherches individuelles.
  • show_members_responses=True fait remonter la contribution de chaque membre, ce qui est inestimable pour déboguer la délégation.

Exécutez-le et observez le chef se répartir vers les deux spécialistes, puis fusionner leurs résultats en un verdict unique. Vous n'avez écrit aucun code de routage — le chef d'équipe gère la délégation via des appels d'outils en coulisses.

Étape 5 : Ajouter mémoire et connaissances

Les vrais assistants se souviennent des conversations passées et peuvent ancrer leurs réponses dans vos propres documents. Agno gère les deux via une base de données (pour la mémoire et les sessions) et une base de Connaissances (Knowledge) (pour la récupération).

Créez memory_knowledge.py :

from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.db.sqlite import SqliteDb
from agno.knowledge.knowledge import Knowledge
from agno.knowledge.embedder.openai import OpenAIEmbedder
from agno.vectordb.lancedb import LanceDb, SearchType
 
# Stockage persistant pour les sessions et la mémoire utilisateur de long terme
db = SqliteDb(db_file="tmp/research.db")
 
# Une base de connaissances adossée à un magasin vectoriel LanceDB embarqué
knowledge = Knowledge(
    vector_db=LanceDb(
        uri="tmp/lancedb",
        table_name="research_docs",
        search_type=SearchType.hybrid,
        embedder=OpenAIEmbedder(id="text-embedding-3-small"),
    ),
)
 
# Ingérez un document une seule fois ; il est découpé, vectorisé et indexé automatiquement
knowledge.insert(url="https://www.paulgraham.com/read.html")
 
assistant = Agent(
    name="Grounded Assistant",
    model=OpenAIChat(id="gpt-4o-mini"),
    db=db,
    knowledge=knowledge,
    search_knowledge=True,          # autorise l'agent à récupérer depuis la base de connaissances
    add_history_to_context=True,    # inclut les tours récents dans le prompt
    num_history_runs=3,             # combien d'échanges passés inclure
    update_memory_on_run=True,      # apprend des faits durables sur l'utilisateur
    markdown=True,
)
 
# Passez un user_id et un session_id stables pour relier la mémoire entre les exécutions
assistant.print_response(
    "According to the essay I added, why does reading matter?",
    user_id="anis@example.com",
    session_id="session-1",
)

Ce que fait chaque élément :

  • SqliteDb persiste les sessions et les mémoires dans un fichier local. En production, vous le remplaceriez par PostgresDb — le code de l'agent ne change pas.
  • Knowledge + LanceDb vous offre une recherche hybride (vectorielle + mots-clés) sur le contenu ingéré. search_knowledge=True indique à l'agent qu'il peut y récupérer des informations.
  • add_history_to_context et num_history_runs contrôlent la mémoire conversationnelle au sein d'une session.
  • update_memory_on_run permet à l'agent d'extraire des faits durables (« l'utilisateur préfère des réponses concises ») et de les rappeler dans de futures sessions liées au même user_id.

C'est le moment où une démo devient un assistant : il se souvient de son interlocuteur et peut citer vos documents.

Étape 6 : Orchestrer un workflow

Les équipes sont parfaites quand vous voulez que le modèle décide qui fait quoi. Mais parfois, il vous faut un flux de contrôle déterministe — exécuter ces étapes en parallèle, boucler jusqu'à atteindre un seuil de qualité, brancher selon une condition. C'est à cela que sert un Workflow.

Créez workflow.py :

from typing import List
 
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.tools.websearch import WebSearchTools
from agno.tools.hackernews import HackerNewsTools
from agno.workflow import Loop, Parallel, Step, Workflow
from agno.workflow.types import StepOutput
 
# --- Agents ---
web_researcher = Agent(
    name="Web Researcher",
    model=OpenAIChat(id="gpt-4o-mini"),
    tools=[WebSearchTools()],
    instructions="Research the topic thoroughly from web sources.",
)
hn_researcher = Agent(
    name="HN Researcher",
    model=OpenAIChat(id="gpt-4o-mini"),
    tools=[HackerNewsTools()],
    instructions="Surface what developers are saying about the topic.",
)
writer = Agent(
    name="Report Writer",
    model=OpenAIChat(id="gpt-4o"),
    instructions="Write a concise, well-structured report from the research provided.",
    markdown=True,
)
 
# --- Étapes ---
research_web = Step(name="Research Web", agent=web_researcher)
research_hn = Step(name="Research HN", agent=hn_researcher)
write_report = Step(name="Write Report", agent=writer)
 
 
# --- Condition de sortie de boucle : continuer jusqu'à réunir assez de matière ---
def enough_research(outputs: List[StepOutput]) -> bool:
    total = sum(len(o.content or "") for o in outputs)
    return total > 1500
 
 
# --- Workflow : recherche parallèle dans une boucle, puis rédaction ---
workflow = Workflow(
    name="Deep Research Workflow",
    description="Research a topic in parallel until sufficient, then write a report",
    steps=[
        Loop(
            name="Research Loop",
            steps=[Parallel(research_web, research_hn, name="Parallel Research")],
            end_condition=enough_research,
            max_iterations=3,
        ),
        write_report,
    ],
)
 
if __name__ == "__main__":
    workflow.print_response(
        input="The state of TypeScript-first AI agent frameworks in 2026",
        stream=True,
    )

Les briques de base qu'Agno vous fournit pour les workflows :

PrimitiveRôle
StepExécuter un agent (ou une fonction) comme une unité
ParallelExécuter plusieurs étapes simultanément
LoopRépéter des étapes jusqu'à ce que end_condition soit vrai ou que max_iterations soit atteint
RouterChoisir une branche dynamiquement via une fonction de sélection
ConditionExécuter des étapes seulement si une expression est vraie (avec else_steps optionnel)

Ici, les deux chercheurs s'exécutent en même temps à l'intérieur d'une Loop qui continue jusqu'à ce que la sortie combinée dépasse 1500 caractères (ou que trois itérations passent), après quoi le rédacteur produit le rapport final. Contrairement à une équipe, le flux de contrôle est entièrement déterministe et testable — vous pouvez tester unitairement enough_research() de manière isolée.

Brancher avec Condition

Pour le routage, Agno prend même en charge des conditions basées sur des expressions :

from agno.workflow import Condition, Step, Workflow
 
workflow = Workflow(
    name="Classify and Route",
    steps=[
        Step(name="Classify", agent=classifier),
        Condition(
            name="Route by Type",
            evaluator='previous_step_content.contains("TECHNICAL")',
            steps=[Step(name="Technical Help", agent=technical_agent)],
            else_steps=[Step(name="General Help", agent=general_agent)],
        ),
    ],
)

Le classificateur étiquette la requête, et la Condition l'envoie dans la bonne branche — sans aucun code de liaison au milieu.

Étape 7 : Déployer avec AgentOS

Un script fonctionnel n'est pas un produit. AgentOS encapsule vos agents, équipes et workflows dans une application FastAPI prête à l'emploi — avec stockage des sessions, historique des conversations et points de terminaison de surveillance — que vous exécutez dans votre propre infrastructure.

Créez serve.py :

from agno.agent import Agent
from agno.team import Team
from agno.workflow import Step, Workflow
from agno.models.openai import OpenAIChat
from agno.db.sqlite import SqliteDb
from agno.tools.websearch import WebSearchTools
from agno.os import AgentOS
 
db = SqliteDb(db_file="tmp/agentos.db")
 
researcher = Agent(
    name="Researcher",
    model=OpenAIChat(id="gpt-4o-mini"),
    db=db,
    tools=[WebSearchTools()],
    instructions="Research thoroughly and cite sources.",
    add_history_to_context=True,
    markdown=True,
)
 
research_team = Team(
    name="Research Team",
    model=OpenAIChat(id="gpt-4o"),
    db=db,
    members=[researcher],
    instructions="Coordinate research and deliver a clear briefing.",
)
 
qa_workflow = Workflow(
    name="QA Workflow",
    description="Answer a question using the researcher agent",
    db=db,
    steps=[Step(name="Answer", agent=researcher)],
)
 
agent_os = AgentOS(
    description="Research AgentOS",
    agents=[researcher],
    teams=[research_team],
    workflows=[qa_workflow],
)
 
# Instance d'application FastAPI — uvicorn recherche `app`
app = agent_os.get_app()
 
if __name__ == "__main__":
    agent_os.serve(app="serve:app", reload=True)

Démarrez le serveur :

python serve.py

AgentOS démarre un serveur FastAPI (par défaut http://localhost:7777) avec des points de terminaison REST générés automatiquement pour chaque agent, équipe et workflow enregistré, ainsi qu'une documentation interactive sur /docs. Comme chaque composant partage la même db, les sessions et la mémoire sont persistées automatiquement — vos agents se souviennent des conversations d'une requête HTTP à l'autre.

Le runtime est sans état et horizontalement scalable : exécutez plusieurs instances derrière un répartiteur de charge et pointez-les vers une base de données Postgres partagée. C'est la « pièce manquante » autour de laquelle Agno est conçu — le pont entre un prototype fonctionnel et un produit déployé.

Tester votre implémentation

Vérifiez chaque couche dans l'ordre :

  1. Agentpython agent.py diffuse une réponse sourcée.
  2. Sortie structuréepython structured.py affiche des champs typés sans erreur.
  3. Équipepython team.py montre la contribution des deux membres, puis un verdict fusionné.
  4. Mémoire — exécutez memory_knowledge.py deux fois avec le même user_id ; la seconde exécution devrait rappeler le contexte.
  5. Workflowpython workflow.py exécute une recherche parallèle dans une boucle avant la rédaction.
  6. AgentOS — ouvrez http://localhost:7777/docs et appelez un point de terminaison ; confirmez la réponse et l'apparition d'une ligne de session dans tmp/agentos.db.

Dépannage

ModuleNotFoundError: No module named 'ddgs'WebSearchTools a besoin du moteur de recherche. Exécutez pip install ddgs.

Appels d'outils vides ou refusés — votre modèle est peut-être trop petit pour raisonner sur les outils de façon fiable. Faites passer le chef/orchestrateur à un modèle plus puissant (gpt-4o, claude-sonnet-4-0) et réservez le modèle bon marché aux rôles de membres simples.

La base de connaissances ne renvoie rien — vérifiez que search_knowledge=True est défini sur l'agent et que knowledge.insert(...) s'est exécuté avec succès avant la requête. La recherche hybride nécessite aussi l'installation de tantivy.

La mémoire ne persiste pas — assurez-vous de passer un user_id et un session_id stables, que l'agent possède une db, et que update_memory_on_run=True et/ou add_history_to_context=True sont définis.

AgentOS ne démarre pas avec serve() — la chaîne app= doit être "<module>:app" correspondant au nom de votre fichier. Dans serve.py, c'est "serve:app".

Prochaines étapes

  • Remplacez SqliteDb par PostgresDb et déployez AgentOS derrière un répartiteur de charge.
  • Ajoutez des étapes Router pour choisir dynamiquement les stratégies de recherche selon le sujet.
  • Connectez des outils externes via MCP grâce à la classe MCPTools d'Agno.
  • Ajoutez de l'évaluation avec ReliabilityEval d'Agno pour détecter les régressions dans le comportement des agents.
  • Explorez des tutoriels connexes sur notre site : systèmes multi-agents CrewAI, agents type-safe Pydantic AI et agents orientés code smolagents.

Conclusion

Vous avez fait passer un assistant de recherche d'un simple agent utilisant un outil jusqu'à une API horizontalement scalable. En chemin, vous avez rencontré les quatre primitives d'Agno qui se composent pour former presque n'importe quel système agentique : l'Agent pour la capacité individuelle, l'Équipe pour la délégation pilotée par le modèle, le Workflow pour l'orchestration déterministe, et AgentOS pour le déploiement en production. Les forces qui définissent Agno — instanciation en microsecondes, faible empreinte mémoire et runtime tout équipé — signifient que le système prototypé cet après-midi est exactement celui que vous livrerez. Commencez petit avec un seul agent, et ne recourez aux équipes et aux workflows que lorsque le problème l'exige réellement.