Serveur d’agent
Un serveur d’agent est la bibliothèque qui transforme votre code d’agent en service. Il enveloppe la boucle d’agent dans un serveur HTTP, définit l’API appelée par les clients pour exécuter l’agent, gère les connexions des clients et détermine ce qui se passe lorsqu’une exécution est interrompue. Le serveur d’agent s’exécute sur l’environnement d’exécution de l’agent. Pour découvrir comment les couches s’articulent, consultez Déployer des agents sur Databricks.
Serveurs d'agents sur Databricks
Databricks fournit trois serveurs d'agents. Pour les nouveaux agents, Databricks recommande DurableAgentServer.
Serveur d’agent | Package | Client d'API | Exécution durable | Utilisé par |
|---|---|---|---|---|
|
| Invocation d’API à | Un magasin Runtime que | Les projets que vous créez avec le CLI Agent Bricks |
|
| OpenAI Responses API à | Exécutez l'état dans une base de données Lakebase que vous configurez. Après un plantage, une nouvelle tentative poursuit l'exécution à partir du journal des événements de la tentative interrompue. | Les app Template |
MLflow |
| OpenAI Responses API sur | Aucun | Les Template d'application de base, tels que |
LongRunningAgentServer étend le composant MLflow AgentServer, et tous deux prennent en charge les agents qui implémentent l'interface MLflow ResponsesAgent. Pour déployer et maintenir un agent qui utilise l'un d'entre eux, consultez la section Exécuter des agents sur Databricks Apps à l'aide du serveur d'agents hérités. Pour query un agent sur l'un de ces serveurs, consultez la section Interroger des agents déployés sur Databricks.
DurableAgentServer
DurableAgentServer est le serveur d’agent Agent Bricks. Il enveloppe votre boucle d’agent dans un serveur HTTP qui dessert l’API d’invocation, suit chaque exécution et récupère les exécutions interrompues par un plantage ou un redémarrage. Les agents que vous créez avec la CLI Agent Bricks utilisent DurableAgentServer par default.
DurableAgentServer fournit :
- Une API pour chaque mode de requête : synchrones, en streaming et en arrière-plan, ainsi que la reconnexion au stream, toutes prises en charge par le même gestionnaire.
- Invocations idempotentes : un ID d’invocation généré par le client garantit qu’une nouvelle tentative de la requête ne start pas une exécution en double.
- Sessions ordonnées : les invocations d’une même session s’exécutent l’une après l’autre, dans l’ordre.
- État d'exécution persistant : lors du déploiement, le statut d'exécution, les événements et les résultats survivent aux redémarrages des worker.
- Crash recovery : le serveur détecte les exécutions interrompues et lance une tentative de remplacement.
- Autorisation de l'utilisateur demandeur : les outils peuvent agir avec les autorisations de l'utilisateur qui a envoyé la demande.
- Custom Endpoint :
DurableAgentServerest une application FastAPI, vous pouvez donc ajouter vos propres routes.
Conditions requises
DurableAgentServer possède les exigences suivantes :
- Python 3.10 et versions ultérieures.
- Le package
databricks-agentbricks, qui inclut la bibliothèquedatabricks_agentkit. Les projets que vous créez avecagentbricks initle déclarent comme dépendance.
Enregistrez votre agent
Lorsque vous créez un projet avec agentbricks init, la CLI s’en charge pour vous. Le runtime/main.py généré crée le serveur et enregistre les gestionnaires d’appel et de récupération du template, de sorte que vous ne modifiez le code de l’agent que dans agent/. Suivez les étapes de cette section pour importer un agent existant ou pour écrire votre propre gestionnaire.
Créez un DurableAgentServer et enregistrez un gestionnaire d’invocations asynchrones avec @app.invoke. Le gestionnaire reçoit le input de la requête ainsi qu’un contexte d’invocation, et renvoie un résultat sérialisable en JSON. Publiez la progression sous forme d’événements avec context.emit.
from databricks_agentkit import DurableAgentServer, InvocationContext
app = DurableAgentServer()
@app.invoke
async def invoke(input, context: InvocationContext) -> dict:
await context.emit({"type": "status", "message": "Looking that up"})
answer = await run_my_agent(input, session_id=context.session_id)
return {"answer": answer}
Vous pouvez enregistrer un gestionnaire d'appels, et le serveur ne start pas sans lui. Le gestionnaire prend en charge tous les modes de requête : le client choisit s'il souhaite attendre le résultat, Stream des événements ou s'exécuter en arrière-plan.
Pour exécuter le serveur localement, start avec agentbricks dev. Les projets que vous créez avec agentbricks init incluent un point d’entrée qui exécute le serveur avec Uvicorn, ainsi qu’un fichier app.yaml qui start ce même point d’entrée après le déploiement.
Contexte d'invocation
Le deuxième argument du gestionnaire est un ou une InvocationContext:
Attribut | Description |
|---|---|
| L’ID que le client a envoyé pour cette invocation. |
| La session à laquelle l’invocation appartient, ou |
| La première tentative est . La première tentative est |
|
|
| Stocke un événement JSON, le transmet aux clients de streaming et renvoie la position de l'événement dans le Stream. |
| Le résolveur d’identifiants de l’utilisateur de la requête, lorsque l’agent requiert une autorisation d’utilisateur de requête. Sinon, |
API Invocations
DurableAgentServer fournit l'API d'invocation sur /api/invocations:
POST /api/invocationsstart une invocation. Par default, la requête attend le résultat. Configurezstreampour recevoir des événements sous forme d’événements envoyés par le serveur (Server-Sent Events), oubackgroundpour un retour immédiat avec une URL de statut.GET /api/invocations/<id>renvoie l’état d’une invocation et, une fois celle-ci terminée, son résultat.GET /api/invocations/<id>/events?after=<event-id>Le Stream diffuse les événements stockés, afin qu’un client puisse se reconnecter après une rupture de connexion.
Pour en savoir plus sur les champs de requête, les exemples et les formats de réponse, consultez Query des agents déployés sur Databricks.
Idempotence
Les clients envoient un UUID id à chaque appel. Le serveur traite l'identifiant comme une clé d'idempotence tout en conservant l'enregistrement d'appel : le renvoi de la même requête renvoie l'appel existant au lieu de réexécuter l'agent. La réutilisation d'un identifiant pour une requête différente renvoie une erreur 409.
Sessions
Les clients peuvent envoyer un objet session_id pour regrouper les invocations au sein d'une même conversation. Le serveur stocke l’identifiant de session séparément de input, le transmet à votre gestionnaire en tant que context.session_id et exécute les appels qui partagent un identifiant de session un par un, dans l’ordre. Le serveur ne déduit pas de session à partir de l'ID d'invocation ou de l'entrée. Sans ID de session, une invocation est dépourvue de session.
État d'exécution
DurableAgentServer stocke la requête, le statut, les pulsations, les événements et le résultat de chaque invocation dans un Runtime Store.
- Développement local :
agentbricks devutilise un Runtime Store intraprocessus. L'API d'invocation se comporte de la même manière, mais l'état d'exécution est perdu lorsque le processus s'arrête, et le serveur ne redémarre pas le travail interrompu. - Agents déployés :
agentbricks deployprovisionne une base de données dédiée pour le Runtime Store de chaque déploiement dans un projet Lakebase géré par Databricks, et la réutilise lors d'un nouveau déploiement. Vous ne pouvez pas utiliser votre propre projet Lakebase pour le Runtime Store, et vous ne le créez ni ne l'associez vous-même. Les résultats et les événements persistent après les redémarrages des worker, et n'importe quelle instance de l'agent peut traiter les requêtes de statut et de reconnexion.agentbricks deployments deletesupprime le Runtime Store avec le déploiement.
Le Runtime Store conserve l'état d'exécution du serveur. Il est distinct des magasins de sessions et de mémoire que votre agent utilise pour l'historique des conversations et la mémoire à long terme.
Récupération après incident
Pour récupérer les exécutions interrompues par un plantage ou un redémarrage d’un worker, enregistrez un gestionnaire de récupération auprès de @app.recover. Lorsqu’un serveur déployé détecte que les pulsations d’une exécution se sont arrêtées, il start une tentative de remplacement sur un worker disponible et appelle le gestionnaire de récupération avec l’entrée d’origine.
@app.recover
async def recover(input, context: InvocationContext) -> dict:
# Resume from the agent's last checkpoint in the session store,
# or replay the input if that's safe for your agent.
return await resume_my_agent(input, session_id=context.session_id)
Si vous n’enregistrez pas de gestionnaire de récupération, la récupération automatique est désactivée et le serveur consigne un avertissement lors de son start.
Recovery works as follows:
- When recovery start : Each running attempt sends a heartbeat every few seconds. If the heartbeats stop, for example because the Worker crashes, restarts, or is replaced during a redeployment, the server detects the stale run within seconds and start a replacement attempt.
- When recovery doesn't start : si votre gestionnaire génère une exception, l'appel échoue et le serveur ne le relance pas. La récupération couvre les Worker interrompus, et non les erreurs dans le code de votre agent.
- Nombre de tentatives : le serveur ne limite pas le nombre de tentatives de récupération. Chaque tentative de remplacement augmente
context.attemptd’une unité. Pour s’arrêter après un certain nombre de tentatives, cochezcontext.attemptdans votre gestionnaire de récupération et générez une erreur. - Récupération manuelle : vous ne pouvez pas Trigger la récupération manuellement. Le renvoi d'une requête avec le même identifiant d'appel renvoie l'appel existant au lieu de lancer une nouvelle tentative.
La récupération peut exécuter le code de votre agent plus d'une fois pour la même invocation. Une tentative interrompue ayant peut-être déjà appelé des systèmes externes avant le start de la tentative de remplacement, veillez à rendre ces appels idempotents.
Bibliothèque AgentKit
DurableAgentServer fait partie de la bibliothèque AgentKit, databricks_agentkit, incluse dans le package databricks-agentbricks. Les projets que vous créez avec agentbricks init importent des éléments depuis celui-ci. La bibliothèque exporte les helpers suivants :
Exporter | Description |
|---|---|
| Le serveur d'agents et le contexte qu'il transmet à vos gestionnaires d'appel (invoke) et de récupération (recovery). |
| Un client pour la mémoire gérée et les stores de sessions. Il crée et obtient des stores, et expose les mémoires et les sessions des stores sous forme d'objets |
| Configurez le traçage MLflow pour l’agent et start une trace autour d’une unité de travail. |
| Create an authenticated Databricks SDK |
| Répertorie les services de modèle que l'agent peut appeler via Unity Gateway. |
La bibliothèque comprend également des assistants de framework dans databricks_agentkit.langgraph et databricks_agentkit.openai, que les Template générés utilisent pour connecter chaque framework au magasin de sessions. Pour les APIs de mémoire et de session, consultez Managed agent memory et Managed agent sessions.
Demander l’autorisation de l’utilisateur
Par default, les outils de votre agent s’exécutent avec les autorisations du Service Principal de l’application. Pour exécuter un outil avec les autorisations de l’utilisateur qui a envoyé la requête, déclarez l’autorisation utilisateur dans agent.toml:
-
Pour un outil géré, définissez
auth = "user"sur l’entrée de l’outil. Les commandesagentbricks tools addpour les serveurs MCP, les sandboxes et les Genie Agents écriventauth = "user"default. Passez--auth apppour utiliser l’identité de l’application à la place. -
Pour un outil que vous écrivez dans le code, déclarez l'exigence et tous les scopes API qu'Agent Bricks ne peut pas déduire :
Toml[auth.user]
required = true
additional_api_scopes = ["sql"]
Lorsqu'un agent nécessite une autorisation utilisateur, DurableAgentServer lit les identifiants de l'utilisateur dans les en-têtes de requête approuvés de Databricks Apps et les conserve en mémoire pour la tentative active uniquement. Le Runtime Store ne stocke pas les identifiants. Dans votre gestionnaire (handler), obtenez un client workspace pour l'utilisateur à partir de context.request_auth:
@app.invoke
async def invoke(input, context: InvocationContext) -> dict:
user_client = context.request_auth.client_for("user")
me = user_client.current_user.me()
return {"answer": f"Hello, {me.user_name}"}
client_for("app") renvoie un client qui utilise le Service Principal de l'application. Le résolveur se ferme lorsque la tentative se termine, alors appelez-le à l'intérieur du gestionnaire au lieu de stocker le client. Lorsque vous exécutez l'agent localement avec agentbricks dev, client_for("user") utilise vos identifiants locaux.
Lorsque vous effectuez un déploiement, agentbricks deploy demande les périmètres utilisateur Databricks Apps dont vos outils ont besoin. Pour ajouter des périmètres manquants à une application existante, passez --allow-user-scope-update. Consultez Configure authorization in a Databricks app.
Les invocations de type request-user utilisent les mêmes APIs synchrones, de streaming, en arrière-plan et de reconnexion. Comme le serveur ne stocke pas les identifiants de l’utilisateur, il ne peut pas récupérer une invocation request-user interrompue. La tentative de remplacement échoue avec l’erreur MCP_USER_AUTH_RECOVERY_UNSUPPORTED avant l’exécution de vos gestionnaires.
Ajouter des Endpoint personnalisés
DurableAgentServer est une application FastAPI. Ajoutez des routes parallèlement à l’API d’invocation de la même manière que vous les ajoutez à n’importe quelle application FastAPI :
@app.get("/status")
async def status() -> dict:
return {"ready": True}
Template de framework
agentbricks init génère deux répertoires :
agent/contient votre code de framework : le modèle, les invites et les outils.runtime/contient l’adaptateur qui connecte le framework àDurableAgentServer, ainsi que le point d’entrée qui enregistre les gestionnaires d’appel et de récupération de l’adaptateur.
L’adaptateur traduit chaque appel en un appel à la boucle d’agent du framework, et traduit le résultat du framework en événements et en un résultat. Les deux Template enregistrent un gestionnaire de récupération. Le template LangGraph reprend à partir de son dernier point de contrôle dans le magasin de sessions, et le template OpenAI Agents SDK réexécute la requête dans la même session. Pour intégrer un agent existant, ajoutez un adaptateur et un point d’entrée DurableAgentServer, et définissez server = "agentbricks" dans la section [agent] de agent.toml.
Limitations
- Vous ne pouvez pas modifier le serveur d'agents d'un déploiement existant. Pour basculer entre
DurableAgentServeret votre propre serveur, créez un nouveau projet avec l'optionagentbricks init --serverde votre choix et déployez-le sous un nouveau nom. - Modifier le champ
serverdansagent.tomlne convertit pas le code serveur existant enDurableAgentServer. - L’autorisation utilisateur nécessite
server = "agentbricks".