Разработка ИИ-агентов · Модуль 2 · Урок 2.1
Проектирование инструментов: описания, схемы, гранулярность
Инструмент — это интерфейс для модели
Качество агента на 80% определяется качеством его инструментов. Инструмент — это не «функция», а интерфейс, который читает и использует модель. Если человек по сигнатуре и описанию понимает, что делает функция и когда её звать, то и модель поймёт. Если описание мутное — модель будет ошибаться, причём незаметно: вызывать инструмент не вовремя, передавать неверные аргументы, зацикливаться.
Поэтому инструменты проектируют как публичный API: продуманные имена, ясные описания, строгие типы. Разница между «работает иногда» и «работает надёжно» — обычно именно в формулировках схем, а не в модели.
Описание и схема
Хорошее описание отвечает на три вопроса: что инструмент делает, когда его применять и что он возвращает. Полезно добавлять короткий пример и явные ограничения («не используй для исторических данных»).
Параметры описываются в JSON Schema. Делайте их строгими: указывайте типы, помечайте обязательные поля в required, используйте enum для закрытых наборов значений (статусы, категории) — это резко снижает число невалидных вызовов. Каждое поле тоже снабжайте описанием: модель читает описания полей так же, как описание инструмента. Чем меньше у модели свободы выдумать аргумент, тем надёжнее агент.
Гранулярность: сколько инструментов и какого размера
Частая ошибка — либо один «универсальный» инструмент на всё, либо десятки почти одинаковых. Оба плохи.
- Слишком крупный инструмент (
do_everything(action, params)) перекладывает выбор действия внутрь аргументов — модель путается, а вы теряете типизацию. - Слишком мелкие инструменты (отдельная функция на каждое поле) раздувают список схем, забивают контекст и усложняют выбор.
Ориентир: один инструмент = одно понятное действие с предсказуемым результатом. Группируйте по смыслу, а не по технической реализации. Если двум инструментам всё время нужен один и тот же набор шагов — возможно, это один инструмент. Если один инструмент делает «то одно, то другое» в зависимости от флага — это, вероятно, два.
// ПЛОХО: размытое имя, нет описаний полей, свободная строка вместо enum.
bad := map[string]any{
"name": "orders",
"description": "работа с заказами",
"parameters": map[string]any{
"type": "object",
"properties": map[string]any{
"q": map[string]any{"type": "string"},
"status": map[string]any{"type": "string"}, // что сюда писать?
},
},
}
// ХОРОШО: глагол в имени, ясное описание «что/когда», enum и required.
good := map[string]any{
"name": "search_orders",
"description": "Ищет заказы пользователя по тексту и статусу. " +
"Используй, когда спрашивают про конкретные заказы или их состояние.",
"parameters": map[string]any{
"type": "object",
"properties": map[string]any{
"query": map[string]any{
"type": "string",
"description": "Поисковый текст: номер заказа или товар.",
},
"status": map[string]any{
"type": "string",
"enum": []string{"new", "paid", "shipped", "cancelled"},
"description": "Фильтр по статусу заказа.",
},
},
"required": []string{"query"},
},
}Anti-patterns
| Анти-паттерн | Почему плохо | Как правильно |
|---|---|---|
| Описание-заглушка («работа с X») | Модель не понимает, когда звать инструмент | Описать что/когда/что возвращает, добавить пример |
Свободная строка вместо enum | Модель шлёт произвольные значения | Закрытые наборы — через enum; обязательные — в required |
Один инструмент do_everything(action) | Выбор действия уходит в аргументы, теряется типизация | Один инструмент = одно понятное действие |
| Десятки почти одинаковых инструментов | Раздувают контекст, усложняют выбор | Группировать по смыслу; объединять близкие действия |
Практическое задание
- Возьмите инструмент из капстоуна Модуля 1 и перепишите его описание по схеме «что / когда / что возвращает».
- Добавьте
enumхотя бы для одного параметра и пометьте обязательные поля вrequired. - Снабдите описанием каждое поле параметров, а не только сам инструмент.
- Проверьте на 3–4 запросах, что модель стала точнее выбирать инструмент и аргументы.
- Найдите в своём наборе два инструмента-кандидата на объединение (или один — на разделение) и обоснуйте.
Проверка знаний
Зачем для параметра-статуса использовать enum вместо обычной строки?
Верный ответ: B
B верно. enum сообщает модели допустимые значения, и она не выдумывает посторонние статусы. Это одно из самых действенных средств надёжности схем. A несущественно; C и D неверны.
В агенте есть инструмент manage(action, payload), где action — это "create"/"update"/"delete", а payload — произвольный JSON.
Что не так с такой гранулярностью?
Верный ответ: B
B верно. «Универсальный» инструмент перекладывает выбор действия в строковый аргумент и лишает каждое действие своей строгой схемы. Чаще правильнее create_item / update_item / delete_item с типизированными параметрами.
Кто основной «читатель» описания инструмента?
Верный ответ: B
B верно. Описание — часть промпта; по нему модель принимает решение о вызове. Поэтому его пишут для модели, как для пользователя API.