Hooks de sandbox
Un hook de sandbox exécute votre code à deux étapes du cycle de vie d'une sandbox. on_create s'exécute une seule fois lorsque la
sandbox est prête, avant le démarrage de l'agent. on_destroy s'exécute une seule fois à la fermeture de la session. Utilisez-les
pour initialiser un espace de travail ou effectuer le téléchargement de ce que l'agent a produit.
Prérequis : Installez le SDK et l'extra bashkit : uv add "mistralai-agents[bashkit]".
Initialiser l'espace de travail
Créez une sous-classe de agents.SandboxHook et placez une instance dans le paramètre hooks= de la sandbox, pas dans celui de l'agent. Les deux
étapes reçoivent ctx, un objet agents.SandboxCallbackContext.
Son attribut ctx.sandbox exécute des commandes avec execute() et lit des fichiers avec read_file(). Les commandes s'exécutent dans
l'espace de travail : les fichiers que vous y créez sont donc accessibles aux outils de l'agent :
from pathlib import Path
from mistralai import agents
class SeedWorkspace(agents.SandboxHook):
async def on_create(self, ctx: agents.SandboxCallbackContext) -> None:
result = await ctx.sandbox.execute("echo 'Run the tests with pytest.' > NOTES.md")
if result.exit_code != 0:
raise RuntimeError(f"seeding failed: {result.stderr}")
async def on_destroy(self, ctx: agents.SandboxCallbackContext) -> None:
report = await ctx.sandbox.read_file("NOTES.md")
Path("saved-notes.md").write_bytes(report) # in your process; deployed, upload it from the sandbox
agent = agents.Agent(
model="mistral-large-4",
environment=agents.BashkitSandbox(hooks=[SeedWorkspace()]),
)Chaque session de cet agent démarre avec un fichier NOTES.md dans son espace de travail et le copie hors de la
sandbox à la fermeture de la session. Une session se ferme lors de l'appel à await session.cancel(), lorsqu'une
limite de session est atteinte ou, dans votre processus, une fois
qu'un appel à agent.run() sans idempotency_key= termine son tour. Dans un bloc async with agents.local_runtime(), elle se ferme à la sortie du bloc. Consultez
le fonctionnement de la fin d'une session.
Lorsque vous déployez avec Studio (déploiements Auto-hébergés ou gérés par Mistral), le hook s'exécute dans du code qui
est rejoué : effectuez ses opérations via ctx.sandbox, utilisez
agents.now() et agents.sleep() pour gérer le temps et veillez à ce que tout téléchargement soit idempotent.
Une commande qui échoue ne lève pas d'exception : vérifiez donc exit_code. Dans une sandbox disposant de git, comme
MistralSandbox ou LocalDockerSandbox, une commande lente telle que git clone peut
dépasser le délai d'exécution par défaut de la sandbox (default_exec_timeout_seconds sur
MistralSandbox et
LocalDockerSandbox). Attribuez-lui un délai spécifique :
await ctx.sandbox.execute("git clone https://github.com/acme/api.git", timeout_seconds=240)Un hook de sandbox ne conserve aucun état entre ses deux étapes : déduisez ce dont on_destroy a besoin à partir des
arguments du constructeur du hook ou récupérez ces informations dans l'espace de travail.
Pour définir l'identité Git associée aux commits dans la sandbox, utilisez le hook intégré
agents.pattern.sandbox_hook.GitIdentity : consultez Identité Git.
NoSandbox, utilisé par défaut, ne crée jamais de sandbox : aucune des deux étapes ne s'exécute donc.
L'initialiser à partir d'une entrée de session
Les deux étapes déclarent des entrées de session comme le ferait un outil, avec
Annotated[T, agents.Depends()]. Utilisez une entrée pour initialiser l'espace de travail avec les éléments sur lesquels porte cette session :
import shlex
from typing import Annotated
from mistralai import agents
class RepositoryContext(agents.SessionInput):
input_id = "acme.repository"
provider: str
repository: str
revision: str
class RecordRepository(agents.SandboxHook):
async def on_create(
self,
ctx: agents.SandboxCallbackContext,
*,
repo: Annotated[RepositoryContext, agents.Depends()],
) -> None:
line = shlex.quote(f"{repo.repository}@{repo.revision}")
result = await ctx.sandbox.execute(f"echo {line} > REPOSITORY")
if result.exit_code != 0:
raise RuntimeError(f"seeding failed: {result.stderr}")
agent = agents.Agent(
model="mistral-large-4",
environment=agents.BashkitSandbox(hooks=[RecordRepository()]),
)Transmettez l'entrée au démarrage de la session, dans une fonction asynchrone, en poursuivant l'exemple ci-dessus :
repo = RepositoryContext(provider="github", repository="acme/api", revision="main")
session = await agent.start_session(session_inputs={RepositoryContext.input_id: repo})Protégez les valeurs d'entrée avec shlex.quote() avant de les insérer dans une commande : le shell exécute tout ce que
contient la chaîne. L'entrée est vérifiée avant la création de la sandbox.
Lorsqu'un hook de sandbox lève une exception
Si on_create lève une exception, la sandbox est supprimée et la session ne démarre pas. Dans votre processus, vous recevez
l'exception du hook. Pour un agent déployé, la session se termine en échec et son message indique uniquement le nom du hook
et le type d'exception. Les logs du déploiement contiennent l'erreur complète : n'incluez donc pas d'identifiants dans les messages d'exception.
agents serve n'affiche ce log que si AGENTS_SDK_DEBUG=1. Si on_destroy lève une exception, l'erreur est
consignée dans les logs et les autres hooks s'exécutent quand même.
Et après
Accès réseau : choisissez les ressources auxquelles la sandbox peut accéder.
Voir aussi :
- Références des hooks de sandbox :
SandboxHooket ses étapes.