Évaluer les agents du SDK Agents

Si le système que vous évaluez est un agent créé avec le SDK Agents, passez-le comme AgentSystem plutôt que de décrire un System manuellement. La tâche exécute l'agent, et l'exécution enregistre l'agent évalué, sous-agents compris, pour que Studio puisse l'afficher.

Avant de commencer

Avant de commencer

Vous avez besoin du SDK Évaluation (voir Installation) et d'une clé API Mistral. Installez le SDK Agents, mistralai-agents en version 1.1.0 ou ultérieure :

pip install -U mistralai-agents

Le SDK Agents n'est pas une dépendance de mistralai-evaluations. Le SDK Évaluation utilise un agent défini dans le code via ses propres méthodes et n'importe le SDK Agents que pour accéder à un agent déployé.

Évaluer un agent

Évaluer un agent

Créez l'agent, puis écrivez une tâche qui l'exécute via ctx.agent :

import asyncio
import os

from mistralai import agents
from mistralai.evaluations import (
    AgentSystem, Evaluation, Evaluator, Mistral, Project, ScorerContext, TaskContext,
)

client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])


@agents.tool
async def lookup_order(order_id: str) -> dict[str, str]:
    """Get the status of an order."""
    return {"order_id": order_id, "status": "shipped on Monday"}  # read from your database


agent = agents.Agent(
    name="support-bot",
    model="mistral-small-latest",
    instructions="You are the support agent of Shopi. Look the order up before answering.",
    tools=[lookup_order],
)

dataset = [
    {"question": "Has order 1042 shipped?", "expected": "shipped"},
    {"question": "What is the status of order 2077?", "expected": "shipped"},
]


async def task(ctx: TaskContext) -> str:
    result = await ctx.agent.run(ctx.input_record["question"])
    return result.text or ""


def scorer(ctx: ScorerContext) -> int:
    return 1 if ctx.input_record["expected"] in str(ctx.output).lower() else 0


evaluators = [
    Evaluator(
        name="accuracy",
        description="1 if the answer contains the expected status, 0 otherwise.",
        scorer=scorer,
    ),
]


async def main():
    run = await client.evaluation.run(
        system=AgentSystem(agent=agent),
        task=task,
        dataset=dataset,
        evaluators=evaluators,
        project=Project(name="Support"),
        evaluation=Evaluation(name="Support bot"),
    )
    run.show(level="run")


asyncio.run(main())

ctx.agent est l'agent à exécuter. Il s'exécute dans votre processus, avec ses outils et hooks réels.

ctx.agent n'est pas l'objet Agent lui-même. ctx.agent.run() est décrit dans Tours qui ne se terminent pas. Tout le reste (name, start_session(), les paramètres) appartient à l'objet Agent. ctx.agent.agent est l'objet Agent auquel les paramètres de remplacement de l'exécution sont appliqués.

Tours qui ne se terminent pas

Tours qui ne se terminent pas

ctx.agent.run() accepte les mêmes arguments que Agent.run() et renvoie le tour Completed.

Tout autre résultat lève AgentTurnError, avec l'enregistrement du tour du SDK Agents dans turn. Cela couvre un tour Failed, Interrupted ou Blocked en attente d'approbation, un tour Busy parce qu'un autre tour de la session est actif, un tour Running parce que son timeout a expiré, ainsi qu'un résultat que le SDK Agents ne reconnaît pas.

Lorsqu'un tour lève une exception, l'enregistrement échoue et les évaluateurs ne lui attribuent pas de score. retry_failed_records() relance l'enregistrement.

Avertissement

Un tour en échec n'apparaît pas dans les statistiques. Vérifiez run.failed_record_count avant de consulter les scores. run.show() affiche cette valeur.

Un tour bloqué en attente d'approbation fait également échouer son enregistrement. Pour permettre à l'agent de continuer, répondez aux demandes d'approbation dans la tâche :

async def task(ctx: TaskContext) -> str:
    result = await ctx.agent.run(
        ctx.input_record["question"],
        on_approval=lambda callback, request: agents.AllowApproval(),
    )
    return result.text or ""

Avec output_type=, un tour dont la sortie ne passe pas la validation reste Completed. Son output est un objet agents.InvalidOutput, que la tâche peut vérifier ou renvoyer pour que les évaluateurs lui attribuent un score.

Évaluer une variante

Évaluer une variante

overrides modifie certains paramètres de l'agent pour cette exécution uniquement. Votre objet Agent n'est pas modifié, et rien n'est créé ni modifié sur un agent déployé.

system = AgentSystem(
    agent=agent,
    overrides={"instructions": "Always look the order up before answering.", "temperature": 0.0},
)

Vous pouvez remplacer tout paramètre de l'objet Agent qui accepte une valeur simple, à l'exception de name : par exemple model, instructions, temperature, max_iterations, reasoning_effort ou permission_mode. L'objet Agent vérifie les valeurs avant le démarrage de l'exécution. Un paramètre ajouté par une version plus récente du SDK Agents peut donc être remplacé dès que vous installez cette version.

Les outils, hooks, skills et sous-agents font partie de la définition de l'agent. Pour les modifier, créez un autre objet Agent. Un agent créé avec sa propre configuration completion= y définit son modèle, sa température et son effort de raisonnement. Ces paramètres ne peuvent donc pas être remplacés.

Décrire l'exécution au-delà de l'agent

Décrire l'exécution au-delà de l'agent

params enregistre ce que l'exécution fait varier en dehors des paramètres de l'agent, par exemple l'environnement dans lequel il s'exécute. L'exécution enregistre ces valeurs avec les paramètres de remplacement dans les params du système, pour que vous puissiez comparer les exécutions selon ces deux aspects :

system = AgentSystem(
    agent=agent,
    overrides={"temperature": 0.0},
    params={"sandbox": "mistral"},
)

params est uniquement enregistré, jamais appliqué à l'agent. Une clé va dans overrides ou dans params, pas dans les deux. Un paramètre de l'objet Agent va dans overrides.

Optimiser un agent

Optimiser un agent

evaluation.optimize() accepte aussi un AgentSystem. Placez les paramètres à explorer dans Tunable. Les valeurs fixes restent inchangées.

from mistralai.evaluations import GEPA, Tunable

system = AgentSystem(
    agent=agent,
    overrides={
        "instructions": Tunable(agent.instructions),
        "temperature": Tunable(0.7, bounds=(0.0, 1.0)),
        "max_iterations": 20,
    },
)
result = await client.evaluation.optimize(
    system=system, task=task, dataset=dataset, evaluators=evaluators, algo=GEPA(),
)

Chaque candidat correspond à une exécution de l'agent avec les valeurs de ce candidat. Voir Optimiser les prompts et les paramètres.

La tâche doit accepter un argument ctx: TaskContext (avec annotation de type), car l'agent est accessible via ctx.agent. optimize() refuse un AgentSystem avec toute autre signature de tâche avant le début de l'optimisation.

result.winner.system (ou result.best_attempt.system) contient les paramètres de remplacement retenus. Évaluez à nouveau l'agent optimisé avec ces paramètres, puis inscrivez les valeurs dans votre objet Agent ou redéployez-le :

if result.winner:
    best = AgentSystem(agent=agent, overrides=result.winner.system)

Pour un agent déployé, les paramètres de remplacement sont des paramètres de session. Inscrivez model et reasoning_effort dans le code de l'agent avant de le redéployer. additional_instructions peut rester un paramètre de remplacement de session.

Évaluer un agent déployé

Évaluer un agent déployé

Passez le nom ou l'identifiant d'un agent déployé pour évaluer le déploiement lui-même. Chaque enregistrement exécute une session sur cet agent. La tâche n'a donc pas besoin du code de l'agent.

system = AgentSystem(agent="support-bot", overrides={"model": "mistral-medium-latest"})

Cela nécessite l'installation du SDK Agents et une exécution enregistrée dans Studio (sans local=True). L'agent est recherché et exécuté avec les identifiants du client, sur le même serveur que l'évaluation.

Un agent déployé est modifié au niveau de chaque session. Les paramètres de remplacement sont ceux que le SDK Agents permet à une session de modifier : model, reasoning_effort et additional_instructions, qui s'ajoute aux instructions déployées. Voir SessionAgentCustomization.

ctx.agent.run() transmet ses options au déploiement comme le fait Agent.run(). Avec output_type=, le SDK Agents valide la réponse par rapport au type, mais le déploiement conserve sa propre configuration de complétion. Si ses instructions ne demandent pas ce format, attendez-vous à un objet agents.InvalidOutput.

Le client d'évaluation recherche l'agent avec ses paramètres HTTP (proxy, TLS). Les sessions de l'agent déployé passent par le client HTTP du SDK Agents, qui ne récupère les proxys que depuis l'environnement (HTTPS_PROXY). Avec mistralai 3, dont le client utilise httpx2, la recherche utilise également les paramètres HTTP du SDK Agents.

Identifiants

Identifiants

L'accès à l'API Agents utilise l'identité du client d'évaluation. Un client disposant d'une clé API la transmet.

Un client sans clé API, dont le client HTTP définit l'en-tête Authorization sur chaque requête, fait passer tous les appels à l'API Agents par ce client HTTP : les recherches d'agents et les sessions d'un agent déployé. Voir Identifiants sans clé API. Dans un workflow Mistral, ces appels s'exécutent sous le compte de service du worker sur un déploiement géré. Lorsque le workflow est déclaré avec on_behalf_of=True, ils s'exécutent sous l'identité de l'utilisateur qui l'exécute. L'agent déployé est alors recherché dans l'espace de travail de cet utilisateur et s'exécute sous son identité.

Avec mistralai 3, dont le client utilise httpx2, le SDK Agents reçoit un client httpx avec les mêmes identifiants, en-têtes, délai d'expiration et paramètres TLS (bundle d'autorités de certification, certificat client). Comme le client httpx2, il lit son proxy depuis l'environnement (HTTPS_PROXY), sauf si ce client a été créé avec trust_env=False. Un proxy défini directement sur le client httpx2 n'est pas repris.

Un agent défini dans le code s'exécute dans votre processus. Ses appels au modèle, ses connecteurs et ses serveurs MCP utilisent les identifiants de son propre environnement (MISTRAL_API_KEY), quels que soient ceux du client d'évaluation.

Exécuter l'agent ailleurs

Exécuter l'agent ailleurs

La tâche n'a pas besoin d'appeler ctx.agent.run(...). Lorsque votre agent s'exécute dans un autre processus ou une sandbox, lisez les paramètres de ctx.agent (l'agent auquel les paramètres de remplacement sont appliqués) et transmettez-les à son environnement d'exécution. L'exécution enregistre toujours l'agent, ses variantes et son optimisation :

from my_agent import agent  # the same Agent your runner builds


async def task(ctx: TaskContext) -> str:
    return await run_in_sandbox(
        prompt=ctx.input_record["prompt"],
        model=ctx.agent.model,
        instructions=ctx.agent.instructions,
        max_iterations=ctx.agent.max_iterations,
    )


system = AgentSystem(
    agent=agent,
    overrides={"model": "mistral-medium-latest"},
    params={"sandbox": "docker"},
)

Transmettez chaque paramètre que votre exécuteur applique : l'exécution enregistre la configuration de ctx.agent, pas ce que l'exécuteur en a fait.

Ce que l'exécution enregistre

Ce que l'exécution enregistre

Le système de l'exécution a kind="agent". Il contient :

  • les paramètres de remplacement et params dans ses params : ce qui varie entre les exécutions et fait l'objet de comparaisons et d'optimisations ;
  • l'agent tel qu'il est évalué dans son spec, enregistré selon la description fournie par le SDK Agents.

Un System créé manuellement a kind="custom" et aucun spec.

Pour un agent défini dans le code, le spec est sa configuration telle que le SDK Agents la sérialise (modèle et paramètres de complétion, instructions, fonctionnalités intégrées, autorisations, sous-agents), avec les paramètres de remplacement appliqués. Le SDK Agents n'ajoute les outils, hooks, skills, serveurs MCP et connecteurs de l'agent qu'au démarrage d'une session et ne les expose pas autrement. Le spec les enregistre donc comme inconnus (null). Un sous-agent est compilé avec ses propres outils et hooks, qui sont donc enregistrés.

Pour un agent déployé, le spec est l'enregistrement de l'agent tel qu'il a été déployé. Les paramètres de remplacement de session constituent les params de l'exécution.

Dans les deux cas, spec.base conserve également les valeurs remplacées : une entrée par paramètre de remplacement, ou null lorsqu'il ne remplace rien, comme c'est le cas pour additional_instructions. Cela permet de distinguer les paramètres de remplacement de params.

Avec une version du SDK Agents qui ne peut pas sérialiser un agent, l'exécution démarre tout de même. La configuration d'un agent défini dans le code est enregistrée comme inconnue (null) et un avertissement est consigné dans les logs.

L'exécution stocke la configuration telle quelle. N'y incluez pas d'identifiants, comme le fait le SDK Agents : il les référence par une variable d'environnement ou un secret de l'espace de travail, jamais par leur valeur.

Lorsqu'un agent déployé dans l'espace de travail porte le même nom (ou que l'exécution évalue un agent déployé), l'exécution lui est liée. Studio peut ainsi ouvrir l'agent depuis ses exécutions. Un lien établi par nom est signalé comme tel, car l'agent déployé peut exécuter un autre code que celui que vous avez évalué.

Si l'API Agents est inaccessible ou refuse les identifiants du client, l'exécution ne démarre pas.

Relancer les enregistrements en échec

Relancer les enregistrements en échec

Pour relancer les enregistrements en échec d'une exécution d'agent, passez le même AgentSystem à retry_failed_records(). La relance est refusée si la configuration de l'agent (sous-agents compris) a changé depuis l'exécution. Les enregistrements d'une même exécution proviennent ainsi toujours d'un seul agent.

  • Les paramètres définis par l'environnement (l'URL de la passerelle de complétion et la variable contenant la clé) ne sont pas comparés.
  • Mettre à jour le SDK Agents entre l'exécution et la relance peut modifier la configuration sérialisée et entraîner le refus de la relance.
  • Pour un agent déployé, la relance compare l'identifiant de l'agent et ses paramètres déployés (modèle, instructions, autorisations), pas la date de son déploiement. Redéployer le même agent n'entraîne pas le refus de la relance. Un redéploiement qui ne modifie que le code, les outils ou les skills de l'agent n'est pas détecté, car l'enregistrement déployé ne les décrit pas.
Résolution des problèmes

Résolution des problèmes

ProblèmeCauseSolution
Les scores semblent meilleurs que les performances réelles de l'agent.Les tours en échec n'apparaissent pas dans les statistiques.Vérifiez run.failed_record_count, puis appelez retry_failed_records().
Les enregistrements échouent avec AgentTurnError sur un tour Blocked.L'agent a demandé une approbation et n'a reçu aucune réponse.Passez on_approval= à ctx.agent.run().
optimize() refuse le AgentSystem avant de démarrer.La tâche n'accepte pas un unique argument ctx: TaskContext.Annotez le paramètre de la tâche avec TaskContext et appelez ctx.agent.run().
Un paramètre de remplacement est refusé avant le démarrage de l'exécution.L'objet Agent a rejeté la valeur, ou le paramètre n'est pas une valeur simple (outils, hooks, skills, sous-agents).Corrigez la valeur, ou créez un autre objet Agent pour les éléments qui ne sont pas des paramètres simples.
retry_failed_records() refuse la relance.La configuration de l'agent a changé depuis l'exécution, ou la version du SDK Agents a changé.Passez le même AgentSystem, avec la même version du SDK Agents que lors de l'exécution.
Et après

Et après