🤖🎯 Spec-Driven Development: научи AI-агента делать то, что нужно

Открыл PR от агента и не узнал свою задачу? Лишний код, не те решения, пропущенные обработки ошибок — и каждый раз заново все объяснять. Дело не в агенте, а в том, что ты не дал ему четкого контракта. Показываем, как это исправить раз и навсегда.

Spec-Driven Development: для чего AI-агенту нужна спецификация

Spec-Driven Development: для чего AI-агенту нужна спецификация

Ты даешь агенту задачу «Добавь анализ YouTube видео». Агент пишет 800 строк кода. Ты открываешь PR и видишь: он добавил три библиотеки для парсинга субтитров, реализовал загрузку видео на диск (которую ты не просил), не обработал видео без субтитров.

Винить агента не за что — ты дал ему пять слов задачи, а остальное он добрал из обучающих данных. Когда ты пишешь «добавь анализ видео», агент сталкивается с десятком развилок: как получить субтитры, какую модель использовать, что делать, если субтитров нет. На все эти вопросы он отвечает сам, как умеет — иногда угадывает правильно, но чаще нет.

Чтобы агент не угадывал, ему нужно заранее ответить на все эти вопросы — до того, как он сядет за код. Для этого существует спецификация.

Что такое спецификация

Спецификация (спека) — это документ, где ты с агентом заранее договариваешься, что должно получиться на выходе, чтобы не выяснять это постфактум по PR на 800 строк. Это контракт между тобой и агентом: что делаем, чего не делаем, как реагируем на ошибки, какие инструменты используем.

Что такое Spec-Driven Development

Spec-Driven Development (SDD) — методология разработки, где спецификация выступает источником истины для агента: не идея в голове разработчика, а зафиксированный документ, на который можно сослаться и который не меняется на лету.

Что фиксирует спецификация

Что фиксирует спецификация

Спецификация отвечает на вопрос «ЧТО делает проект?», чего не делает, как реагирует на граничные случаи, и какие технические решения уже приняты (модель, библиотека, сервис). Она не отвечает на вопрос, как именно эти решения реализовать в коде: какой будет внутренняя структура функций, алгоритм парсинга, имена переменных.

Дальше весь разбор строится на одном примере: сервисе анализа субтитров YouTube-видео.

Какие контракты описывают в спецификации

Что на входе, что на выходе: Например POST /api/videos/analyze возвращает {analysis: {...}}, формат запроса, формат ответа, коды ошибок. В реализацию (какие технологии и как вызываются внутри кода) спека не лезет.

Что такое инварианты в спецификации

Инварианты — правила без исключений: «Максимальная длина видео — 60 минут», «Субтитры кешируются на 7 дней», «Анализ только через Claude Opus». Когда через месяц агент решит, что было бы неплохо проанализировать двухчасовые видео, именно инвариант не даст ему сделать это.

Какие граничные случаи нужно описывать

Что происходит, когда что-то идет не так: видео без субтитров, упавший сервис субтитров, удаленное видео. Идеальный сценарий агенты пишут отлично, а вот про обработку ошибок забывают, если не напомнить явно.

Зачем нужны архитектурные правила в спецификации

Кто с кем общается. «Фронтенд не вызывает YouTube API напрямую, только через /api/videos/*». «Для субтитров используем только UltraData API, не youtube-transcript-api». Без этого агент выберет первую знакомую библиотеку из обучающих данных.

Что писать в разделе «Вне scope»

Какие фичи не реализуем. Без этого раздела агент будет ползти по scope: «раз уж мы тут, давайте еще и анализ комментариев». Явно перечисли, что НЕ делаем в этой итерации.

Как писать критерии приемки для AI-агента

Критерии приемки должны быть такими, чтобы агент мог сам их проверить, не спрашивая тебя.

Плохой критерий: «ошибки обрабатываются корректно». Хороший: «видео без субтитров возвращает 422 с error: no_subtitles». Если критерий нельзя проверить командой или кликом — он еще не готов.

Когда нужен Spec-Driven Development

Когда нужен Spec-Driven Development

Фича затрагивает больше одного компонента

Анализ видео: сервис субтитров, сервис анализа, API, UI, кеширование — пять компонентов, которым агент додумает поведение, если не написать явно.

Задача содержит бизнес-требования

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

Ожидаемый diff больше 400 строк

При таком объеме ты перестаешь удерживать последствия в голове — твой агент тоже. Спецификация разбивает большую задачу на атомарные части.

Агент уже переделывал задачу дважды

Если агент уже дважды переделывал задачу, стоит остановиться и зафиксировать требования в спецификации.

Когда Spec-Driven Development не нужен

Когда Spec-Driven Development не нужен
  • Правка в одном файле, поведение очевидно
  • Рефакторинг по шаблону
  • Быстрый эксперимент

Как выглядит спецификация в Spec-Driven Development

# spec: анализ YouTube видео

Статус: актуально  
Версия: 1.1  
Автор: @ivanov  

---

## Зачем
Создатели контента хотят учиться на успешных видео.
Мы автоматизируем анализ: хук, темп, ключевые моменты, рекомендации.

---

## Контракт
POST /api/videos/analyze
Body: {"url": "https://youtube.com/watch?v=..."}
Успешный ответ -- 200:

{
  "video_id": "...",
  "title": "...",
  "analysis": {
    "hook": {"summary": "...", "rating": "strong"},
    "pacing": {"summary": "..."},
    "key_points": [{"timestamp": "0:15", "description": "..."}],
    "improvements": ["..."]
  }
}

Ошибки:

400 -- невалидный URL 
404 -- видео не найдено 
422 -- нет субтитров или видео > 60 мин 
429 -- rate limit (5 запросов/мин) 
502 -- ошибка сервиса анализа (невалидный ответ Claude или недоступность Claude API) 
503 -- сервис субтитров недоступен (UltraData API не отвечает) 

---

## Инварианты
- Анализ только через Claude Opus
- Субтитры кешируются на 7 дней
- Результат анализа кешируется на 30 дней
- Максимальная длина видео -- 60 минут
- Rate limit: 5 запросов в минуту на IP-адрес, fixed window  
- Авторизация: эндпоинт публичный, без авторизации (вне scope этой итерации)

---

## Граничные случаи

**Видео без субтитров**
→ 422: {"error": "no_subtitles", "message": "Субтитры недоступны"}

**UltraData API упал**
Retry 3 раза (интервал 5 сек, без экспоненциального backoff), потом 503:
{"error": "transcript_service_unavailable"}

**Видео удалено**
→ 404: {"error": "video_not_found"}

**Видео > 60 минут**
→ 422: {"error": "video_too_long", "max_duration": 3600}

**Rate limit превышен**
Fixed window 60 сек, лимит 5 запросов на IP-адрес. 
→ 429: {"retry_after": <секунды до конца текущего окна>}
Пример: окно открылось в 12:00:00, 6-й запрос пришел в 12:00:18 → retry_after: 42

**Claude API вернул невалидный JSON или оборванный ответ**
Retry 2 раза (интервал 3 сек). Если после всех попыток ответ все еще
невалиден → 502: {"error": "analysis_failed", "message": "Не удалось получить анализ, попробуйте позже"}
Невалидный ответ не кешируется.

**Claude API недоступен (5xx/timeout)**
Retry 2 раза (интервал 3 сек), потом 502: {"error": "analysis_service_unavailable"}

---

## Архитектурные правила
- Фронтенд вызывает только `/api/videos/analyze`
- Claude API вызывает только backend
- Кеширование только через Redis
- Компоненты не вызывают внешние API напрямую, минуя соответствующий сервис
  (TranscriptService — единственная точка входа к UltraData, AnalysisService — к Claude)

---

## Технические требования
- Используй UltraData API для субтитров (API key в `.env`), не используй
  другие источники субтитров
- Используй Claude Opus через Anthropic SDK
- Для кеширования используй `RedisCache` из `utils/cache.py`
- Если результат анализа есть в кеше — он возвращается сразу, без обращения к TranscriptService и без повторной проверки длительности видео  
- НЕ добавляй youtube-transcript-api, yt-dlp
- НЕ скачивай видео на диск
- НЕ храни сырой транскрипт в ответе

---

## Вне scope
- ❌ Анализ визуального ряда -- только текст субтитров
- ❌ Поддержка Vimeo/TikTok -- только YouTube
- ❌ История анализов в UI -- не в этом спринте
- ❌ Экспорт в PDF -- не сейчас
- ❌ Авторизация и квоты по пользователям -- не в этом спринте

---

## Задачи

### Task 1: TranscriptService
**Файлы:** `services/transcript_service.py`
- `extract_video_id(url)` -- парсинг URL
- `fetch_transcript(video_id)` -- вызов UltraData API
- Retry 3 раза при 5xx (интервал 5 сек)
- Кеширование через Redis (TTL 7 дней)

**Верификация:**
- [ ] `pytest tests/test_transcript_service.py` проходит
- [ ] Вызов с реальным video_id возвращает транскрипт
- [ ] Повторный вызов берет из кеша
- [ ] Мокнутый 503 от UltraData во всех 4 попытках (1 исходный запрос + 3 retry) → TranscriptServiceUnavailableError наверх (роут конвертирует в HTTP 503 согласно разделу «Граничные случаи») 

---

### Task 2: AnalysisService
**Файлы:** `services/analysis_service.py`
- `analyze_video(video_id, transcript)` -- промпт для Claude
- Retry 2 раза (интервал 3 сек) при ошибках API и при невалидном/
  оборванном JSON в ответе
- Кеширование результата (TTL 30 дней), невалидный ответ не кешируется

**Верификация:**
- [ ] `pytest tests/test_analysis_service.py` проходит
- [ ] Mock Claude API возвращает валидный JSON → сохраняется в кеш
- [ ] Mock Claude API возвращает невалидный JSON во всех 3 попытках (1 исходный запрос + 2 retry) → AnalysisFailedError наверх, кеш не записан 
- [ ] Повторный вызов берет из кеша

---

### Task 3: POST /api/videos/analyze
**Файлы:** `api/routes/videos.py`
- Парсинг URL, валидация
- Rate limiting (5 req/min, fixed window, на IP-адрес) 
- Проверка длины видео (< 60 мин)
- Обработка всех ошибок согласно разделу «Граничные случаи»

**Верификация:**
- [ ] `curl -X POST /api/videos/analyze -d '{"url":"..."}'` → 200
- [ ] Невалидный URL → 400
- [ ] Видео без субтитров → 422
- [ ] 6-й запрос в минуту → 429 с корректным retry_after
- [ ] Мокнутый невалидный JSON от Claude → 502 с error=analysis_failed 
- [ ] Мокнутая недоступность Claude API → 502 с error=analysis_service_unavailable 

---

### Task 4: UI
**Файлы:** `frontend/src/pages/AnalyzePage.tsx`
- Input для YouTube URL
- Loader во время анализа
- Отображение результата (хук, темп, ключевые моменты, рекомендации)
- Обработка ошибок: 
  - error=analysis_service_unavailable → «Сервис анализа временно недоступен» 
  - error=analysis_failed → «Не удалось получить анализ, попробуйте позже» 

**Верификация:**
- [ ] Вставка валидного URL → результат отображается
- [ ] Видео без субтитров → показывается «Субтитры недоступны»
- [ ] Rate limit → показывается таймер обратного отсчета на retry_after секунд
- [ ] Mock 502 с error=analysis_service_unavailable → «Сервис анализа временно недоступен» 
- [ ] Mock 502 с error=analysis_failed → «Не удалось получить анализ, попробуйте позже» 

---

## Критерии приемки
- [ ] Пользователь вставляет URL → видит полный анализ
- [ ] Видео без субтитров → видит понятное сообщение
- [ ] Видео > 60 мин → видит «Слишком длинное»
- [ ] 6-й запрос → видит таймер с корректным временем ожидания
- [ ] Повторный анализ того же видео → мгновенный результат (берется
      из кеша анализа, а не пересчитывается заново)
- [ ] Claude вернул невалидный ответ → пользователь видит понятную
      ошибку, а не зависший loader

На бумаге это выглядит логично, а на практике первые спеки обычно получаются либо слишком общими, либо слишком подробными: забыл прописать граничный случай — агент его не учтет, не назвал библиотеку явно — агент возьмет первую знакомую, а иногда спека незаметно разрастается до десяти страниц.

Сам такие огрехи замечаешь обычно постфактум, когда агент уже пошел не туда. Научиться распознавать их заранее получится, если помогает человек, который уже освоил этот навык: «Смотри, тут спеки написаны так, что устареют после первой итерации», «Здесь агент ушел не туда, потому что контекст неполный» — именно так и устроена обратная связь на курсе «Управляемая разработка с AI и Spec-Driven Development», где ты собираешь проект по неделям. К концу курса ты защищаешь проект и выходишь с рабочей системой.

Как работать с AI-агентом по методологии Spec-Driven Development

Как работать с AI-агентом по методологии Spec-Driven Development

1. Как сгенерировать спецификацию

Промпт:

Напиши спецификацию для фичи: анализ YouTube видео.

Структура: Зачем, Что, Контракты, Инварианты, Граничные случаи, 
Архитектурные правила, Технические требования, Вне scope, 
Задачи (3-5 штук с верификацией).

Контекст: Python/FastAPI, React, Redis, Claude Opus, 
UltraData API для субтитров.

Прежде чем писать, проверь, хватает ли тебе информации для 
Инвариантов и Граничных случаев (лимиты по длительности видео, 
правила кеширования, поведение при отсутствии субтитров и т.д.). 
Если каких-то решений не хватает -- задай мне вопросы списком, 
не придумывай их сам.

Каждый пункт делай конкретным и проверяемым: коды ошибок, 
точные числа лимитов, названия библиотек -- без общих формулировок 
вроде "обрабатываем ошибки корректно".

Агент сгенерирует первую версию. Дальше ты ее ревьюишь.

2. Как проверить спецификацию перед реализацией

[✓] Неоднозначности устранены?

[✓] Библиотеки явно названы?

[✓] Out of scope записан?

[✓] Каждый таск атомарный?

[✓] Есть способ проверить результат?

[✓] Граничные случаи покрыты?

3. Как протестировать спецификацию

Промпт:

Прочитай spec.md. Реализуй только Task 1 (минимальный прототип).
Протестируй, что базовая механика работает.

Если что-то не так (библиотека не подходит, API не работает) → правь спеки, а не код.

4. Как давать задачи AI-агенту по спецификации

Не давай агенту всю спецификацию сразу. Работай по одной задаче.

Сессия 1:

Прочитай spec.md. Реализуй Task 1.

Агент пишет код → ты ревьюишь → коммитишь.

Сессия 2:

Прочитай spec.md. Реализуй Task 2.

Ты не застреваешь в одной длинной сессии и каждый коммит атомарный.

5. Как проверять код после каждой задачи

Промпт:

Проверь, что Task 1 работает:
1. Запусти pytest
2. Попробуй вызвать функцию вручную
3. Убедись, что кеширование работает

Агент сам протестирует свой код. Если что-то сломано — исправит до Task 2.

6. Как обновлять спецификацию в процессе разработки

Обнаружил проблему в процессе → останови работу, обнови спеки. Например, в процессе разработки выяснилось, что без ограничения числа попыток агент зависал в бесконечном retry при недоступности UltraData API. Обновляем спеки:

- Retry 3 раза при ошибках UltraData API 
+ Retry 3 раза (интервал 5 сек), потом 503 — без этого агент зависал в бесконечном retry при недоступности сервиса 

7. Как фиксировать технические решения

Зафиксируй выбранные библиотеки, сервисы и инструменты и то, что использовать нельзя. Это и есть та часть «ЧТО», которая казалась бы похожей на «КАК»: выбор технологии — это принятое решение, а не алгоритм. Агент не имеет права пересматривать его без обсуждения, но вправе сам решать, как именно внутри кода эту технологию использовать. «Используй UltraData API, не youtube-transcript-api» — из этой категории.

Антипаттерны Spec-Driven Development: какие ошибки делают при написании спецификаций

Антипаттерны Spec-Driven Development: какие ошибки делают при написании спецификаций

❌ Ошибка: нет конкретики в спецификации

Ты: «Добавь анализ видео»Агент угадывает: какой API? какую модель? что делать без субтитров?Результат: 800 строк, половина не то.

Правильно: пиши спеки с явными решениями.

❌ Ошибка: спецификация на 10 страниц

Ты описываешь, как реализовать. Агент теряется в деталях.

Правильно: спеки отвечают на «ЧТО» и фиксируют принятые решения, но не диктуют, как писать сам код.

❌ Ошибка: все задачи за раз

Агент пытается сделать все сразу → 800 строк → ревью невозможно.

Правильно: разбей на 3-5 атомарных задач.

❌ Ошибка: спецификация без верификации

Агент говорит «готово», ты запускаешь → не работает.

Правильно: каждая задача содержит конкретные команды для проверки.

Как автоматизировать создание спецификаций

Промпт для генерации спецификации

Ты пишешь спецификацию для AI-агента по методологии Spec-Driven Development.

Контекст проекта:
- Стек: [впиши свой, например Python/FastAPI, React, Redis]
- Фича: [опиши задачу в 1-2 предложениях]

Прежде чем писать спеку, проверь, хватает ли тебе информации.
Если не хватает -- НЕ придумывай, а задай мне уточняющие вопросы
по каждому из пунктов ниже и жди ответа.

Структура спеки:
- Зачем: зачем это нужно, для кого
- Что: что делаем (1-2 абзаца, без деталей реализации)
- Контракты: эндпоинты, форматы запросов/ответов, коды ошибок
- Инварианты: правила без исключений (лимиты, ограничения, выбор модели/сервиса)
- Граничные случаи: что происходит, когда что-то идет не так
  (минимум 3-5 случаев: невалидный вход, отказ внешнего сервиса, превышение лимита)
- Архитектурные правила: какой компонент с каким имеет право общаться
- Технические требования: какие библиотеки/сервисы использовать,
  что использовать запрещено
- Вне scope: что НЕ делаем в этой итерации (минимум 3 пункта)
- Задачи: 3-5 атомарных задач, каждая -- отдельный коммит,
  с конкретной командой/способом верификации
- Критерии приемки: 3-5 проверяемых сценариев "пользователь делает X → видит Y"

Правила:
- Будь конкретным: не "используй кеш", а "используй Redis с TTL 7 дней"
- Не гадай -- если решение неочевидно, спроси меня, а не выбирай сам
- Спека описывает ЧТО и контракты, а не КАК реализовывать алгоритм
- Каждый пункт должен умещаться в 1-3 предложения -- если получается больше,
  значит, это две задачи, а не одна
- Если фича маленькая (один файл, очевидное поведение) -- скажи мне,
  что спека не нужна, вместо того чтобы писать ее формально

Выведи результат в формате markdown, готовом для сохранения в spec.md.

Итого: зачем AI-агентам нужен Spec-Driven Development

Зачем AI-агентам нужен Spec-Driven Development

Если коротко, спецификация — это просто способ договориться с агентом заранее, а не разгребать последствия в PR. На практике важнее всего четыре вещи:

  1. Писать спеку до того, как агент сядет за код
  2. Фиксировать требования, контракты и принятые технические решения, но не диктовать внутреннюю реализацию и структуру кода
  3. Двигаться маленькими задачами по одной за сессию
  4. Проверять каждую задачу, а не верить агенту на слово

Где еще пригодится спецификация

За пределами этой статьи остаются темы, которые тоже стоят отдельного разговора: как писать спеки для легаси-кода, для рефакторинга, который не должен ничего поломать вокруг, и для багфиксов, где сначала нужно воспроизвести проблему. Отдельно — чек-лист ревью AI-кода: какие типовые ошибки агенты допускают чаще всего и как их ловить автоматически. И тест-стратегия: как писать тесты до реализации, чтобы агент не написал код, который проходит только идеальный сценарий.

На курсе «Управляемая разработка с AI и Spec-Driven Development» каждой из этих тем отведена отдельная неделя — 8 в общей сложности. Ты ведешь свой проект и получаешь обратную связь от эксперта на воркшопах, а в конце остаешься с работающим кодом для портфолио и принципами SDD: шаблонами спецификаций, чек-листами ревью, тест-стратегиями.

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ

natkaida
08 ноября 2023

🔈16+ лучших нейронок для синтеза речи

Предлагаем подборку платных, бесплатных и опенсорсных инструментов для озву...
natkaida
18 октября 2023

🤖 25 бесплатных AI-инструментов для разработчиков

Расскажем о бесплатных и опенсорсных ИИ-помощниках, которые заменят GitHub ...
korneva.i.24
21 сентября 2023

🤖 Создание собственного ИИ-бота на Python за 33 строчки кода

Расскажем, как создать собственный чат-бот на Python с помощью следующей ин...