Навыки для AI-агентов: как проектировать и внедрять в реальных системах
Я — Денис Шохирев, архитектор AI из Эрлангена, управляю DennisCraft AI Studio и внедряю продакшн-агентов для клиентов B2B в DACH. Последние полгода — 14 агентов на стеке Claude, Supabase, n8n, Doppler, self-hosted Postgres. Одна из главных боли — как реализовать расширение навыков агента так, чтобы это не сломалось в проде после первого регресса. Что такое навык агента на практике В продакшн-системах навык — это не просто абстрактная “функция”, а конкретная связка: входные параметры → валидац
Я — Денис Шохирев, архитектор AI из Эрлангена, управляю DennisCraft AI Studio и внедряю продакшн-агентов для клиентов B2B в DACH. Последние полгода — 14 агентов на стеке Claude, Supabase, n8n, Doppler, self-hosted Postgres. Одна из главных боли — как реализовать расширение навыков агента так, чтобы это не сломалось в проде после первого регресса.
Что такое навык агента на практике
В продакшн-системах навык — это не просто абстрактная “функция”, а конкретная связка: входные параметры → валидация → вызов внешнего действия (API, базу, сервис) → структурированный выход. Например, навык “создать инвойс” — это не вызов LLM, а проверка входных данных, запись в Postgres, отправка через API, логирование результата. Главная проблема — стабильность и предсказуемость поведения навыка в условиях частых изменений API, схем и бизнес-логики.
Дизайн навыков: шаблон «Skill as Function»
Почему не «Prompt as Skill»
В демо на конференциях часто видишь: новый навык = новый prompt. В продакшне это не работает. Пример: на трех последних внедрениях агенты с навыками на голых промптах регулярно генерировали некорректные SQL-запросы (типичные ошибки: SQL-инъекции, неверные JOIN’ы). Решение — каждый навык оформлять как отдельную функцию с четкой схемой входа и выхода, а LLM использовать только как “подсказчика”, но не как исполнителя кода напрямую.
Пример — навык создания инвойса
def create_invoice(data: dict) -> dict:
# Валидация входных данных
if not validate_invoice_data(data):
return {"error": "validation_failed"}
# Запись в Postgres
invoice_id = insert_invoice_pg(data)
# Вызов стороннего API для отправки
api_result = send_invoice_api(invoice_id)
return {"invoice_id": invoice_id, "api_status": api_result}
Claude или GPT здесь только для генерации шаблонов писем или разбора неструктурированного текста, но не для бизнес-логики.
Интеграция навыков: orchestrator и Supabase
Почему не монолит
Если навык “зашит” прямо в агенте — любые изменения требуют перекомпиляции и тестирования всего агента. На практике навыки выносятся в отдельные модули/функции и регистрируются в Supabase как REST endpoint или в n8n как node. Это ускоряет ротацию навыков без ломки основной логики агента.
Оркестрация через n8n
- id: create_invoice
type: httpRequest
properties:
url: https://api.denniscraft.ai/invoice
method: POST
- id: notify_client
type: emailSend
properties:
to: {{$json.client_email}}
subject: "Ваш инвойс"
n8n позволяет собирать цепочки навыков без дублирования кода. В Supabase удобно хранить схему навыков и их версионирование.
Безопасность навыков: статический анализ и runtime sandbox
Ошибки, которые ловлю лично
Частая проблема — LLM генерирует небезопасный код при обработке пользовательских данных. На трех последних внедрениях ловил случаи, когда LLM-“навык” писал SQL без параметризации (risk: SQL-инъекция). Для проверки внедряю statical analysis: semgrep и bandit для Python, gitleaks для поиска секретов до попадания в продакшн. После — runtime sandbox: блокировка exec/eval, лимит времени, логирование всех внешних вызовов.
| Инструмент | Тип проверки | Где применяется |
|---|---|---|
| semgrep | Поиск паттернов уязвимостей | CI/CD, pre-commit |
| bandit | Анализ Python-кода на уязвимости | CI/CD |
| gitleaks | Поиск секретов в репозитории | Pre-push |
Версионирование и откат навыков
В реальном продакшне любой навык нужно версионировать явно. В Supabase использую таблицу skills со столбцами: skill_id, version, schema, code_hash, status. Откат на предыдущую версию через простое изменение active_flag. Это критично — иначе при ошибке в новой версии агент начинает некорректно работать во всей цепочке.
CREATE TABLE skills (
skill_id TEXT,
version INT,
schema JSONB,
code_hash TEXT,
status TEXT,
active_flag BOOLEAN
);
FAQ
Как протестировать новый навык без риска для продакшна?
Выношу тестовый endpoint, забираю данные с прода через read-only, запускаю навык в safe-среде (sandbox, отдельный Postgres schema), смотрю логи. Только после ручного ревью — rollout в основную цепочку.
LLM можно ли допускать к CRUD в реальной БД?
Только через proxy-слой с whitelisted-методами. Прямой доступ — риск, на практике даже Claude случайно пишет DROP вместо SELECT. LLM — только parser/generator, не executor.
Как быстро катить багфикс в навык?
Держу отдельный багфикс-branch с CI/CD на отдельный endpoint. После теста и ручного ревью — переключаю active_flag в Supabase. Downtime — секунды.
Какой минимальный набор логирования для навыка?
user_id, skill_id, входные и выходные параметры (без PII), статус выполнения, время исполнения, error trace. В n8n удобно писать в отдельную коллекцию logs.
Можно ли отдавать описание навыков в openapi.yaml для автогенерации?
Да, если описание написано строго, без “human in the loop” шагов. Тогда можно автогенерировать тесты и верификацию схемы.
В какой части цепочки навыков у вас чаще всего сыплются ошибки — при валидации входных данных, на этапе вызова внешнего API или при возврате результата? Рассказать детали — интересно сравнить подходы. Я провожу бесплатный 30-мин аудит стека для DACH-фаундеров, строящих AI в регулируемых рынках. Пишите в LinkedIn или на @ger_dennis_ai.
Turn your process into an AI system
Fixed price. Production quality. DACH B2B focus.