Tutoriel

Statut éditorial : En attente de relecture

Créer un agent typé avec Pydantic AI, outils et dépendances

Construire un agent Python dont les entrées, dépendances, outils et sortie sont validés par des types explicites.

Classification du contenu

Types

  • Agents IA

Technologies

Niveau
Avancé
Publié le
24 août 2026
Dernière relecture
Relecture en attente
Prochaine vérification
24 octobre 2026

Pydantic AI applique aux agents la même idée que Pydantic aux API : rendre les contrats explicites. Nous allons créer un assistant support qui consulte une commande via un outil et retourne une structure validée.

Installer le projet

~~~bash python -m venv .venv source .venv/bin/activate pip install -U pydantic-ai python-dotenv ~~~

Configurez la clé du fournisseur choisi dans l’environnement. Le nom de modèle dépend du provider ; centralisez-le dans une variable plutôt que de le répéter.

Définir les contrats

~~~python from dataclasses import dataclass from pydantic import BaseModel, Field

@dataclass class SupportDeps: order_repository: "OrderRepository" customer_id: str

class SupportAnswer(BaseModel): answer: str needs_human: bool = False confidence: float = Field(ge=0, le=1) ~~~

"SupportDeps" contient les services disponibles pendant un run. "SupportAnswer" décrit la sortie attendue par le reste de l’application.

Créer l’agent et son outil

~~~python from pydantic_ai import Agent, RunContext

agent = Agent( "openai:gpt-5-mini", deps_type=SupportDeps, output_type=SupportAnswer, system_prompt=( "Tu aides un client à comprendre sa commande. " "N'invente jamais un statut et demande une reprise humaine si nécessaire." ), )

@agent.tool async def get_order(ctx: RunContext[SupportDeps], order_id: str) -> dict: """Retourne une commande appartenant au client connecté.""" order = await ctx.deps.order_repository.get(order_id) if order is None or order["customer_id"] != ctx.deps.customer_id: return {"found": False} return { "found": True, "status": order["status"], "estimated_delivery": order.get("estimated_delivery"), } ~~~

Le contrôle d’autorisation reste dans l’outil. Le modèle ne doit jamais choisir lui-même quel client il est autorisé à consulter.

Exécuter l’agent

~~~python deps = SupportDeps( order_repository=repository, customer_id="customer-42", )

result = await agent.run( "Où en est la commande CMD-123 ?", deps=deps, )

answer = result.output print(answer.answer, answer.needs_human, answer.confidence) ~~~

La sortie est un objet Python validé. Si le modèle ne respecte pas le schéma, le framework peut lui demander de corriger sa réponse dans les limites configurées.

Rendre les instructions dynamiques

Utilisez une fonction de "system_prompt" lorsqu’une instruction dépend du contexte fiable, par exemple le rôle de l’utilisateur ou la langue. N’injectez pas directement un texte non fiable dans les instructions système.

Tester sans appeler les vrais services

Injectez un faux repository dans "SupportDeps". Testez au minimum : commande existante, commande appartenant à un autre client, identifiant inconnu, erreur du repository et sortie demandant une reprise humaine. Le typage ne prouve pas la justesse métier ; ajoutez des assertions sur le contenu et les outils appelés.

Production

Fixez des limites de requêtes et de tours, donnez aux outils des schémas étroits, imposez les autorisations côté code et journalisez identifiant de trace, modèle, latence et consommation. Une action destructive doit exiger confirmation et clé d’idempotence. Versionnez prompts et jeux de tests avec le code.

FAQ

Une sortie typée élimine-t-elle les hallucinations ?

Non. Elle garantit la forme, pas la vérité. Les valeurs critiques doivent venir d’un outil ou être vérifiées par des règles métier.

Pourquoi injecter les dépendances ?

Cela sépare l’agent de l’infrastructure, évite les variables globales et rend les tests beaucoup plus simples.

Sources utilisées