Comment concevoir des outils
Les trois mêmes outils, avec des noms et des descriptions vagues – le modèle ne choisit juste que 14 fois sur 30 ; décrits clairement, 30 sur 30. Comment écrire le nom, la description, les paramètres, la valeur de retour et les messages d'erreur d'un outil.
- Environ 35 minutes
- Niveau : Intermédiaire
- Testé : 2026-09-14 deepseek-flash
Le code et les sorties des programmes sont reproduits tels qu’ils ont tourné : commentaires et sorties sont donc en chinois.
L'efficacité d'un agent dépend en grande partie de ses outils. Le modèle ne voit que le nom, la description et la définition des paramètres d'un outil, pas votre code. Si la description est vague, le modèle doit deviner : que fait cet outil ? Quand l'utiliser ? Que mettre dans les paramètres ?
Cette leçon mesure d'abord par une expérience l'écart entre une bonne et une mauvaise description, puis explique concrètement comment l'écrire.
Expérience : description vague contre description claire
Les trois mêmes fonctions : chercher dans la documentation, lire un fichier de documentation, consulter le numéro de version sur PyPI. Deux jeux de descriptions.
Le jeu vague : les noms sont des verbes génériques, les descriptions tiennent en deux ou trois caractères :
VAGUE = [
fn("search", "搜索", q="内容"),
fn("read", "读取", x="要读的东西"),
fn("lookup", "查找信息", name="名字"),
]
Le jeu clair : les noms désignent l'objet de l'opération, les descriptions disent clairement ce que fait l'outil, quand l'utiliser et comment remplir les paramètres :
CLEAR = [
fn("search_docs", "在 httpx 官方文档里按英文关键词全文搜索,返回匹配的文件名和行号。"
"用户问 httpx 某个功能怎么用、某个参数是什么意思时,先用它。",
keyword="英文关键词,例如 timeout、proxy、follow_redirects"),
fn("read_doc", "读取 httpx 文档里某个文件的内容。通常在 search_docs 找到文件名之后使用。",
path="文档文件路径,例如 advanced/timeouts.md"),
fn("get_pypi_info", "查询某个 Python 包在 PyPI 上的最新版本号和发布信息。只在用户问版本号、是否已发布新版本时使用。",
package="PyPI 上的包名,例如 httpx"),
]
(fn est une petite fonction qui génère la description d'un outil ; code complet dans code/05-agents/tool_design.py.)
On prépare ensuite 10 questions, en notant pour chacune l'outil qui devrait être appelé à la première étape. Pour la question « 你好 » (bonjour), la bonne réponse est de n'appeler aucun outil. Chaque question est posée 3 fois avec chaque jeu de descriptions ; on regarde seulement quel outil le modèle choisit à la première étape, sans rien exécuter réellement :
QUESTIONS = [
("httpx 怎么设置代理?", "search_docs"),
("httpx 最新版本是多少?", "get_pypi_info"),
("帮我看看 advanced/ssl.md 里写了什么", "read_doc"),
("follow_redirects 参数是干什么的?", "search_docs"),
("requests 现在出到哪个版本了?", "get_pypi_info"),
("httpx 怎么上传文件?", "search_docs"),
("你好", None),
("把 quickstart.md 的内容给我看一下", "read_doc"),
("httpx 有没有发布 1.0 正式版?", "get_pypi_info"),
("httpx 的 event hooks 怎么用?", "search_docs"),
]
Résultat :
含糊的工具:14/30 次选对
httpx 怎么设置代理? 应该用 search_docs,实际 {'None': 2, 'search_docs': 1}
httpx 最新版本是多少? 应该用 get_pypi_info,实际 {'search_docs': 3}
帮我看看 advanced/ssl.md 里写了什么 应该用 read_doc,实际 {'read_doc': 2, 'get_pypi_info': 1}
follow_redirects 参数是干什么的? 应该用 search_docs,实际 {'search_docs': 1, 'None': 1, 'get_pypi_info': 1}
requests 现在出到哪个版本了? 应该用 get_pypi_info,实际 {'get_pypi_info': 1, 'search_docs': 2}
httpx 怎么上传文件? 应该用 search_docs,实际 {'None': 3}
httpx 有没有发布 1.0 正式版? 应该用 get_pypi_info,实际 {'search_docs': 3}
清楚的工具:30/30 次选对
Le même modèle, avec seulement des descriptions différentes : le taux de réussite passe de 47 % à 100 %.
Ce qui ne va pas dans les descriptions vagues
On ne sait pas sur quoi porte l'outil. « 搜索 » (chercher), mais où ? Sur le web, dans la documentation, dans le code ? Le modèle l'ignore. Pour « quelle est la dernière version de httpx ? », il a donc choisi search 3 fois sur 3, parce que « chercher » semble le plus général.
On ne sait pas quand l'utiliser. Pour « comment téléverser un fichier avec httpx ? », il n'a appelé aucun outil 3 fois sur 3 et a répondu directement de mémoire. Il ne savait pas que search pouvait l'aider à trouver une réponse plus fiable, et n'avait donc aucune raison de s'en servir.
Le nom ne correspond pas à la fonction. lookup sert en réalité à consulter la version sur PyPI, mais la description « rechercher des informations » ne se distingue ni de « lire » ni de « chercher », et le modèle choisit au hasard. Pour « à quoi sert le paramètre follow_redirects ? », 3 essais ont donné 3 résultats différents.
Les descriptions claires disent tout cela : on cherche dans la « documentation officielle de httpx », « quand l'utilisateur demande comment utiliser une fonction de httpx, utilise-le d'abord » ; l'outil de version ne s'utilise « que quand l'utilisateur demande un numéro de version ». Le modèle n'a pas besoin de deviner.
Le nom
- Désigner clairement l'objet de l'opération.
search_docsvaut mieux quesearch,get_pypi_infomieux quelookup. Avec beaucoup d'outils, les noms génériques entrent facilement en collision. - Commencer par un verbe, de façon cohérente.
get_,search_,read_,create_: une seule règle, appliquée partout. - Pas d'abréviations. Vous savez ce qu'est
gpi, le modèle non.
La description
Une bonne description répond à trois questions :
- Que fait-il ? « Recherche en texte intégral par mot-clé anglais dans la documentation officielle de httpx, renvoie les noms de fichiers et numéros de ligne correspondants. »
- Quand l'utiliser ? « Quand l'utilisateur demande comment utiliser une fonction de httpx, utilise-le d'abord. »
- Quand ne pas l'utiliser ? « Ne l'utiliser que quand l'utilisateur demande un numéro de version, ou si une nouvelle version est sortie. »
Le troisième point est particulièrement important quand des outils se confondent facilement. La description peut aussi indiquer comment les outils s'articulent, par exemple pour read_doc : « généralement utilisé après que search_docs a trouvé le nom du fichier » ; le modèle sait alors qu'il faut chercher d'abord, lire ensuite.
Les paramètres
- Décrire chaque paramètre, idéalement avec un exemple. « Mot-clé anglais, par exemple timeout, proxy, follow_redirects. » L'exemple indique le format au modèle et suggère aussi que « la documentation est en anglais, il faut chercher en anglais ».
- Le moins de paramètres possible. Avec sept ou huit paramètres, le modèle en oublie ou en remplit mal facilement. Donnez une valeur par défaut chaque fois que possible.
- Limiter les valeurs par des énumérations. Quand un paramètre ne peut prendre que quelques valeurs fixes, listez-les avec
enumdans le schéma (utilisé à la leçon 4 du module 02). - Des noms et des types explicites. Des noms comme
x,qounamevalent moins quepath,keywordoupackage.
La valeur de retour
La valeur renvoyée par un outil entre telle quelle dans le contexte, et chaque étape suivante la paie. Donc :
- Ne renvoyer que l'utile. Le
get_pypi_infode la leçon précédente ne retenait que quelques champs (numéro de version, résumé, version de Python requise), au lieu d'y mettre les dizaines de Ko de JSON brut renvoyés par PyPI. - Limiter la longueur. Le
grep_docsde la leçon précédente renvoie au plus 20 résultats,read_docau plus 80 lignes à la fois, et la boucle tronque en plus à 3000 caractères. - Faciliter l'étape suivante du modèle.
grep_docsrenvoie « fichier:ligne:contenu », et le modèle peut passer directement le fichier et la ligne àread_doc. - Dire clairement quand le résultat est vide. Renvoyer « rien trouvé pour pool timeout » plutôt qu'une chaîne vide. Une chaîne vide déroute le modèle : l'outil est-il cassé, ou n'y a-t-il vraiment rien ?
Les messages d'erreur
Les messages d'erreur sont écrits pour le modèle et doivent l'aider à se corriger :
错误:没有这个文件 advanced/timeout.md,请先用 list_docs 查看有哪些文件
Cette phrase dit trois choses : ce qui ne va pas, quel paramètre est en cause, et quoi faire ensuite. Le message Python par défaut FileNotFoundError: [Errno 2] No such file or directory, le modèle le comprend aussi, mais il ne sait pas quel outil appeler pour trouver le bon nom de fichier.
Quand les outils se multiplient
Plus il y a d'outils, plus le modèle a du mal à bien choisir, et plus les descriptions de chaque requête s'allongent. Quelques repères :
- Fusionner les outils aux fonctions proches. Si même vous ne savez pas expliquer la différence entre
search_docsetsearch_api_reference, fusionnez-les en un seul avec un paramètre pour les distinguer. - Regrouper par usage. Chaque tâche ne reçoit que les outils pertinents ; les agents multiples de la leçon 6 reprennent cette idée.
- Regarder la trace. Un outil souvent mal utilisé est un outil dont la description doit être modifiée.
Exercices
- Dans le jeu clair de
tool_design.py, supprimez de la description desearch_docsla phrase « quand l'utilisateur demande comment utiliser une fonction de httpx, utilise-le d'abord », et relancez. Le résultat de la question « comment téléverser un fichier avec httpx ? » change-t-il ? - Ajoutez aux deux jeux une fonction
list_docs, qui liste tous les fichiers de documentation. Dans le jeu vague, appelez-lalistavec la description « liste » ; dans le jeu clair, écrivez-la selon la méthode de cette leçon. Ajoutez deux questions pour la tester. - Prenez une fonction que vous avez déjà écrite, rédigez-lui une description d'outil selon la méthode de cette leçon, et faites-la appeler par le modèle.
Auto-test
1. À quelles questions une bonne description d'outil doit-elle répondre ?
Ce qu'il fait ; quand l'utiliser ; quand ne pas l'utiliser (surtout quand il se confond facilement avec d'autres outils). On peut ajouter comment il s'articule avec d'autres outils, par exemple « généralement utilisé après search_docs ».
2. Pourquoi la valeur de retour d'un outil doit-elle être aussi courte que possible ?
La valeur de retour entre telle quelle dans la liste de messages ; chaque étape suivante de l'agent l'emporte en appelant le modèle et la paie. Une valeur trop longue fait aussi perdre l'essentiel au modèle, voire remplit la fenêtre de contexte. Ne renvoyer que les champs utiles, avec une limite de longueur.
3. Comment écrire au mieux les messages d'erreur d'un outil ?
Pour le modèle : dire clairement ce qui ne va pas, où, et quoi faire ensuite. Par exemple « le fichier X n'existe pas, utilise d'abord list_docs pour voir quels fichiers existent ». Le modèle peut ainsi se corriger lui-même, au lieu de répéter la même erreur.
Questions et discussion
Bloqué sur cette leçon ? Posez votre question ici. Et si vous pouvez répondre à quelqu'un, n'hésitez pas.
Une question rapporte 3 points, une réponse 6. Les messages paraissent après vérification.
Chargement de la discussion…