almdev Технический блог

Я перестал писать Swagger вручную: что в документации API можно делегировать AI
Агент собирает контракт из route, DTO, validation и ошибок, но не получает права его придумывать.

Как делегировать coding agent исследование endpoint, обновление OpenAPI и поиск рассинхронизации, не отдавая ему решения о публичном контракте API.

Подкатегория: Воркфлоу

Чтение
6 мин
Технологии / версии
Coding agent · Воркфлоу · Документация · API
Серия
Swagger и OpenAPI · часть 2 из 2
1 сен 2026 · 6 мин · 9 просмотров · AI
Карточки из кода собираются в спецификацию, публичный контракт закрыт печатью
Воркфлоу 09/2026

В предыдущей статье я разбирал OpenAPI как часть архитектуры API. После этого остаётся механическая проблема: route, validation, DTO, Resource, enum и исключения уже описаны в коде, но разработчик повторяет их в спецификации.

Именно такую работу мне всё меньше хочется выполнять вручную. Не потому, что AI умеет сочинять документацию, а потому, что coding agent умеет пройти по проекту и сопоставить уже существующие части контракта.

Не написать документацию, а собрать контракт

Запрос «сделай Swagger» слишком широкий. Он подталкивает модель заполнить пробелы правдоподобным текстом, а в API правдоподобная выдумка опаснее честного пропуска.

Рабочая постановка выглядит иначе:

repository
   ↓
route and middleware
   ↓
request DTO and validation
   ↓
application operation
   ↓
response DTO or Resource
   ↓
exceptions and error mapping
   ↓
OpenAPI diff

Это не творческое письмо. Это исследование связей и перенос фактов из одного формального представления в другое.

Правила, которые я задаю один раз

Для проекта я фиксирую короткий порядок:

1. Найди route и middleware.
2. Определи controller или action.
3. Найди FormRequest, MapRequestPayload или request DTO.
4. Извлеки validation rules и enum.
5. Проследи вызов до response DTO или Resource.
6. Найди exception handler / subscriber.
7. Используй существующие reusable schemas.
8. Не придумывай поля и ошибки.
9. Не меняй публичный контракт без отдельного решения.
10. Сгенерируй OpenAPI и проверь результат.

Такой список нужен не одному endpoint. Он превращает обновление документации в повторяемый workflow.

Сначала research, потом изменения

Я не разрешаю агенту сразу расставлять Attributes. Первый проход — только чтение:

Исследуй endpoint создания заказа. Не изменяй код. Определи route, авторизацию, входной DTO, validation rules, вызываемый сервис, формат ответа и возможные исключения. Сравни это с OpenAPI-описанием и приложи ссылки на файлы.

Хороший отчёт короткий и проверяемый:

POST /api/orders
Controller: StoreOrderController
Request: StoreOrderRequest
Response: OrderResource
Success: 201
Errors found in code: 401, 409, 422

OpenAPI drift:
- response 409 отсутствует
- у quantity не указано minimum: 1
- поле delivery_date описано без format: date

Уже на этом шаге агент полезен как аудитор. Если карта неверна, я исправляю понимание до того, как ошибка размножится по схемам.

План отделён от реализации

После исследования появляется план с конкретными объектами, а не обещание «обновить Swagger»:

1. Добавить CreateOrderRequest schema.
2. Переиспользовать OrderResponse.
3. Добавить ConflictErrorResponse.
4. Обновить POST /api/orders.
5. Сгенерировать openapi.json.
6. Сравнить схему с validation и тестами.

Только после проверки этого списка агент меняет файлы. Разделение research, plan и implementation кажется медленнее одного большого запроса, но экономит ревью: спор о контракте происходит до диффа.

Unknown лучше выдумки

Пусть контроллер возвращает $this->json($result), а тип $result не удаётся восстановить ни по сигнатуре, ни по фабрике, ни по тестам. У агента два варианта:

A. «Структуру ответа определить не удалось»
B. «Вероятно, ответ выглядит так...»

В документации API подходит только вариант A. Моё правило записано буквально:

Модель легко создаёт убедительный example response. Убедительность не делает его контрактом.

Laravel: цепочка для агента

В Laravel маршрут обычно читается достаточно прямо:

Route
↓
Middleware
↓
FormRequest
↓
Controller
↓
Action
↓
Resource
↓
Exception Handler

Из правила:

'quantity' => [
    'required',
    'integer',
    'min:1',
    'max:100',
],

можно получить type: integer, minimum: 1 и maximum: 100. Из backed enum — допустимые значения. Из OrderResource — форму успешного ответа, если Resource не зависит от скрытого runtime-контекста.

Современный swagger-php предпочитает PHP Attributes, а L5-Swagger использует его генератор и Swagger UI. Для coding agent это проще старого DocBlock-синтаксиса: атрибуты имеют структурированные аргументы и проверяются PHP.

Symfony уже автоматизирует часть сам

В Symfony карта похожа:

Route
↓
Controller
↓
MapRequestPayload / DTO
↓
Symfony Validator
↓
Handler
↓
Response DTO
↓
ExceptionSubscriber

NelmioApiDocBundle уже извлекает request body из MapRequestPayload и использует Symfony Attributes. Поэтому агенту не всегда нужно генерировать всю схему. Полезнее найти то, чего автоматический проход не видит: бизнес-ошибки, permissions, нестандартные headers, idempotency и примеры.

Чем больше способен вывести инструмент, тем меньше текста должен писать агент. Я не плачу за дублирование только потому, что теперь его делает модель.

Bitrix и legacy: сначала фактический контракт

В собственном API на Bitrix автоматизации обычно меньше, поэтому эффект от исследования выше. Если проект уже разделён на Controller, Request, Response, Service и Exception, агент проходит знакомую цепочку и обновляет Attributes для swagger-php.

Legacy интереснее. Допустим, существует обработчик:

if ($_REQUEST['action'] === 'create') {
    // 250 строк авторизации, проверок, ORM и JSON
}

Просить сразу написать OpenAPI рано. Сначала нужен отчёт о фактическом поведении:

входные параметры и обязательность
приведение типов и проверки
успешный ответ
ветки ошибок
побочные эффекты
неоднозначные места

Такой документ становится картой для последующего разделения обработчика. Если контракт невозможно определить однозначно, это результат исследования, а не неудача агента.

Синхронизация вместо разовой генерации

Самая полезная автоматизация начинается не с новой документации, а с обычной задачи. Например, при добавлении external_id разработчик меняет DTO, validation, service, базу, Resource и тесты — и забывает спецификацию.

Я хочу, чтобы правило проекта срабатывало по самому факту изменения публичного API:

если изменён route, request, response, enum
или публичная ошибка,
найди затронутую OpenAPI operation,
обнови её и проверь генерацию

Тогда документация входит в Definition of Done, а не зависит от памяти автора задачи.

TASK
  ↓
RESEARCH
  ↓
PLAN
  ↓
IMPLEMENTATION
  ├── code
  ├── validation
  ├── tests
  └── OpenAPI
  ↓
VERIFY
  ├── tests
  ├── OpenAPI generation
  └── contract diff
  ↓
REPORT

Проверка рассинхронизации

После генерации агент может сравнить код и спецификацию. Здесь не требуется архитектурное чутьё — нужны точные пары:

Validator: quantity max = 100
OpenAPI:   quantity maximum = 1000

Controller: 201 Created
OpenAPI:    200 OK

PHP enum: draft, active, archived
OpenAPI:  draft, active

Каждая такая разница должна остановить проверку. Автоматически выбрать правильную сторону нельзя: иногда устарела схема, иногда код, иногда оба расходятся с договорённостью команды.

Агент хорошо находит противоречие. Решение о контракте остаётся у разработчика.

OpenAPI как вход для других инструментов

Качественный openapi.json обслуживает не только Swagger UI:

PHP code
   ↓
OpenAPI
   ↓
client SDK
frontend types
mocks
contract tests
AI context

Поэтому ошибка в спецификации размножается дальше. Сгенерированный TypeScript type делает выдуманное поле убедительнее, но не реальнее. Чем больше потребителей у схемы, тем строже должно быть правило Unknown > Invented.

Что я делегирую, а что оставляю себе

Агенту можно поручить исследование endpoint, поиск связанных классов, извлечение validation rules и enum, обновление Attributes, переиспользование schemas, генерацию примеров из подтверждённых типов, запуск генератора и поиск рассинхронизации.

Осторожность начинается там, где нужно решить, каким должен быть публичный API: границы endpoint, семантика status codes, бизнес-ошибки, versioning, backward compatibility, permissions и security. Здесь агент собирает факты и варианты, но не получает право молча менять договор между системами.

Ускорение не в наборе Attributes

Пятьдесят строк OpenAPI Attributes агент напишет быстрее меня. Это небольшая экономия.

Сильнее меняется сам цикл: раньше я должен был вспомнить о документации, найти нужную схему, обновить и проверить. Теперь workflow замечает изменение контракта, показывает затронутые операции, обновляет OpenAPI и возвращает diff вместе с тестами.

Автоматизируется не набор текста. Автоматизируется обязанность помнить о повторяющемся действии.

После Swagger тот же вопрос возникает вокруг миграций, changelog, permissions matrix и примеров интеграции: если изменение уже видно в коде, почему человек должен каждый раз вручную вспоминать обо всех его отражениях?

О том, как вместе с этой обязанностью меняется моя роль разработчика, я написал отдельно — в личной заметке.

Серия

Swagger и OpenAPI

#coding-agent #workflow #dokumentaciya #api #openapi