Aller au contenu principal

API Supervisor (Bêta)

info

Bêta

Cette fonctionnalité est en Bêta. Les administrateurs du Workspace peuvent activer cette fonctionnalité depuis la page Aperçus . Consultez Gérer les aperçus Databricks.

L’API Supervisor simplifie la création d’agents personnalisés sur Databricks avec la prise en charge du mode d’arrière-plan pour les tâches de longue durée. Vous définissez le modèle, les outils et les instructions dans une seule requête à un endpoint compatible OpenResponses(POST ai-gateway/mlflow/v1/responses), et Databricks exécute la boucle d'agent pour vous : en appelant le modèle de manière répétée, en sélectionnant et en exécutant des outils, et en synthétisant une réponse finale.

Il existe trois approches pour créer un agent d'appel d'outils personnalisé sur Databricks :

  • Agent Bricks Supervisor Agent (recommandé) : entièrement déclaratif avec optimisation par feedback humain pour une qualité optimale.
  • API de supervision : Créez un agent personnalisé par programme – choisissez les modèles au Runtime, contrôlez les outils à utiliser par requête, ou itérez pendant le développement. C'est également le bon choix lorsque vous avez besoin de contrôler le choix du modèle tout en déchargeant la gestion de la boucle de l'agent à Databricks.
  • APIs unifiées ou natives d'AI Gateway : Écrivez votre propre boucle d'agent. Databricks fournit uniquement la couche d'inférence LLM. Utilisez les APIs unifiées lorsque cela est possible pour permettre le changement de modèles, ou les APIs natives spécifiques au fournisseur (/openai, /anthropic, /gemini) lors du portage de code existant vers Databricks ou de l'utilisation de fonctionnalités spécifiques au fournisseur.

Exigences

Étape 1 : Créer un appel LLM à tour unique

Start par un appel de base sans outils. Le client DatabricksOpenAI configure automatiquement l’URL de base et l’authentification pour votre Workspace :

Python
from databricks_openai import DatabricksOpenAI

client = DatabricksOpenAI(use_ai_gateway=True)

response = client.responses.create(
model="databricks-claude-sonnet-4-5",
input=[{"type": "message", "role": "user", "content": "Tell me about Databricks"}],
stream=False
)

print(response.output_text)

Étape 2 : Ajoutez des outils hébergés pour exécuter la boucle de l'agent

Lorsque vous incluez des outils dans la demande, Databricks gère une boucle multi-tours en votre nom : le modèle décide quels outils appeler, Databricks les exécute, renvoie les résultats au modèle et se répète jusqu'à ce que le modèle produise une réponse finale.

Python
response = client.responses.create(
model="databricks-claude-sonnet-4-5",
input=[{"type": "message", "role": "user", "content": "Summarize recent customer reviews and flag any urgent issues."}],
tools=[
{
"type": "genie_space",
"name": "Customer reviews",
"description": "Answers customer review questions using SQL",
"genie_space": {"space_id": "<genie-space-id>"}
},
{
"type": "dashboard",
"name": "Customer reviews dashboard",
"description": "Answers questions about the customer reviews dashboard",
"dashboard": {"dashboard_id": "<dashboard-id>"}
},
{
"type": "uc_function",
"name": "Flag urgent review",
"description": "Flags a review as requiring urgent attention",
"uc_function": {"name": "<catalog>.<schema>.<function_name>"}
},
{
"type": "table",
"table": {
"name": "<catalog>.<schema>.<table_name>",
"description": "Reads from the customer reviews table"
}
},
{
"type": "vector_search_index",
"vector_search_index": {
"name": "<catalog>.<schema>.<index_name>",
"description": "Searches the product documentation index for relevant passages"
}
},
{
"type": "knowledge_assistant",
"name": "Internal docs",
"description": "Answers questions from internal documentation",
"knowledge_assistant": {"knowledge_assistant_id": "<knowledge-assistant-id>"}
},
{
"type": "serving_endpoint",
"name": "Custom agent",
"description": "Calls a custom agent served from a Databricks model serving endpoint",
"serving_endpoint": {"name": "<serving-endpoint-name>"}
},
{
"type": "vector_search_index",
"name": "Product docs",
"description": "Looks up product documentation by semantic search",
"vector_search_index": {
"name": "<catalog>.<schema>.<index>",
"columns": ["title", "content"]
}
},
{
"type": "app",
"name": "Support agent",
"description": "Custom application endpoint",
"app": {"name": "<app-name>"}
},
{
"type": "uc_connection",
"name": "GitHub",
"description": "Searches GitHub for issues and pull requests",
"uc_connection": {"name": "<uc-connection-name>"}
},
{
"type": "uc_mcp",
"name": "Slack",
"description": "Searches and reads from the team Slack workspace",
"uc_mcp": {"name": "<catalog>.<schema>.<mcp_service>"}
},
{
"type": "databricks_web_search",
"name": "Web search",
"description": "Searches the public web for current information and returns a synthesized answer with citations",
"web_search": {}
},
{
"type": "volume",
"volume": {
"name": "<catalog>.<schema>.<volume>",
"description": "Searches files in a Unity Catalog volume"
}
},
],
stream=True
)

for event in response:
print(event)

Étape 3 (Facultatif) : connectez-vous à des services tiers avec des connexions gérées par le système

Databricks fournit des connexions gérées par le système pour des services tiers populaires tels que Google Drive, GitHub, Atlassian, SharePoint et Glean. Ces connexions sont une alternative rapide à la configuration de votre propre serveur MCP externe — vous pouvez toujours utiliser le type d'outil uc_connection pour vous connecter à tout serveur MCP externe que vous avez configuré vous-même.

Les connexions gérées par le système nécessitent l'activation de la version bêta des connecteurs tiers pour les agents dans votre workspace. Voir Gérer les aperçus Databricks.

Les connecteurs suivants sont pris en charge :

Connecteur

Description

system_ai_agent_google_drive

Rechercher et lire des fichiers depuis Google Drive.

system_ai_agent_github_mcp

Accédez aux repositories GitHub, aux problèmes et aux pull requests.

system_ai_agent_atlassian_mcp

Recherchez et gérez les ressources Atlassian (Jira, Confluence).

system_ai_agent_sharepoint

Rechercher et lire les fichiers depuis SharePoint.

system_ai_agent_glean_mcp

Rechercher dans le contenu d'entreprise indexé par Glean.

Connecteur

Description

system_ai_agent_google_drive

Rechercher et lire des fichiers depuis Google Drive.

system_ai_agent_github_mcp

Accédez aux repositories GitHub, aux problèmes et aux pull requests.

system_ai_agent_atlassian_mcp

Recherchez et gérez les ressources Atlassian (Jira, Confluence).

system_ai_agent_sharepoint

Rechercher et lire les fichiers depuis SharePoint.

system_ai_agent_glean_mcp

Rechercher dans le contenu d'entreprise indexé par Glean.

Transmettez un connecteur dans le tableau tools à l'aide du type d'outil uc_connection avec le champ name défini sur le nom du connecteur :

Python
response = client.responses.create(
model="databricks-claude-sonnet-4-5",
input=[{"type": "message", "role": "user", "content": "List my open GitHub pull requests."}],
tools=[
{
"type": "uc_connection",
"uc_connection": {
"name": "system_ai_agent_github_mcp"
}
}
],
)

Authentification utilisateur-machine (U2M)

Chaque utilisateur s'authentifie individuellement. Les jetons OAuth ne sont pas partagés entre les utilisateurs. Lors de la première requête utilisant un connecteur pour lequel l’utilisateur n’est pas authentifié, la réponse se termine par status: "failed" et une erreur oauth contenant une URL de connexion :

JSON
{
"status": "failed",
"error": {
"code": "oauth",
"message": "Failed request to <connector>. Please login first at <login-url>."
}
}

Ouvrez l'URL dans un navigateur, terminez le flux OAuth, puis réexécutez la même requête.

Étape 4 (Facultatif) : Ajouter un outil de fonction côté client

Utilisez les outils function lorsque vous souhaitez que votre application exécute une logique personnalisée à côté des outils hébergés par Databricks. Déclarez un outil de fonction avec type: "function", un name, un description facultatif et un objet Schéma JSON parameters :

Python
response = client.responses.create(
model="databricks-claude-sonnet-4-5",
input=[{"type": "message", "role": "user", "content": "<user prompt>"}],
tools=[
{
"type": "function",
"name": "<client-side-function-name>",
"description": "<description of what this function does>",
"parameters": {
"type": "object",
"properties": {"<param-name>": {"type": "string"}},
"required": ["<param-names>"],
"additionalProperties": False,
},
}
],
)

L'API Supervisor ne stocke pas l'état de la conversation entre les requêtes, de sorte qu'un appel de fonction côté client prend deux tours :

  1. Tour 1. Le modèle renvoie un élément function_call (par exemple, « call get_weather with location=Paris») au lieu d’une réponse finale.
  2. **Votre code** exécute la fonction localement et produit un résultat.
  3. **Tour 2.** Appelez responses.create() à nouveau, en transmettant l'entrée originale plus le du modèle function_call plus un nouveau function_call_output avec votre résultat. Le modèle utilise le résultat pour produire la réponse finale.

Exemple d'outil de fonction côté client

Python
import json
from databricks_openai import DatabricksOpenAI

client = DatabricksOpenAI(use_ai_gateway=True)
MODEL = "databricks-claude-sonnet-4-5"

GET_WEATHER = {
"type": "function",
"name": "get_weather",
"description": "Get the current weather for a location.",
"parameters": {
"type": "object",
"properties": {"location": {"type": "string"}},
"required": ["location"],
"additionalProperties": False,
},
}

def run_get_weather(args):
return json.dumps({
"location": args["location"],
"temp_c": 18,
"condition": "sunny",
})

CLIENT_TOOLS = {"get_weather": run_get_weather}
TOOLS = [GET_WEATHER]

input_list = [{"role": "user", "content": "What's the weather in Paris?"}]

# Turn 1 — model emits a function_call
resp = client.responses.create(model=MODEL, input=input_list, tools=TOOLS)

# Echo the model's turn into history, then execute pending client function_calls
input_list += [item.model_dump() for item in resp.output]
for item in resp.output:
if item.type == "function_call" and item.name in CLIENT_TOOLS:
args = json.loads(item.arguments)
# Execute the client-side function with the model's arguments
# and append the result so the model can use it on the next turn.
tool_output = CLIENT_TOOLS[item.name](args)
input_list.append({
"type": "function_call_output",
"call_id": item.call_id,
"output": tool_output,
})

# Turn 2 — model produces the final answer using the tool result
final = client.responses.create(model=MODEL, input=input_list, tools=TOOLS)
print(final.output_text)

Pour plus de modèles (streaming, outils clients hébergés, approbation MCP, dépannage), consultez la compétence d'appel de fonction côté client de l'API Supervisor.

Étape 5 : activer le traçage

Transmettez un trace_destination dans le corps de la requête pour envoyer des traces de la boucle de l’agent aux tables Unity Catalog. Chaque requête génère une trace capturant la séquence complète des appels de modèle et des exécutions d'outils. Si vous ne définissez pas trace_destination, aucune trace n’est écrite. Pour les détails de configuration, consultez Stocker les traces OpenTelemetry dans Unity Catalog.

À l'aide du client Python databricks-openai, transmettez-le via extra_body:

Python
response = client.responses.create(
model="databricks-claude-sonnet-4-5",
input=[{"type": "message", "role": "user", "content": "Tell me about Databricks"}],
tools=[...],
extra_body={
&quot;trace_destination&quot;: {
&quot;catalog_name&quot;: &quot;&lt;catalog&gt;&quot;,
&quot;schema_name&quot;: &quot;&lt;schema&gt;&quot;,
&quot;table_prefix&quot;: &quot;&lt;table-prefix&gt;&quot;
}
}
)

Pour également renvoyer la trace directement dans la réponse de l'API, passez "databricks_options": {"return_trace": True} dans extra_body.

Vous pouvez également utiliser le traçage distribué MLflow pour combiner les traces de votre code d'application et de la boucle d'agent de l'API Supervisor en une seule trace de bout en bout. Propager les en-têtes de contexte de trace en utilisant le champ extra_headers :

Python
import mlflow
from mlflow.tracing import get_tracing_context_headers_for_http_request

with mlflow.start_span("client-root") as root_span:
root_span.set_inputs({"input": "Tell me about Databricks"})

trace_headers = get_tracing_context_headers_for_http_request()

response = client.responses.create(
model="databricks-claude-sonnet-4-5",
input=[{"type": "message", "role": "user", "content": "Tell me about Databricks"}],
tools=[...],
extra_body={
&quot;trace_destination&quot;: {
&quot;catalog_name&quot;: &quot;&lt;catalog&gt;&quot;,
&quot;schema_name&quot;: &quot;&lt;schema&gt;&quot;,
&quot;table_prefix&quot;: &quot;&lt;table-prefix&gt;&quot;
}
},
extra_headers=trace_headers,
)

Mode d'arrière-plan

Le mode d'arrière-plan vous permet d'exécuter des workflows d'agent longs qui impliquent plusieurs appels d'outil et un raisonnement complexe sans attendre qu'ils se terminent de manière synchrone. Soumettez votre requête avec background=True, recevez immédiatement un ID de réponse, et interrogez le résultat lorsqu'il est prêt. Ceci est particulièrement utile pour les agents qui interrogent plusieurs sources de données ou qui enchaînent plusieurs outils dans une seule requête.

Créer une requête en arrière-plan

Python
response = client.responses.create(
model="databricks-claude-sonnet-4-5",
input=[{"type": "message", "role": "user", "content": "Tell me about Databricks"}],
tools=[...],
background=True,
)

print(response.id) # Use this ID to poll for the result
print(response.status) # "queued" or "in_progress"

Obtenir le résultat

Utilisez responses.retrieve() pour vérifier l'état jusqu'à ce qu'il atteigne un état final :

Python
from time import sleep

while response.status in {"queued", "in_progress"}:
sleep(2)
response = client.responses.retrieve(response.id)

print(response.output_text)

Mode d'arrière-plan avec MCP

Pour des raisons de sécurité, l'API Supervisor requiert l'approbation explicite de l'utilisateur avant d'exécuter tout appel d'outil MCP en mode arrière-plan. Lorsque la boucle de l'agent sélectionne un outil MCP, la réponse se termine par un mcp_approval_request. Vous pouvez examiner le nom de l'outil, le libellé du serveur et les arguments que le modèle a l'intention de transmettre :

JSON
{
"type": "mcp_approval_request",
"id": "<tool-call-id>",
"arguments": "{\"query\": \"what is Databricks\", \"count\": 5}",
"name": "you-search",
"server_label": "<server-label>",
"status": "completed"
}

Pour approuver l'appel d'outil et poursuivre la boucle de l'agent, transmettez un mcp_approval_response dans le champ input avec l'historique complet de la conversation :

JSON
{
"type": "mcp_approval_response",
"id": "<tool-call-id>",
"approval_request_id": "<tool-call-id>",
"approve": true
}
remarque

Les réponses du mode d'arrière-plan sont conservées dans la base de données pendant un maximum de 30 jours.

Outils pris en charge

Vous définissez les outils dans le tableau tools de votre requête. Chaque objet outil partage trois champs de niveau supérieur :

  • type (chaîne, obligatoire) : le discriminant qui sélectionne le type d'outil.
  • name (chaîne de caractères, facultatif) : Nom d'affichage présenté au modèle.
  • description (chaîne, facultatif) : Indication au modèle sur le moment d'appeler cet outil.

De plus, chaque objet outil contient un objet de configuration imbriqué dont la clé correspond à la valeur type. Le tableau ci-dessous documente la configuration imbriquée pour chaque type d'outil pris en charge.

Type d'outil

Exemple

Portée

genie_space

JSON
{
"type": "genie_space",
"name": "Customer reviews",
"genie_space": {
"space_id": "<id>"
}
}

genie

dashboard

JSON
{
"type": "dashboard",
"name": "Sales dashboard",
"dashboard": {
"dashboard_id": "<id>"
}
}

dashboards

uc_function

JSON
{
"type": "uc_function",
"name": "Flag urgent review",
"uc_function": {
"name": "<catalog>.<schema>.<function>"
}
}

unity-catalog

table

JSON
{
"type": "table",
"name": "Customer reviews",
"table": {
"name": "<catalog>.<schema>.<table_name>"
}
}

unity-catalog

knowledge_assistant

JSON
{
"type": "knowledge_assistant",
"name": "Internal docs",
"knowledge_assistant": {
"knowledge_assistant_id": "<id>"
}
}

model-serving

serving_endpoint

JSON
{
"type": "serving_endpoint",
"name": "Custom agent",
"serving_endpoint": {
"name": "<endpoint-name>"
}
}

model-serving

databricks_web_search

JSON
{
"type": "databricks_web_search",
"name": "Web search",
"web_search": {}
}

model-serving

vector_search_index

JSON
{
"type": "vector_search_index",
"name": "Product docs",
"vector_search_index": {
"name": "<catalog>.<schema>.<index>",
"columns": ["title", "content"]
}
}

vector-search

volume

JSON
{
"type": "volume",
"volume": {
"name": "<catalog>.<schema>.<volume>",
"description": "Searches files in a Unity Catalog volume"
}
}

unity-catalog

app

JSON
{
"type": "app",
"name": "Support agent",
"app": {
"name": "<app-name>"
}
}

apps

uc_connection

JSON
{
"type": "uc_connection",
"name": "GitHub",
"uc_connection": {
"name": "system_ai_agent_github_mcp"
}
}

unity-catalog

uc_mcp

JSON
{
"type": "uc_mcp",
"name": "Slack",
"uc_mcp": {
"name": "<catalog>.<schema>.<mcp_service>"
}
}

ai-gateway

function

JSON
{
"type": "function",
"name": "get_weather",
"description": "Get the current weather for a location.",
"parameters": {
"type": "object",
"properties": { "location": { "type": "string" } },
"required": ["location"]
}
}

Aucun

Type d'outil

Exemple

Portée

genie_space

JSON
{
"type": "genie_space",
"name": "Customer reviews",
"genie_space": {
"space_id": "<id>"
}
}

genie

dashboard

JSON
{
"type": "dashboard",
"name": "Sales dashboard",
"dashboard": {
"dashboard_id": "<id>"
}
}

dashboards

uc_function

JSON
{
"type": "uc_function",
"name": "Flag urgent review",
"uc_function": {
"name": "<catalog>.<schema>.<function>"
}
}

unity-catalog

table

JSON
{
"type": "table",
"name": "Customer reviews",
"table": {
"name": "<catalog>.<schema>.<table_name>"
}
}

unity-catalog

knowledge_assistant

JSON
{
"type": "knowledge_assistant",
"name": "Internal docs",
"knowledge_assistant": {
"knowledge_assistant_id": "<id>"
}
}

model-serving

serving_endpoint

JSON
{
"type": "serving_endpoint",
"name": "Custom agent",
"serving_endpoint": {
"name": "<endpoint-name>"
}
}

model-serving

databricks_web_search

JSON
{
"type": "databricks_web_search",
"name": "Web search",
"web_search": {}
}

model-serving

vector_search_index

JSON
{
"type": "vector_search_index",
"name": "Product docs",
"vector_search_index": {
"name": "<catalog>.<schema>.<index>",
"columns": ["title", "content"]
}
}

vector-search

volume

JSON
{
"type": "volume",
"volume": {
"name": "<catalog>.<schema>.<volume>",
"description": "Searches files in a Unity Catalog volume"
}
}

unity-catalog

app

JSON
{
"type": "app",
"name": "Support agent",
"app": {
"name": "<app-name>"
}
}

apps

uc_connection

JSON
{
"type": "uc_connection",
"name": "GitHub",
"uc_connection": {
"name": "system_ai_agent_github_mcp"
}
}

unity-catalog

uc_mcp

JSON
{
"type": "uc_mcp",
"name": "Slack",
"uc_mcp": {
"name": "<catalog>.<schema>.<mcp_service>"
}
}

ai-gateway

function

JSON
{
"type": "function",
"name": "get_weather",
"description": "Get the current weather for a location.",
"parameters": {
"type": "object",
"properties": { "location": { "type": "string" } },
"required": ["location"]
}
}

Aucun

Pour serving_endpoint, seuls les Endpoint ResponseAgent, ChatCompletions et ChatAgent sont pris en charge.

Pour app, seules les applications MCP (avec le préfixe « mcp- ») et les applications ResponseAgent personnalisées (avec le préfixe « agent- ») sont prises en charge.

Pour uc_connection, utilisez le nom de connexion que vous avez créé pour un serveur MCP externe, ou un connecteur géré par le système system_ai_agent_* (voir Étape 3 (Facultatif) : Se connecter à des services tiers avec des connexions gérées par le système). Les serveurs MCP personnalisés sur les Applications ne sont pas pris en charge.

Exécution de code

Lorsqu'une requête nécessite un calcul, le superviseur exécute le code généré par le modèle dans une session de compute Serverless en sandbox pour analyser les données, transformer les fichiers ou effectuer des calculs. Il prend en charge les commandes Python (default), SQL et shell. Le superviseur écrit et exécute le code lui-même si nécessaire, vous n'avez donc pas besoin d'activer, de configurer ou de fournir le code.

L'exécution du code s'exécute dans un sandbox verrouillé avec :

  • Pas d'accès Internet. Il bloque toutes les sorties réseau sortantes, quelle que soit la politique réseau de votre workspace, de sorte que le code s'exécutant dans le sandbox ne peut pas atteindre les endpoints externes.
  • Accès Databricks limité uniquement. Il n'a pas son propre accès aux données. Il peut lire les tables Unity Catalog que vous déclarez avec l'outil table dans la même requête.

Paramètres pris en charge

Chaque requête à l'API Supervisor accepte les parameters suivants.

  • model: l'un des modèles pris en charge suivants. Modifiez ce champ pour changer de fournisseurs sans modifier le reste de votre code.

  • GPT-5 (databricks-gpt-5)

  • GPT-5.1 (databricks-gpt-5-1)

  • GPT-5.2 (databricks-gpt-5-2)

  • GPT-5.4 (databricks-gpt-5-4)

  • input: les messages de conversation à envoyer.

  • tools: définitions d'outils hébergés (genie_space, dashboard, uc_function, table, knowledge_assistant, serving_endpoint, databricks_web_search, vector_search_index, volume, app, uc_connection, uc_mcp) et outils de fonction côté client (function). Voir Étape 4 (facultatif) : ajouter un outil de fonction côté client.

  • instructions: une invite système pour guider le comportement du superviseur.

  • stream: défini à true pour stream les réponses.

  • background: défini sur true pour exécuter la requête de manière asynchrone. Renvoie un ID de réponse que vous interrogez avec responses.retrieve(). Consultez le mode arrière-plan.

  • trace_destination: objet facultatif avec les champs catalog_name, schema_name et table_prefix. Si défini, l'API Supervisor écrit une trace de la boucle complète de l'agent dans les tables Unity Catalog spécifiées. Transmettez via extra_body dans le client Python.

L'API ne prend pas en charge les parameters d'inférence tels que temperature. Le serveur les gère en interne.

Autorisation

L'API Supervisor exécute la boucle de l'agent avec les informations d'identification de l'appelant, de sorte que les outils qu'elle invoque respectent les permissions Unity Catalog de l'appelant. Lorsque vous appelez l'API directement, le client DatabricksOpenAI s'authentifie en tant que vous.

Lorsque vous appelez l'API Supervisor à partir d'une application Databricks, vous pouvez exécuter des outils soit en tant que service principal Databricks de l'application (autorisation d'application), soit en tant qu'utilisateur demandeur (autorisation utilisateur). Pour l'autorisation d'application, accordez au service principal Databricks de l'application des autorisations sur chaque outil. Pour l'autorisation utilisateur, transmettez le jeton de l'utilisateur au client DatabricksOpenAI et ajoutez les étendues d'autorisation utilisateur requises. Consultez Exécuter des outils en tant qu'utilisateur demandeur.

Limitations

L'API Supervisor présente les limitations suivantes :

  • **Durée d'exécution en mode arrière-plan** : Les demandes en mode arrière-plan ont une durée d'exécution maximale de 30 minutes.

  • **Streaming en mode arrière-plan** : stream et background ne peuvent pas tous deux être true dans la même requête.

  • Exécution durable : la récupération automatique après des défaillances ou des interruptions avec des garanties d'exécution exacte pour la boucle d'agent n'est pas prise en charge.

  • Modèle de recherche web : L'outil databricks_web_search s'exécute sur l'API de modèle de fondation databricks-gpt-5 hébergée par Databricks, quelle que soit la model que vous définissez pour le superviseur. Le workspace doit avoir databricks-gpt-5 disponible dans sa liste d'autorisation system.ai de modèles.

  • Éligibilité du workspace de recherche Web : L'outil databricks_web_search n'est pas disponible dans les cas suivants. Les requêtes qui incluent databricks_web_search provenant de workspaces inéligibles sont rejetées.

Ressources supplémentaires