Набор навыков для работы с AI-агентами
Разбор репозитория mattpocock/skills: практические инструкции и системный подход к проектированию навыков для автономных AI-агентов.
Суть концепции навыков для агентов
Почему стандартных промптов недостаточно
Когда мы говорим об автономных агентах, возникает соблазн решить любую задачу через один длинный системный промпт. Мы пытаемся впихнуть в контекстное окно и инструкции по поведению, и правила форматирования, и описание инструментов, и примеры работы. С практической точки зрения это путь к нестабильности.
Проблема в том, что чем больше инструкций вы даёте модели в одном блоке, тем ниже её предсказуемость. В LLM (Large Language Models) это работает так же, как в перегруженном конфигурационном файле: чем больше условий, тем выше вероятность, что агент проигнорирует критически важную деталь или начнет галлюцинировать, пытаясь совместить несовместимое.
Если мы посмотрим на подход, описанный в репозитории mattpocock/skills, то увидим переход от «промпт-инжиниринга» к «инженерии навыков». Вместо того чтобы учить агента всему сразу, мы разбиваем его компетенции на атомарные, изолированные модули.
Это напоминает работу с микросервисами в инфраструктуре. Вместо одного монолитного приложения, которое делает всё — от обработки запросов до бэкапов — мы создаём набор специализированных сервисов. Если один сервис падает или работает некорректно, это не обрушивает всю систему, а лишь ограничивает конкретную функцию. В случае с агентами это означает, что навык «чтение логов» не будет конфликтовать с навыком «написание кода», потому что они живут в разных контекстах.
Структура директории .agents
Системный подход требует порядка в файловой системе. Репозиторий предлагает использовать директорию .agents как единый источник истины для всех компетенций агента. Это позволяет декларативно описывать, что агент умеет делать, не смешивая логику управления с логикой выполнения задач.
Типичная структура выглядит следующим образом:
text.agents/ ├── search/ │ ├── description.md # Описание того, что делает этот навык │ └── schema.json # Описание интерфейса (аргументы, типы данных) ├── filesystem/ │ ├── read_file.md │ └── write_file.md └── database/ └── query_sql.json
Каждый навык — это не просто текст, а связка из описания и технического контракта.
Во-первых, файл description.md служит для семантического поиска. Когда агент получает задачу, он сначала сканирует доступные описания, чтобы понять, какой инструмент ему подходит. Здесь важно писать максимально конкретно, избегая общих фраз. Вместо «помогает с файлами» нужно писать «предоставляет доступ к чтению содержимого текстовых файлов в директории проекта».
Во-вторых, schema.json обеспечивает техническую предсказуемость. Это то, что позволяет агенту правильно сформировать вызов функции (function calling). Если мы настраиваем агентную среду, нам важно, чтобы входные параметры были строго типизированы.
Пример упрощенного JSON-контракта для навыка поиска в файловой системе:
json{
"name": "search_files",
"description": "Ищет файлы по расширению и ключевому слову в названии",
"parameters": {
"type": "object",
"properties": {
"extension": {
"type": "string",
"description": "Расширение файла, например 'py' или 'yaml'"
},
"keyword": {
"type": "string",
"description": "Часть имени файла для поиска"
}
},
"required": ["extension", "keyword"]
}
}
Такая структура позволяет масштабировать возможности агента простым добавлением новых папок в .agents. Вы просто копируете шаблон, описываете новый инструмент и добавляете его в реестр. Это делает систему расширяемой и, что самое важное, поддающейся аудиту: вы всегда видите, какие именно «суперсилы» есть у вашего агента и как они ограничены.
Применение навыков в инженерных задачах
Автоматизация рутинных процессов
Когда мы говорим об AI-агентах, важно не путать их с простыми чат-ботами. Бот отвечает на вопросы, а агент выполняет работу. С практической точки зрения, проектирование навыков (skills) — это создание набора инструментов, которые позволяют модели взаимодействовать с операционной системой или API.
В инженерных задачах это чаще всего касается рутины, которая съедает время: сбор логов, проверка состояния сервисов или подготовка отчётов. Вместо того чтобы писать огромные промпты, описывающие, как проверить статус Docker-контейнера, лучше дать агенту чёткий навык с ограниченным набором команд. Это повышает предсказуемость: агент не будет пытаться «гадать», что происходит, а выполнит конкретную функцию.
Например, можно создать навык для анализа состояния системы. Если мы используем подход из репозитория mattpocock/skills, то навык должен представлять собой атомарную операцию. Рассмотрим пример того, как агент может использовать навык для диагностики упавшего сервиса через systemd.
Сначала агент должен иметь доступ к инструменту проверки статуса. Мы можем описать это как функцию, которая принимает имя юнита и возвращает последние 20 строк лога:
bash# Пример команды, которую агент вызывает через свой навык
journalctl -u nginx.service -n 20 --no-pager
Если мы проектируем среду для агента, важно ограничить его возможности. Я не рекомендую давать агенту прямой доступ к sudo без ограничений. Правильнее создать специализированного пользователя с правами на выполнение только конкретных скриптов.
Для автоматизации проверки дискового пространства можно подготовить скрипт, который агент будет запускать как часть своего цикла самодиагностики:
bash#!/bin/bash
# Скрипт для проверки критического порога заполнения диска
# Агент вызывает его, если замечает замедление работы системы
THRESHOLD=90
CURRENT_USAGE=$(df / | tail -1 | awk '{print $5}' | sed 's/%//')
if [ "$CURRENT_USAGE" -gt "$THRESHOLD" ]; then
echo "CRITICAL: Disk usage is at ${CURRENT_USAGE}%"
exit 1
else
echo "OK: Disk usage is at ${CURRENT_USAGE}%"
exit 0
fi
Интеграция с существующими инструментами
Проблема многих «умных» решений в том, что они существуют в вакууме. Настоящая ценность агента появляется тогда, когда он встраивается в уже готовую инфраструктуру. Если у вас развёрнут стек на базе Docker и мониторинг в Prometheus, агент должен уметь обращаться к их API, а не пытаться имитировать их работу.
Интеграция навыков — это, по сути, создание моста между LLM и вашим текущим инструментарием. Если мы возьмём типичный сценарий управления контейнерами, то агент не должен просто «знать» про Docker. Он должен обладать навыком выполнения запросов к Docker Socket или использовать CLI.
С точки зрения архитектуры, лучше всего реализовать это через небольшие API-обёртки или CLI-утилиты. Рассмотрим, как агент может взаимодействовать с Docker Compose для перезапуска окружения после обнаружения ошибки в конфигурации.
Вместо того чтобы позволять агенту редактировать файлы напрямую (что чревато поломкой всей системы), мы даём ему навык «валидация и перезапуск».
Сначала агент выполняет проверку синтаксиса:
bash# Проверка конфигурации перед применением изменений
docker compose config
Если команда вернула ошибку, агент анализирует вывод и исправляет конкретную строку в файле, после чего снова запускает проверку. Только после успешного прохождения config он выполняет:
bash# Применение изменений
docker compose up -d
Такой подход обеспечивает ту самую предсказуемость, о которой я говорил ранее. Мы не доверяем агенту управление всей системой, мы даём ему набор инструментов, которые работают по строго определённым правилам.
При интеграции с системами мониторинга, например, с Grafana, навык может заключаться в запросе к API для получения метрик за определённый период. Это позволяет агенту не просто констатировать факт «сервер тормозит», а приводить конкретные цифры: «За последние 15 минут потребление CPU выросло с 10% до 85%».
Для реализации этого можно использовать простой curl запрос, который агент будет упаковывать в свой навык:
bash# Пример запроса метрики из Prometheus API
curl -G 'http://localhost:9090/api/v1/query' \
--data-urlencode 'query=rate(node_cpu_seconds_total{mode="idle"}[5m])'
Интеграция должна строиться по принципу минимальных привилегий: агент получает доступ только к тем данным и тем командам, которые необходимы для выполнения его текущей задачи.
Методология создания предсказуемых инструкций
Методология создания предсказуемых инструкций
Когда мы говорим об автономных агентах, главная проблема — это их склонность к галлюцинациям и непредсказуемому поведению при малейшем отклонении от сценария. В репозитории mattpocock/skills заложена идея, что навык (skill) — это не просто текстовое описание задачи, а строго структурированный протокол.
С системной точки зрения, проектирование навыка похоже на написание документации для API или создание unit-тестов: агент должен точно понимать границы своей ответственности. Если инструкция размыта, вы получите «черный ящик», который выдаёт разные результаты на одни и те же входные данные. Чтобы добиться предсказуемости, нужно работать в двух направлениях: как мы подаём данные и как мы учим агента реагировать на неудачи.
Форматирование и контекст
Агенты работают с контекстным окном, и чем больше в нём «мусора», тем выше вероятность ошибки. Если вы даёте агенту слишком длинную и неструктурированную инструкцию, он начинает игнорировать детали в середине текста.
С практической точки зрения, я рекомендую использовать четкое разделение ролей и структурных блоков. Вместо сплошного текста используйте Markdown-разметку. Это помогает модели визуально (на уровне токенов) отделить описание задачи от примеров и ограничений.
Хорошо структурированный навык должен включать:
- Role (Роль) — кто агент в рамках этого навыка.
- Objective (Цель) — конечный результат.
- Constraints (Ограничения) — что делать категорически нельзя.
- Input/Output Schema (Схема данных) — формат входных и выходных данных.
Пример качественного описания навыка для работы с файловой системой в домашней лаборатории:
markdown## Skill: File System Auditor
### Role
You are a Linux System Administrator specializing in filesystem integrity.
### Objective
Analyze the provided directory structure and identify files with insecure permissions.
### Constraints
- DO NOT suggest deleting files.
- DO NOT attempt to change permissions (chmod) directly.
- ONLY report findings in JSON format.
### Input Schema
- `path`: string (absolute path to the directory)
- `depth`: integer (recursion depth)
### Output Schema
```json
{
"findings": [
{
"file": "string",
"issue": "string",
"current_perms": "string"
}
]
}
Такой подход гарантирует, что агент не начнёт «самодеятельность» вроде автоматического исправления прав доступа, что в реальной инфраструктуре может привести к поломке сервисов. Мы ограничиваем его область действия, делая поведение предсказуемым.
### Обработка ошибок и граничных случаев
Самая большая ошибка при проектировании агентов — это ожидание, что всё всегда будет работать по идеальному сценарию. В реальности API отваливаются, диски переполняются, а права доступа внезапно меняются. Если в инструкции не прописано, что делать при ошибке, агент либо зависнет в бесконечном цикле попыток, либо выдаст галлюцинацию, утверждая, что «всё прошло успешно».
В методологии [mattpocock/skills](https://github.com/mattpocock/skills) важно внедрять блоки обработки исключений прямо в описание навыка. Вы должны явно указать агенту, как интерпретировать ошибки и какие действия предпринять.
Разделите сценарии на три типа:
1. **Expected Error (Ожидаемая ошибка)** — например, файл не найден. Агент должен просто сообщить об этом в структурированном виде.
2. **Boundary Case (Граничный случай)** — например, запрос слишком велик. Агент должен предложить уменьшить масштаб задачи.
3. **Critical Failure (Критический сбой)** — например, потеря доступа к сетевому хранилищу. Агент должен немедленно прекратить выполнение и запросить вмешательство человека.
Пример инструкции для обработки ошибок при работе с Docker-контейнерами:
```markdown
### Error Handling Protocols
#### Scenario: Container Not Found
If the command `docker ps -a --filter "name=..."` returns an empty list:
1. Do not assume the container was deleted.
2. Check if the Docker daemon is responsive.
3. Return error: `{"status": "error", "code": "NOT_FOUND", "message": "Container name does not exist"}`.
#### Scenario: Permission Denied
If the output contains `Error response from daemon: permission denied`:
1. Stop all subsequent commands in this sequence.
2. Return error: `{"status": "error", "code": "AUTH_FAILURE", "message": "Insufficient privileges to access Docker socket"}`.
Если мы посмотрим на это с точки зрения системного инженера, мы увидим знакомый паттерн: мы не просто описываем «счастливый путь» (happy path), а проектируем систему, устойчивую к отказам. Только так можно построить автономную систему, которая не превратит ваш домашний сервер в хаос при первом же сетевом лаге.
Практическое использование репозитория
Адаптация навыков под свои задачи
Когда вы открываете репозиторий mattpocock/skills, важно понимать: это не готовые скрипты, которые можно просто скопировать и запустить. Это методология. Если вы попытаетесь скормить агенту навык «как есть», не учитывая специфику вашей инфраструктуры, вы получите не предсказуемое поведение, а галлюцинации и хаос.
С практической точки зрения адаптация заключается в том, чтобы превратить абстрактную инструкцию в конкретный набор инструментов, доступных агенту. Если навык подразумевает работу с файловой системой или API, вы должны ограничить область видимости агента.
Во-первых, определите контекст. Если агент должен управлять вашим домашним сервером, не давайте ему доступ ко всей системе. Вместо этого создайте изолированную директорию или специализированного пользователя.
Во-вторых, перепишите описание навыка (description) так, чтобы оно соответствовало вашим именам сущностей. Если в примере используется database_query, а у вас в инфраструктуре всё завязано на postgres_cluster, меняйте терминологию. Агент опирается на семантику: чем точнее описание, тем меньше шансов, что он выберет не тот инструмент.
Пример того, как может выглядеть адаптированный JSON-конфиг навыка для управления конкретным сервисом в Docker:
json{
"skill_name": "docker_service_monitor",
"description": "Проверяет статус контейнера в конкретной docker-сети и анализирует последние 10 строк логов",
"parameters": {
"container_name": "string",
"network_name": "string"
},
"execution_logic": "docker logs --tail 10 {{container_name}} | grep 'ERROR'"
}
Здесь мы ушли от общего «управления Docker» к узкой, предсказуемой задаче. Это и есть системный подход: давать агенту не «молоток», а «инструмент для забивания конкретного гвоздя».
Тестирование и отладка поведения
Проектирование навыков без этапа тестирования — это создание системы, которая упадет в самый неподходящий момент. В отличие от обычного кода, где мы проверяем вход и выход, здесь мы проверяем логику рассуждений (reasoning).
Я всегда использую подход, схожий с отладкой системных служб через journald: мне нужно видеть не только результат, но и весь путь, который прошел агент к этому результату.
Для тестирования нового навыка я рекомендую создать тестовый сценарий в изолированной среде (например, в отдельном Docker-контейнере или на виртуальной машине в Proxmox). Процесс отладки стоит разделить на три этапа:
- Проверка синтаксиса и параметров. Убедитесь, что агент правильно извлекает аргументы из запроса. Если вы просите «проверь статус веб-сервера», агент должен понять, что
web-server— это параметрcontainer_name. - Проверка границ (Edge Cases). Что сделает агент, если команда вернет ошибку? Если
docker logsвыдастNo such container, агент должен уметь обработать это сообщение, а не пытаться интерпретировать пустой вывод как «всё в порядке». - Анализ цепочки рассуждений (Chain of Thought). Если ваш фреймворк позволяет, смотрите на логи рассуждений. Если агент делает лишние шаги — например, сначала запрашивает список всех контейнеров, чтобы найти один нужный, — значит, описание навыка недостаточно конкретное.
Для автоматизации этого процесса можно использовать простой bash-скрипт, который прогоняет набор запросов через API вашего агента и сравнивает ожидаемый вывод с реальным.
bash#!/bin/bash
# Простейший тест для проверки навыка работы с логами
TEST_CONTAINER="test_service_container"
echo "Запуск теста навыка: проверка логов..."
# Имитируем запрос агента к API
RESPONSE=$(curl -s -X POST http://agent-api/run \
-d "{\"skill\": \"docker_service_monitor\", \"container_name\": \"$TEST_CONTAINER\"}")
# Проверяем, содержит ли ответ ожидаемую структуру
if echo "$RESPONSE" | grep -q "status"; then
echo "Тест пройден: ответ получен в корректном формате."
else
echo "Ошибка: формат ответа не соответствует спецификации."
echo "Ответ агента: $RESPONSE"
exit 1
fi
Если вы видите, что агент постоянно ошибается в одном и том же месте, не пытайтесь «дожать» его более сложными промптами. Вернитесь на шаг назад и пересмотрите структуру самого навыка. Предсказуемость системы напрямую зависит от того, насколько жестко вы ограничили пространство её действий.
Заключение
Итоги и системный подход
Разбор репозитория mattpocock/skills показывает, что проектирование навыков для AI-агентов — это не столько про написание промптов, сколько про инженерную дисциплину. Если мы хотим получить предсказуемое поведение системы, мы должны относиться к навыку как к программному модулю: с четким интерфейсом, ограниченной областью ответственности и понятными входными данными.
С практической точки зрения, работа с агентами переходит из плоскости «попроси нейросеть сделать что-то» в плоскость «предоставь агенту набор инструментов, которые он может использовать безопасно и эффективно».
Как избежать хаоса при масштабировании
Когда вы начинаете добавлять новые навыки, возникает риск превратить агента в «черный ящик», который делает что угодно, но не всегда то, что нужно. Чтобы этого избежать, я рекомендую придерживаться трёх принципов:
- Атомарность. Один навык — одна задача. Не пытайтесь создать функцию
manage_server, которая и обновляет пакеты, и чистит логи, и перезапускает сервисы. Лучше иметь три отдельных инструмента:update_packages,clean_logsиrestart_service. - Строгая типизация. Если агент вызывает инструмент через JSON-RPC или аналогичный протокол, описание параметров должно быть максимально конкретным. Вместо
path: stringпишитеpath: absolute path to the configuration file (e.g., /etc/nginx/nginx.conf). - Логирование и аудит. Каждый вызов навыка должен оставлять след. В домашней лаборатории это может быть простой лог-файл, но в серьезных проектах это должен быть структурированный поток данных, который можно проанализировать через Loki или ELK.
Если вы проектируете систему управления через агента, ваш конфиг описания навыка (например, в формате OpenAPI или кастомного JSON) должен выглядеть примерно так:
json{
"skill_name": "check_service_status",
"description": "Проверяет, запущен ли конкретный системный сервис через systemd.",
"parameters": {
"service_name": {
"type": "string",
"description": "Имя юнита systemd, например, 'nginx' или 'docker'.",
"pattern": "^[a-zA-Z0-9._-]+$"
}
},
"expected_output": "Статус сервиса: active/inactive/failed"
}
Когда подход перестанет работать
Системное проектирование навыков отлично работает на задачах автоматизации рутины, но у него есть предел.
Во-первых, при резком увеличении количества доступных инструментов (context window saturation) агент начинает «путаться» в них. Если у вас в распоряжении 100+ мелких навыков, точность выбора нужного инструмента падает. В этом случае нужно внедрять иерархическую структуру: основной агент управляет «суперагентами», у каждого из которых свой узкий набор навыков.
Во-вторых, безопасность. Любой навык, который имеет доступ к записи в файловую систему или выполнению команд, — это потенциальная дыра. Если вы даёте агенту инструмент execute_shell_command, вы фактически передаёте ему root-права. В таких случаях лучше ограничивать возможности через sudoers или запускать агента в изолированном контейнере с ограниченными привилегиями.
Предсказуемость системы напрямую зависит от того, насколько жестко вы ограничили её возможности на этапе проектирования.
FAQ
Как добавить новый навык в систему?
Процесс добавления навыка в методологии, описанной в репозитории mattpocock/skills, больше напоминает разработку микросервиса, чем простое написание текста. Вам нужно не просто дать инструкцию, а определить границы ответственности и инструменты, которые агент сможет использовать.
Во-первых, опишите саму задачу: что именно должен сделать агент. Во-вторых, предоставьте контекст и ограничения. Если навык подразумевает работу с файловой системой или API, это должно быть четко зафиксировано.
С практической точки зрения, структура нового навыка в формате YAML может выглядеть так:
yamlskill:
name: file_analyzer
description: Анализирует содержимое лог-файлов на наличие ошибок
tools:
- grep
- awk
parameters:
path: string # Путь к файлу
pattern: string # Регулярное выражение для поиска
steps:
- "Прочитать файл по указанному пути"
- "Применить паттерн для поиска строк"
- "Сгруппировать результаты по типу ошибки"
В чем отличие навыка от обычного промпта?
Разница заключается в предсказуемости и атомарности. Обычный промпт — это попытка направить мысли модели в нужное русло. Это часто приводит к галлюцинациям, потому что модель пытается «угадать» логику выполнения.
Навык же — это жестко структурированная единица работы. Если промпт — это совет «постарайся писать код аккуратно», то навык — это четкий алгоритм: «возьми этот файл, выполни линтинг через eslint, если есть ошибки — исправь их согласно правилам из .eslintrc».
С точки зрения архитектуры, навык превращает LLM из «собеседника» в «диспетчера», который вызывает конкретные функции. Это обеспечивает ту самую предсказуемость, которая критически важна, когда вы строите автономную систему.
Какие инструменты нужны для запуска?
Для полноценной работы с такими навыками вам понадобится среда, которая умеет исполнять код или вызывать внешние API по команде агента. Одного чат-интерфейса в браузере будет недостаточно.
Вам необходимы:
- Оркестратор (например, LangChain, CrewAI или собственный скрипт на Python), который будет интерпретировать инструкции навыка.
- Runtime-среда: контейнер (Docker) или изолированная песочница, где агент сможет безопасно выполнять команды.
- Интерфейс взаимодействия: API, через которое агент будет получать доступ к инструментам.
Если вы хотите протестировать концепцию на своей домашней лаборатории, проще всего развернуть Docker-контейнер с Python и установленным SDK нужной библиотеки:
bash# Создаем изолированную среду для экспериментов с агентом
docker run -it --name ai-agent-sandbox python:3.11-slim /bin/bash
Можно ли использовать эти навыки локально?
Да, это вполне реально, если использовать локальные модели (LLM), запущенные на вашем оборудовании. Для этого лучше всего подходят инструменты вроде Ollama или LocalAI.
Однако стоит учитывать один нюанс: для качественного исполнения сложных навыков требуется высокая способность модели к рассуждению (reasoning). Маленькие модели (на 7–8 млрд параметров) могут путаться в многошаговых инструкциях и неверно интерпретировать параметры.
Если вы планируете использовать навыки локально, я рекомендую запускать модели семейства Llama 3 или Mistral через Docker, чтобы обеспечить изоляцию процесса:
yaml# Пример docker-compose.yml для запуска локальной модели
services:
ollama:
image: ollama/ollama
container_name: ollama-server
volumes:
- ./ollama_data:/root/.ollama
ports:
- "11434:11434"
При таком подходе вы получаете полный контроль над данными и не зависите от внешних API, что важно для конфиденциальных задач.
Часто задаваемые вопросы
Чем инженерия навыков отличается от обычного промпт-инжиниринга?
Если промпт-инжиниринг — это попытка объяснить модели все правила игры в одном сообщении, то инженерия навыков — это создание набора специализированных инструментов. Мы переходим от написания длинных инструкций к проектированию изолированных модулей, которые агент вызывает только тогда, когда это необходимо. С практической точки зрения это повышает предсказуемость системы: агент не тратит контекстное окно на инструкции, которые не относятся к текущей подзадаче.
Можно ли использовать этот подход для простых чат-ботов?
С технической стороны — да, но целесообразность зависит от сложности задач. Если ваш бот просто отвечает на вопросы по FAQ, дробление логики на навыки создаст избыточную сложность и увеличит задержку (latency) из-за лишних вызовов модели. Однако, как только функционал бота выходит за рамки простого диалога и требует взаимодействия с внешними API или файловой системой, переход к модульной структуре становится необходимым.
Как масштабировать количество навыков, чтобы не запутаться в них?
Для поддержания порядка стоит использовать принципы, схожие с управлением конфигурациями в инфраструктуре: четкая иерархия папок и строгая типизация описаний. Рекомендую группировать навыки по доменам ответственности, например, выделив отдельные директории для работы с данными, сетевыми запросами или системными командами. Это позволит вам легко проводить аудит компетенций агента и обновлять конкретный модуль, не затрагивая работу всей системы.
Влияет ли разделение на навыки на стоимость использования API?
Разделение навыков помогает оптимизировать расходы за счёт более эффективного управления контекстным окном. Вместо того чтобы отправлять в каждом запросе огромный системный промпт со всеми возможными инструкциями, вы передаёте только те описания инструментов, которые нужны для текущего шага. Это снижает количество потребляемых токенов, хотя и требует более сложной логики управления состоянием на стороне приложения.