Набор навыков для работы с AI-агентами
Разбор репозитория mattpocock/skills: как структурировать инструкции и навыки для автономных агентов, чтобы повысить предсказуемость их работы.
Суть подхода к навыкам агентов
Почему стандартных промптов недостаточно
Когда мы начинаем работать с автономными агентами, первая интуитивная реакция — попытаться впихнуть всё описание логики в один огромный системный промпт. Это напоминает попытку настроить сложный сервис через одну гигантскую переменную окружения: вроде бы всё внутри, но управлять этим невозможно.
С практической точки зрения, у такого подхода есть три критических проблемы:
- Потеря фокуса. Чем длиннее промпт, тем выше вероятность, что модель начнет игнорировать инструкции в середине текста. В LLM это называют «lost in the middle». Если агент должен одновременно знать, как работать с API, как форматировать JSON и как соблюдать корпоративный стиль, он неизбежно начнет ошибаться в одном из этих аспектов.
- Отсутствие предсказуемости. Длинные инструкции создают избыточность. Модель может начать интерпретировать двусмысленные части промпта по-разному при каждом новом запуске. Для автоматизации это недопустимо — нам нужна детерминированность, насколько это вообще возможно в мире вероятностных моделей.
- Сложность тестирования. Если вы измените одно предложение в промпте на 2000 токенов, вы не сможете точно сказать, как это повлияло на другие части логики. Вы не можете протестировать «модуль форматирования» отдельно от «модуля принятия решений».
Если мы посмотрим на архитектуру классических программных систем, то поймём, что решение всегда лежит в разделении ответственности. Агенту не нужен «монолитный промпт», ему нужен набор узкоспециализированных инструментов и четких инструкций.
Концепция .agents directory
Подход, который предлагает Мэтт Покок в репозитории mattpocock/skills, заключается в переходе от «написания промптов» к «проектированию навыков». Вместо одного файла мы создаём структуру, где каждый навык — это отдельный, атомарный компонент.
В основе лежит идея директории .agents. Это своего рода «библиотека навыков», где каждый файл описывает конкретную способность агента. Это очень похоже на то, как мы используем Docker-образы: вместо того чтобы собирать всё в один тяжелый контейнер, мы запускаем специализированные сервисы, которые взаимодействуют друг с другом.
Структура может выглядеть следующим образом:
textmy-agent-project/ ├── .agents/ │ ├── file_manager.md # Навык работы с файловой системой │ ├── sql_executor.md # Навык выполнения запросов к БД │ └── web_searcher.md # Навык поиска информации в сети ├── main_agent.py # Основной цикл управления └── config.yaml # Конфигурация доступных инструментов
Каждый файл в .agents — это не просто текст, а структурированный манифест. Он должен содержать:
- Name: Четкое название навыка.
- Description: Описание того, когда и зачем агент должен использовать этот навык (это критически важно для этапа планирования).
- Instructions: Пошаговый алгоритм выполнения.
- Input/Output schema: Строгое описание входных данных и ожидаемого результата.
Пример содержимого файла .agents/sql_executor.md:
markdown# Skill: SQL Executor
## Description
Используй этот навык, когда пользователю нужно получить данные из PostgreSQL или изменить состояние записей в базе данных.
## Instructions
1. Сначала проанализируй запрос пользователя и определи необходимые таблицы.
2. Сформируй SQL-запрос, соблюдая правила безопасности (никаких DROP или TRUNCATE).
3. Выполни запрос через предоставленный инструмент `db_query`.
4. Если запрос вернул ошибку, проанализируй текст ошибки и попробуй исправить синтаксис.
## Input Schema
{
"query": "string (valid SQL statement)",
"database": "string (default: 'production')"
}
## Output Schema
{
"status": "success | error",
"data": "array | null",
"error_message": "string | null"
}
Такой подход превращает разработку агентов в инженерную дисциплину. Мы можем брать один навык, тестировать его на граничных значениях, фиксировать результат и только потом подключать к основному агенту. Это и даёт ту самую предсказуемость, которая отличает работающий инструмент от игрушки.
Структурирование навыков для инженера
Структурирование навыков для инженера
Когда мы переходим от простых чат-ботов к автономным агентам, характер работы меняется. Если обычный LLM-чат — это собеседник, то агент — это исполнитель, который должен взаимодействовать с вашей инфраструктурой. В репозитории mattpocock/skills заложена важная идея: агент не должен «просто знать», как работать. Он должен обладать набором чётко определённых навыков, которые можно измерить и протестировать.
С практической точки зрения, работа с агентами напоминает проектирование микросервисов. Вы не можете просто скормить модели огромный текстовый файл с описанием всей вашей сети. Вам нужно разбить логику на мелкие, предсказуемые компоненты.
Атомарность и модульность инструкций
Главная ошибка при создании агентов — попытка описать слишком широкий процесс в одной инструкции. Если вы дадите агенту задачу «настрой мониторинг», он либо запутается в бесконечных вариантах, либо сделает что-то непредсказуемое.
Я придерживаюсь принципа атомарности: один навык — одна конкретная задача. Вместо одного гигантского промпта лучше подготовить библиотеку маленьких инструкций. Это делает систему предсказуемой. Если агент ошибается, вы точно знаете, какой именно модуль нужно подправить, не ломая при этом всю остальную логику.
Представьте, что мы настраиваем агента для работы с Docker. Вместо инструкции «управляй контейнерами», мы разбиваем её на модули:
- Skill: Container Status Check — только чтение состояния.
- Skill: Container Restart — только перезапуск конкретного ID.
- Skill: Log Retrieval — только сбор логов.
В формате конфигурации (например, если вы используете JSON-подобную структуру для описания инструментов агенту) это выглядит примерно так:
json{
"skill_name": "docker_container_restart",
"description": "Перезапускает конкретный контейнер по его имени или ID.",
"parameters": {
"container_id": "string (required)"
},
"expected_outcome": "Статус контейнера меняется на 'restarting', затем 'running'."
}
Такой подход позволяет вам тестировать каждый навык отдельно. Вы можете прогнать unit-тесты на агенте, проверяя, что при команде на перезапуск он вызывает именно нужную функцию, а не пытается удалить образ.
Связь навыков с конкретными инструментами
Навык без инструмента — это просто теоретическое знание. Для автономного агента навык обретает смысл только тогда, когда он жестко привязан к конкретному интерфейсу управления: CLI, API или скрипту.
Если мы говорим о домашней лаборатории, то агент должен взаимодействовать с вашими сервисами через проверенные интерфейсы. Например, вместо того чтобы просить агента «посмотреть, что с дисками», мы даём ему навык, который вызывает команду df -h или обращается к API TrueNAS.
С точки зрения инженера, важно, чтобы описание навыка включало в себя не только «что делать», но и «как это делать технически». Это минимизирует галлюцинации. Если агент знает, что для проверки состояния SSH-сервиса нужно выполнить команду через systemctl, он не будет пытаться искать этот сервис в сетевых сканерах.
Пример описания навыка для работы с системными службами:
yamlskill: check_service_status
tool: systemd_cli
command: "systemctl is-active {service_name}"
description: |
Проверяет, запущен ли сервис в системе.
Возвращает 'active' или 'inactive'.
Используйте этот навык перед тем, как пытаться перезапустить службу.
Здесь мы видим три важных элемента:
- Чёткий инструмент:
systemd_cli. - Конкретная команда: с использованием плейсхолдера
{service_name}. - Контекстная подсказка: указание, что проверку нужно делать до перезапуска.
Такая связка превращает абстрактный интеллект в надёжный инструмент управления. Чем меньше свободы у агента в выборе способа выполнения задачи, тем выше стабильность всей вашей системы.
Практическое применение навыков
Интеграция в рабочий процесс разработки
Когда мы переходим от простых чат-ботов к автономным агентам, подход к написанию инструкций меняется. Если раньше мы просто просили модель «напиши код», то теперь мы должны проектировать систему навыков. С практической точки зрения, это напоминает переход от написания скриптов на Bash к созданию полноценных модулей в системном программировании: каждый навык должен иметь чёткую область ответственности и понятный интерфейс.
Репозиторий mattpocock/skills предлагает структурировать возможности агента не как свалку промптов, а как набор атомарных операций. В рабочем процессе это означает, что вместо одного огромного системного промпта вы создаёте библиотеку навыков, которые агент вызывает по мере необходимости.
Если мы посмотрим на процесс деплоя через CI/CD, агент не должен «пытаться» настроить сервер. Он должен использовать навык deploy_service, который принимает на вход параметры и возвращает стандартизированный JSON.
Пример того, как может выглядеть описание навыка в конфигурационном файле агента (например, для систем, использующих YAML-based определения):
yamlskills:
- name: check_service_status
description: Проверяет состояние конкретного юнита в systemd
parameters:
service_name:
type: string
description: Имя юнита, например, nginx.service
expected_output:
status: string # active, inactive, failed
uptime: string
error_handling:
on_failure: "Если сервис не найден, используй навык list_all_units"
Такая структура позволяет агенту не гадать, что делать, если команда вернула ошибку. Мы заранее определяем логику перехода, что делает поведение системы гораздо более управляемым.
Обеспечение предсказуемости результата
Главная проблема автономных систем — это их склонность к «галлюцинациям» в логике выполнения. В моей практике системного инженера предсказуемость всегда достигалась через строгие ограничения и валидацию. С AI-агентами работает тот же принцип.
Чтобы агент не превратил вашу инфраструктуру в хаос, навыки должны работать в связке с инструментами валидации. Я рекомендую использовать подход, где каждый навык завершается проверкой состояния (assertion). Если агент выполнил действие, он обязан подтвердить его результат через отдельный инструмент.
Во-первых, используйте схематизацию вывода. Агент должен возвращать данные в строго определённом формате, чтобы следующий шаг в цепочке (pipeline) мог их обработать без ошибок парсинга.
Во-вторых, внедряйте промежуточное логирование каждого шага. Если агент использует навык для изменения конфигурации Nginx, лог должен содержать не только результат, но и diff изменений.
Пример реализации проверки после выполнения навыка в рамках автоматизированного сценария:
bash# Агент выполнил навык изменения конфига.
# Теперь запускаем автоматическую проверку синтаксиса,
# чтобы обеспечить предсказуемость состояния системы.
nginx -t > /tmp/nginx_check.log 2>&1
if [ $? -eq 0 ]; then
echo "Конфигурация валидна. Перехожу к перезагрузке."
systemctl reload nginx
else
echo "Ошибка в конфигурации. Откат изменений..."
# Здесь агент должен вызвать навык rollback_config
cat /tmp/nginx_check.log
exit 1
fi
С точки зрения архитектуры, предсказуемость — это не отсутствие ошибок, а возможность системы точно определить, в каком состоянии она находится после каждой операции. Если навык modify_config не может гарантировать, что система останется работоспособной, этот навык должен быть пересмотрен и разбит на более мелкие, безопасные подзадачи.
Оценка эффективности системы
Критерии качества навыков
Когда мы переходим от простых чат-ботов к автономным агентам, фокус смещается с качества генерации текста на качество выполнения задач. Если агент — это исполнитель, то навыки (skills) — это его инструментарий. Чтобы этот инструментарий не превратился в бесполезный набор скриптов, я использую три критерия оценки, которые помогают добиться предсказуемости.
Во-первых, это атомарность. Навык должен решать одну конкретную задачу. Если вы попытаетесь запихнуть в один инструмент и поиск по базе данных, и отправку уведомления в Slack, агент неизбежно запутается в логике обработки ошибок. Хороший навык — это как хорошо написанная функция в коде: входные данные, преобразование, выходные данные.
Во-вторых, детерминизм. Насколько результат выполнения навыка предсказуем при одних и тех же входных параметрах? Если агент вызывает инструмент для получения погоды, он должен получать структурированный JSON, а не художественное описание облачности.
В-третьих, самодокументированность. Агент «читает» описание вашего навыка, чтобы понять, когда его использовать. Если описание функции в JSON-схеме будет размытым, агент применит её не вовремя.
С практической точки зрения, качественный навык в репозитории mattpocock/skills описывается через четкую структуру. Рассмотрим пример описания навыка для проверки состояния сервиса в домашней лаборатории:
json{
"name": "check_service_status",
"description": "Проверяет, запущен ли конкретный системный сервис через systemd. Используйте этот навык, если нужно подтвердить работоспособность приложения.",
"parameters": {
"type": "object",
"properties": {
"service_name": {
"type": "string",
"description": "Точное имя сервиса, например: nginx, docker или plex"
}
},
"required": ["service_name"]
}
}
Здесь описание description — это не просто комментарий для человека, это инструкция для LLM. Чем конкретнее вы укажете, в каких случаях вызывать check_service_status, тем меньше вероятность, что агент начнет проверять статус сервиса там, где нужно просто прочитать лог.
Типичные ошибки при настройке
В моей практике я часто вижу, как инженеры пытаются построить сложные системы, забывая о базовой гигиене конфигурации. Это приводит к тому, что агенты начинают «галлюцинировать» действиями или зацикливаются.
Самая частая ошибка — избыточная сложность интерфейса. Если навык требует на вход десять параметров, вероятность того, что агент правильно их скомбинирует, падает экспоненциально. Если задача требует многоступенчатой подготовки данных, лучше разбить её на цепочку из трёх простых навыков, чем пытаться сделать один «швейцарский нож».
Вторая проблема — отсутствие обработки ошибок в описании. Агент должен знать, что делать, если инструмент вернул ошибку. Если ваш скрипт падает с exit code 1, агент может решить, что он всё сделал правильно, или, наоборот, впасть в панику.
Пример плохого подхода — попытка дать агенту прямой доступ к shell без ограничений:
bash# ОПАСНО: Агент может выполнить любой произвольный код
python3 agent_executor.py --run-command "rm -rf /"
Вместо этого я всегда рекомендую использовать обёртки. Если агенту нужно управлять Docker-контейнерами, создайте узкоспециализированный навык, который принимает только разрешённые команды.
Также стоит упомянуть ошибку «размытых описаний». Если у вас есть два навыка: get_data и fetch_info, агент почти наверняка будет использовать их хаотично. В системном подходе каждое действие должно иметь уникальный семантический профиль.
Если мы посмотрим на структуру типичного рабочего процесса, то увидим, что предсказуемость достигается за счёт жестких границ:
- Вход: Строгая JSON-схема.
- Процесс: Выполнение изолированного скрипта или API-вызова.
- Выход: Стандартизированный ответ (успех/ошибка + данные).
Только при соблюдении этого цикла можно построить систему, которая не требует постоянного присмотра со стороны администратора.
Часто задаваемые вопросы
Нужно ли переписывать все существующие промпты под этот подход?
Не обязательно переписывать всё сразу, но стоит начать с самых критичных узлов. Если вы видите, что агент начинает «галлюцинировать» или игнорировать часть инструкций при усложнении задачи, это верный признак того, что пора выделять логику в отдельные навыки. С практической точки зрения, лучше внедрять модульный подход постепенно, превращая монолитные инструкции в набор инструментов.
Как понять, что конкретную инструкцию пора выносить в отдельный навык?
Главным критерием служит предсказуемость и сложность тестирования. Если вы не можете проверить корректность работы функции (например, парсинга JSON) отдельно от логики принятия решений, значит, эта функция должна стать самостоятельным навыком. Если изменение одного абзаца в промпте ломает поведение агента в совершенно другой области, пора разделять ответственности.
Повлияет ли использование множества мелких навыков на стоимость работы агента?
Да, использование большого количества навыков может увеличить расход токенов, так как агенту нужно передавать описания этих инструментов для выбора. Однако этот расход стоит рассматривать как инвестицию в надёжность системы. В долгосрочной перспективе вы экономите ресурсы за счёт того, что агент совершает меньше ошибок и не требует бесконечных циклов переделывания задачи.
Можно ли использовать этот подход для простых чат-ботов?
Для простых диалоговых систем, которые просто отвечают на вопросы, этот метод может оказаться избыточным. Но если ваша задача выходит за рамки простого общения и требует взаимодействия с внешними API, базами данных или файловой системой, модульный подход становится необходимым. Разделение логики на навыки превращает чат-бота из «собеседника» в полноценный инструмент автоматизации.