Agent Skill
Готовый Agent Skill, который учит кодового ассистента писать на Volga правильно, — тот же материал, что и на этом сайте, но переупакованный под модель, а не под читателя.
Исходники: skill/volga.
Зачем это нужно
Ассистенты уверенно ошибаются в Volga, и причина конкретная: в ветке 0.9 поменялись умолчания безопасности и исчезло целое семейство вспомогательных методов, в 0.10.0 перестроилось то, как запросы доходят до middleware и как группы маршрутов применяют свои настройки, в 0.10.1 изменился ответ на отклонённый токен, в 0.11.0 появились синхронные обработчики, catch-all маршруты и таймаут завершения, в 0.11.1 — собственный fallback у группы маршрутов, в 0.12.0 Err обработчика стал ошибкой для map_err, а не вторым видом ответа, в 0.13.0 каждый параметр пути стал приходить уже декодированным, в 0.13.1 группа маршрутов и маршрут получили собственное ограничение размера тела, в 0.13.2 сервер ресурсов научился загружать ключи эмитента с указанного им URL, в 0.13.3 with_alg стал заменять HS256 по-умолчанию, и ключи сверяются с ним при старте, в 0.14.0 Dc<T> стал доступен только для чтения, и сервисы с параметрами пути проверяются при старте, а в 0.14.1 cache_control, use_problem_details и ValidPath переименованы по одному правилу именования, — при том что почти весь код на Volga, который модель видела, написан до всего этого. Поэтому типичная ошибка — не забытое имя метода. Это ассистент, который пишет ok!("hi", [("x-key", "v")]) через запятую вместо точки с запятой, возвращает Err("not found".to_string()) и получает 500, повторно декодирует уже декодированный параметр пути, тянется к with_default_cors(), вызывает use_cors() на приложении, где CORS не настроен, раздаёт статику через map_static_assets() или отдаёт конфигурацию bearer-аутентификации, которая за прокси с терминацией TLS отвечает 400 на каждый запрос.
Скилл выносит ровно эти ловушки вперёд, а за подробностями отправляет в нужный файл.
Что внутри
| Файл | О чём |
|---|---|
SKILL.md | Определение версии и набора фич, список ловушек, минимальное приложение, маршрутизация |
references/routing.md | Маршруты, группы, параметры пути и запроса, параметры пути собственных типов, JSON, формы, файлы, multipart, ограничения размера тела, заголовки, куки |
references/responses.md | Макросы ответов, IntoResponse, статус-коды, стриминг, ошибки и IntoError, Problem Details |
references/middleware.md | with / wrap / attach / filter / tap_req / map_ok, CORS, сжатие, статика, rate limiting |
references/di-config.md | Времена жизни DI, Inject, фабрики, файлы конфигурации, горячая перезагрузка |
references/security.md | Basic-аутентификация, JWT, авторизаторы, OAuth 2.1 / OIDC, клиентский крейт, TLS, HSTS |
references/realtime.md | WebSockets, WebSocket-over-HTTP/2, Server-Sent Events |
references/operations.md | Фичи, graceful shutdown, отмена запросов, трейсинг, OpenAPI и схемы, описанные вручную, TestServer |
references/migration.md | Симптом → причина и переходы с 0.14.0 на 0.14.1, с 0.13.x на 0.14.0, с 0.13.2 на 0.13.3, с 0.13.1 на 0.13.2, с 0.13.0 на 0.13.1, с 0.12.x на 0.13.0, с 0.11.x на 0.12.0, с 0.10.x на 0.11.0, с 0.10.0 на 0.10.1, с 0.9.x на 0.10.x и с 0.8.x на 0.9.x |
SKILL.md намеренно короткий: это точка входа, которую агент читает всегда, и восемь справочников, которые он подгружает только под конкретную задачу.
Установка
Формат SKILL.md — общий стандарт, поэтому установка везде одинаковая: распаковать и скопировать каталог volga/ в папку скиллов инструмента, сохранив имя каталога — оно должно совпадать с полем name во frontmatter.
| Инструмент | Персонально | В проекте |
|---|---|---|
| Claude Code | ~/.claude/skills/volga/ | .claude/skills/volga/ |
| opencode | ~/.config/opencode/skills/volga/ | .opencode/skills/volga/ |
| Codex CLI | ~/.codex/skills/volga/ | .codex/skills/volga/ |
unzip volga-skill.zip
mkdir -p ~/.claude/skills && cp -r volga ~/.claude/skills/
После этого ассистента нужно перезапустить — скиллы обнаруживаются при старте.
opencode дополнительно читает .claude/skills/ и .agents/skills/, так что одна копия внутри проекта может обслуживать несколько инструментов.
Всё остальное
Подойдёт любой ассистент, умеющий читать файлы. Укажите ему на SKILL.md и дайте пройти по ссылкам — либо добавьте строчку в AGENTS.md проекта:
For Rust web work with the `volga` crate, read
`.agents/skills/volga/SKILL.md` and the reference file it routes you to.
Что вынесено вперёд
Смысл скилла, в отличие от пересказа документации, — именно список того, в чём модель ошибается сама по себе. Часть того, что SKILL.md ставит до всего остального:
- Пользовательские заголовки идут после точки с запятой:
ok!("Hello"; [("x-key", "v")]). Запятая попадает в веткуformat!и не компилируется. with_*забираетAppпо значению,map_*— по&mut. Сначала цепочка настроек, потом маршруты, и приложение объявляется какlet mut app.require_httpsиstrip_token_from_requestвключены по умолчанию для bearer-аутентификации — из-за этого локально работающая конфигурация за обратным прокси отвечает400.with_audделаетaudобязательным клеймом, пока не вызванwithout_strict_aud().with_default_cors()иwith_default_tracing()удалены, а builder-методы видаwith_credentials,with_preloadбольше не принимаютbool.Path<T>— это кортеж,NamedPath<T>— именованная структура, и ни тот, ни другой нельзя смешивать с позиционными параметрами пути в одном обработчике. Собственный тип становится параметром пути черезFromPathArgначиная с 0.13.0.full— это не «всё»:#[derive(Claims)],#[http_header], dev-сертификаты иTestServerтребуют фич, которых вfullнет.- Отклонённый bearer-токен — это
401, а не403начиная с 0.10.1;403остался за действительным токеном, которому не хватает роли или разрешения, требуемых маршрутом. - Неразрешимый граф зависимостей останавливает приложение на старте начиная с 0.10.1, поэтому ручная реализация
Injectдолжна декларировать то, что она резолвит. - Синхронный обработчик выполняется на воркере рантайма — блокирующая работа оборачивается в
blocking, а не пишется в обычнойfn. - Значение catch-all — не безопасный путь к файлу:
{*path}приходит ненормализованным, вместе с... - Бесконечные ответы завершаются по сигналу остановки через экстрактор
ShutdownHandle, а не обрываются по таймауту завершения. - Оболочка SPA отвечает только на
GETиHEADначиная с 0.11.1, а API на том же сервере получает собственныйmap_fallbackу своей группы. Errобработчика — это ошибка начиная с 0.12.0: он доходит доmap_err, голая строка отвечает500, а тип ошибки реализуетIntoError— никогда неFrom<T> for Error.- Параметры пути приходят декодированными начиная с 0.13.0: обработчик никогда не декодирует их повторно, а литеральный сегмент, записанный с
%XX, вызывает панику при регистрации. - Ограничение размера тела задаётся там, где тело читают, начиная с 0.13.1: группа маршрутов или маршрут повышает или понижает его для себя, побеждает самое конкретное ограничение, а на тело больше него приходит
413. with_issuer— этоiss, который несут токены: если сервер не может до него достучаться (контейнер, хост ingress), начиная с 0.13.2 ключи загружаются черезwith_jwks_uri, а не перенаправлением эмитента на внутренний URL.with_algзадаёт список целиком начиная с 0.13.3: первый вызов заменяетHS256,encodeподписывает первым алгоритмом, статический ключ RSA, EC или Ed25519 идёт вместе сwith_algсвоего семейства, иначе приложение не стартует, аwith_issделает claimissобязательным.Dc<T>доступен только для чтения начиная с 0.14.0: изменяемое состояние живёт внутри сервиса заMutex,RwLockили атомиком, а обработчик или middleware, принимающий незарегистрированный сервис, останавливает приложение при старте.- Обработчик читает только те параметры пути, которые объявляет его маршрут, начиная с 0.14.0:
map_get("/sum", |x: i32, y: i32| ..)паникует при регистрации, а не отвечает500на каждый запрос.
Код в нём компилируется
Rust-код скилла собирается против опубликованных крейтов volga в CI этого репозитория — той же задачей, что проверяет сниппеты на сайте, — так что то, что ассистент оттуда копирует, компилируется. Блоки, показывающие форму, а не программу (сигнатура, impl с опущенными телами), исключаются явно.
Ту же проверку можно запустить локально:
python3 ci/check-snippets.py --docs-dir skill --default-mode compile-fragment --default-features "full auth-full macros dev-cert test"
Версия
Скилл описывает volga 0.14.1 при MSRV 1.90. Обе величины записаны во frontmatter, чтобы ассистент мог понять, совпадает ли скилл с крейтом в проекте:
metadata:
volga-version: "0.14.1"
msrv: "1.90"