← Назад к статьям

Мой подход к разработке продукта с ИИ-агентами

технологии
ai-agentsproduct-developmentopenspecsdd

Read in English →

Когда вы даёте ИИ-агенту задачу «сделай мне сервис заметок» без предварительной подготовки, результат почти всегда один и тот же: хаотичный набор кода, который решает не ту задачу, которую вы имели в виду, и который сложно развивать дальше. Причина не в том, что агент «плохой», а в том, что у него нет контекста — того самого понимания продукта, которое есть у вас в голове, но которое вы не зафиксировали в явном виде.

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

Подход состоит из трёх крупных этапов:

  1. Анализ — проектирование системы на бумаге, до того как написана хоть одна строчка кода.
  2. Разработка — реализация функционала по заранее согласованному плану.
  3. Тестирование — проверка того, что реализованное соответствует задуманному.

Разберём каждый этап подробно.


Этап 1. Анализ: спроектируйте систему, прежде чем её строить

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

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

Шаг 1. Опишите проект своими словами

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

Например, если вы хотите сделать сервис для ведения заметок, начальное описание может звучать так: «Хочу сервис, где пользователь может быстро создавать заметки, группировать их по тегам и находить нужную через поиск по тексту».

Это описание сохраняется в отдельный файл — SOURCE.md. Он не обязан быть идеальным: его задача — зафиксировать первоначальный замысел, к которому агент будет возвращаться при заполнении остальных документов.

Шаг 2. Сформируйте три базовых документа проекта

Шаблоны для всех трёх файлов не нужно придумывать с нуля — я собрал их в отдельном репозитории: ai-project-tmpl. Скачайте нужные шаблоны оттуда и используйте как основу.

На основе SOURCE.md формируются ещё три файла. Вместе с исходным описанием они образуют полный комплект артефактов этапа анализа:

  • SOURCE.md — свободное описание проекта, отправная точка для всего остального.
  • PROJECT.md — центральный технический документ: архитектура, стек, функциональные требования, пользовательские сценарии. Это основной файл, на который агент опирается на протяжении всей разработки, чтобы не терять контекст проекта.
  • DATAMODEL.md — модель данных: таблицы, поля, связи между ними.
  • ROADMAP.md — дорожная карта, по которой агент будет последовательно реализовывать проект.

Заполняются они не одновременно, а по цепочке: каждый следующий файл строится на основе предыдущих.

2.1. Заполнение PROJECT.md

Начните с архитектуры. Если вы уже знаете, какой стек хотите использовать — пропишите его сами. Если нет — попросите агента предложить архитектуру на основе SOURCE.md, но в этом случае обязательно проверьте предложение критически: агент может выбрать стек, который не подходит под ваши реальные ограничения (команда, инфраструктура, сроки).

Пример того, как может выглядеть описание стека для backend-части:

Стек: Python (FastAPI)

Зависимости:
- Python 3.11+
- FastAPI
- PostgreSQL 15+
- Обязательный async-first режим: async def в API/сервисах/CRUD,
  SQLAlchemy AsyncSession, async-драйвер PostgreSQL (asyncpg)
- Запрещены блокирующие I/O операции в runtime-коде API
  (HTTP, БД, sleep и т.п. — только через async API)
- pytest + pytest-asyncio для тестов
- pydantic-settings + .env для конфигурации
- structlog для логирования

Такой уровень детализации важен: чем конкретнее зафиксированы технические ограничения, тем меньше агенту придётся «додумывать» самому — а значит, тем меньше риск получить решение, которое технически работает, но не соответствует вашим стандартам.

Если backend и frontend в проекте разделены и общаются через API, имеет смысл описывать их архитектуру отдельно, начиная с backend как более критичной части.

После того как стек и архитектура описаны, отдайте агенту задачу на заполнение шаблона:

На основании файла @SOURCE.md заполнить шаблон @PROJECT.md.

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

2.2. Формирование модели данных

Когда PROJECT.md готов, на его основе формируется модель данных:

На основании файла @PROJECT.md заполни шаблон @DATAMODEL.md

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

2.3. Формирование дорожной карты

Финальный документ этапа анализа — план реализации:

На основании файла @PROJECT.md и @DATAMODEL.md заполни шаблон @ROADMAP.md

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

Если находите пробелы — не бойтесь возвращаться назад

Если в процессе заполнения любого из файлов вы понимаете, что что-то не учли или описали неточно — пройдите цикл анализа заново: скорректируйте SOURCE.md или PROJECT.md и заново сформируйте зависящие от них документы. Дешевле потратить лишний час на этом этапе, чем переделывать реализованный функционал.


Этап 2. Разработка: Spec-Driven Development

Когда все четыре документа готовы и проверены, начинается непосредственно написание кода. Но здесь важно не наступить на ещё одни грабли: просто отдать агенту ROADMAP.md и попросить «реализуй всё по порядку» — недостаточно. Roadmap описывает что нужно сделать на уровне вех, но не фиксирует как именно агент должен рассуждать над конкретной задачей, какие у неё границы и какое поведение системы считается правильным. Без этого агент на каждой вехе заново додумывает детали — и снова рискует отклониться от замысла.

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

Погружаться в теорию SDD в рамках этой статьи я не буду — материалов по теме достаточно в открытом доступе. Расскажу про инструмент, которым пользуюсь сам.

Инструмент: OpenSpec

Реализовать SDD-подход вручную можно, но удобнее опираться на готовый фреймворк. Я использую OpenSpec — open-source фреймворк для SDD-разработки с LLM. Подобных инструментов немного, и OpenSpec не единственный вариант: например, есть также Specify от GitHub. Но в большинстве проектов мне хватает OpenSpec.

Устанавливается он глобально через npm:

npm install -g @fission-ai/openspec@latest

После установки инициализируется прямо внутри проекта:

cd your-project
openspec init

Настройка: артефакты на русском языке

По умолчанию OpenSpec генерирует артефакты на английском. Если вы хотите, чтобы все документы фреймворка были на русском языке, это настраивается в конфиге openspec/config.yml:

schema: spec-driven

context: |
  1. Источник истины: PROJECT.md
  2. Язык артефактов: все артефакты OpenSpec (proposal, tasks, design, specs и любые другие) должны быть написаны на русском языке. Заголовки, описания, задачи и текст в артефактах — только по-русски.

Здесь же полезно явно указать, что источником истины для агента остаётся PROJECT.md — так фреймворк не начнёт «спорить» с документами, которые вы подготовили на этапе анализа.

Жизненный цикл: explore → propose → apply → archive

В основе OpenSpec — четыре команды, которые образуют цикл работы над каждым изменением:

explore → propose → apply → archive

  • explore — агент разбирается в задаче и контексте, прежде чем предлагать решение.
  • propose — на основе анализа формируется предложение по изменению: что и зачем мы делаем.
  • apply — одобренное предложение реализуется в коде.
  • archive — изменение завершается и убирается из списка активных предложений, при этом его история сохраняется.

На практике для большинства задач мне достаточно трёх команд из четырёх — propose, apply и archive; explore пригождается в основном для более сложных или неоднозначных задач, требующих отдельного разбора перед тем, как формировать предложение.

Как это выглядит на практике

Работа строится вокруг вех из ROADMAP.md. Я беру первую невыполненную веху целиком — с её описанием и списком задач — и передаю её агенту (например, в Cursor) командой propose:

/opsx-propose Milestone 1: Фундамент платформы и безопасность

Сама веха в ROADMAP.md к этому моменту выглядит примерно так — с чёткой целью, разбивкой на задачи и критерием готовности:

### Milestones (Вехи проекта)

#### [ ] Milestone 1: Фундамент платформы и безопасность

**Цель:** Заложить надежную асинхронную базу (FastAPI) и реализовать базовую модель пользователей и авторизации. Система должна быть готова к приему бизнес-логики.

- [ ] **TASK-01: Инфраструктура и Архитектура**
  - [ ] Развертывание `docker-compose.yml` (PostgreSQL 15+, MinIO, FastAPI).
  - [ ] Настройка слоистой архитектуры (`app/api`, `app/services`, `app/crud`, `app/db`).
  - [ ] Настройка базовых библиотек: `SQLAlchemy AsyncSession`, `Alembic` для миграций, `pydantic-settings` для `.env`.
  - [ ] Настройка линтеров (`ruff`, `mypy`) и CI-пайплайна.

- [ ] **TASK-02: Авторизация и Пользователи**
  - [ ] Создание моделей БД (`workspaces` как root tenant и `users`, роли: Trainer / Athlete). При регистрации юзеру создается персональный workspace.
  - [ ] Реализация эндпоинтов регистрации и логина (выдача JWT токенов).
  - [ ] Разработка Dependency (`get_current_user`) для защиты закрытых роутов.

- **🏁 Результат (DoD):** Swagger UI доступен, можно зарегистрироваться, получить токен и дернуть защищенный тестовый роут. Настроен локальный MinIO и БД.

В ответ на propose система формирует не один документ, а сразу четыре взаимосвязанных артефакта:

  • proposal.md — намерение: зачем и что именно мы меняем.
  • design.md — архитектурное решение: как технически будет реализовано изменение.
  • specs/.../spec.md — контракт поведения: каким должно быть поведение системы после изменения.
  • tasks.md — план работ: конкретный список задач для реализации.

Именно эти четыре документа, а не сам пункт ROADMAP.md, становятся источником истины для агента на время работы над вехой. Их стоит просмотреть перед тем, как двигаться дальше — так же, как вы проверяли PROJECT.md и DATAMODEL.md на этапе анализа.

Когда предложение устраивает, запускается реализация:

/opsx-apply

Агент реализует веху в коде, опираясь на зафиксированные design.md, spec.md и tasks.md. Когда работа завершена, изменение архивируется:

/opsx-archive

После архивации переходим к следующей вехе — и повторяем цикл propose → apply → archive заново. Принцип — одна веха за одну итерацию: это не даёт агенту распыляться сразу на весь проект и позволяет проверять результат на управляемых, законченных кусках функционала, а не после того, как реализован весь ROADMAP.md целиком.


Этап 3. Тестирование: проверка соответствия задуманному

Тестирование в этом подходе — это не только про отсутствие багов, но и про то, что реализованный функционал действительно соответствует тому, что описано в PROJECT.md и DATAMODEL.md.

Практический ориентир:

  • Проверяйте каждый пункт дорожной карты сразу после реализации, а не откладывайте тестирование на конец проекта — так дешевле исправлять несоответствия.
  • Сверяйтесь с пользовательскими сценариями из PROJECT.md: даже если код технически работает и покрыт unit-тестами, стоит убедиться, что он решает исходную задачу пользователя так, как она была описана.
  • Используйте автоматизированные тесты там, где это возможно — например, если в стеке зафиксирован pytest и pytest-asyncio, тесты должны появляться параллельно с кодом, а не постфактум.
  • Возвращайтесь к анализу, если тестирование вскрыло пробел. Если в процессе проверки выясняется, что какой-то сценарий вообще не был учтён на этапе анализа — это сигнал вернуться к SOURCE.md или PROJECT.md, а не просто «залатать» проблему точечным изменением в коде.

Frontend: тот же подход, но на основе backend-документов

После того как backend протестирован и работает так, как задумано, наступает очередь frontend-части. И здесь не нужно изобретать новый процесс — я прохожу тот же путь анализа, что и в самом начале, только с одним отличием: файл DATAMODEL.md для frontend не формируется, поскольку модель данных уже полностью описана и зафиксирована на стороне backend.

Формируем документы для frontend

Удобнее всего сделать это, не выходя из backend-проекта: агент уже знает контекст всей системы, поэтому можно прямо там попросить его сформировать PROJECT.md и ROADMAP.md для frontend-части — указав нужный стек (например, React, Vue или любой другой, который вы выбрали). После того как документы готовы и проверены, перенесите их во frontend-проект, в каталог /project.

Файл AGENTS.md

В корне frontend-проекта дополнительно создаётся файл AGENTS.md — он указывает агенту, где искать базовую документацию проекта:

## Базовая документация проекта.

- project/PROJECT.md - Описывает проект
- project/ROADMAP.md - ROADMAP
- project/openapi.json - API endpoints

Третий файл в этом списке — openapi.json — спецификация OpenAPI по эндпоинтам вашего backend. Она нужна агенту, чтобы понимать, какие API-запросы доступны, какие у них параметры и форматы ответов, и корректно реализовывать интеграцию frontend с backend. Получить её просто: она скачивается прямо со Swagger-документации backend-проекта.

Разработка через тот же цикл OpenSpec

Дальше всё повторяет уже знакомый процесс: в frontend-проекте заново инициализируется OpenSpec, и начинается итеративная работа по ROADMAP.md — веха за вехой, через цикл explore → propose → apply → archive. Разница в том, что теперь агент опирается не только на PROJECT.md, но и на спецификацию openapi.json — это позволяет ему реализовывать не просто интерфейс, а корректную интеграционную часть, которая действительно соответствует контракту вашего backend.

Когда все вехи реализованы и протестированы, вы получаете готовый продукт — именно тот, который описывали на самом первом шаге анализа, а не то, что агент «додумал» по пути.

Важный момент на будущее: даже после завершения основной разработки любые дальнейшие изменения в проекте — что для backend, что для frontend — стоит проводить по тому же сценарию OpenSpec: explore → propose → apply → archive. Это сохраняет дисциплину процесса и не даёт проекту со временем снова превратиться в хаотичный набор кода.


И ещё немного за рамками этой статьи

Помимо описанного процесса, у меня есть ещё три навыка (skills) для агентов, которые проверяют готовый сайт с трёх разных сторон: юридическую часть, SEO-оптимизацию и качество контента. Это отдельный слой проверки, который логично встраивается уже после того, как продукт разработан и протестирован по описанному выше циклу. Но это самостоятельная и довольно объёмная тема — расскажу о ней в отдельной статье.

Итог

Весь подход можно свести к одной идее: сначала спроектировать, потом строить, потом проверить, и на каждом шаге явно фиксировать решения в документах, к которым агент может обращаться. Это не избавляет от итераций — вы всё равно будете возвращаться к SOURCE.md и PROJECT.md, когда найдёте пробелы, — но эти итерации происходят на уровне документов, что значительно дешевле, чем переделывать уже написанный код.

Такой цикл — анализ → разработка → тестирование → (при необходимости) снова анализ — превращает работу с ИИ-агентом из непредсказуемого процесса в управляемый, где итоговый продукт действительно соответствует тому, что вы изначально задумали.

Поделиться