или Как локально правильные .md-спецификации и агенты могут вместе создать неправильную систему
Каждая команда описала свой сервис, каждый агент точно выполнил локальную спецификацию, все контракты прошли проверку — а сквозной процесс всё равно развалился. Проблема не обязательно в коде: часто у системы нет общего контекста, владельца инвариантов и правил частичного отказа.
Агентный SDD особенно убедительно выглядит внутри одного сервиса: есть локальный spec.md, контракт, кодовая база и тесты. Но распределённая система живёт не внутри сервисов, а между ними. Именно там теряются бизнес-контекст, порядок событий, ответственность за итоговый статус и правила компенсации.
Каждый сервис правильный. Система — нет
Представим оформление заказа. Один агент работает с сервисом заказов, второй — с платежами, третий — со складом, четвёртый — с доставкой. У каждого есть свой spec.md, API-контракт и критерии приёмки.
Сервис заказов создаёт заказ. Платёжный сервис списывает деньги. Склад резервирует товар. Доставка создаёт заявку. Все локальные тесты проходят.
Но что произойдёт, если деньги списаны, а товар не зарезервирован? Кто решит, что процесс завершился неуспешно? Кто запустит возврат? Сколько ждать запоздавшее событие? Какой сервис владеет итоговым статусом?

Внимание: РИСК
Каждая команда может выполнить свою спецификацию, а клиент всё равно получить двойное списание, вечный промежуточный статус или заказ без резерва. Формально ответственного за ошибку может не оказаться.
Граница контекста агента становится архитектурной границей
Агент видит только тот контекст, который ему предоставили. Если в его рабочую область входят payment/spec.md, payment/openapi.yaml и исходный код платежного сервиса, он не может надёжно учитывать жизненный цикл заказа, правила склада и ожидания доставки.
Сильная модель не восполняет отсутствующий контекст. Она может предположить типичное поведение, но такое предположение и есть скрытое архитектурное решение.

Внимание: КОНФЛИКТ
Чем уже контекст, тем безопаснее область изменений и дешевле работа агента — но тем хуже он понимает сквозной процесс. Чем шире контекст, тем больше устаревших, противоречивых и конфиденциальных данных попадает в его рабочую область.
Автономия команд против целостности процесса
Микросервисная архитектура строится вокруг автономии. Команда владеет сервисом, самостоятельно выбирает детали реализации и отвечает за его эксплуатацию. SDD, напротив, требует явно зафиксировать ограничения, которые нельзя нарушать.
Если центральная функция подробно проектирует каждый межсервисный шаг, команды теряют автономию, а архитекторы становятся bottleneck. Если каждая команда описывает только свой компонент, никто не гарантирует целостность процесса.
“Проблема решается не максимальной централизацией, а разделением локальных решений и системных инвариантов.”
Над сервисными спецификациями нужен отдельный слой
Для критичных сквозных сценариев необходим общий набор .md-файлов. Он не должен дублировать локальные OpenAPI и spec.md. Его задача — описать отношения между сервисами и правила, которые нельзя вывести из одного контракта.
/processes/order-fulfillment/ |
Вариант структуры: общий контекст процесса хранится отдельно и ссылается на локальные спецификации.
В process.md фиксируются цель, участники, владелец результата и основные состояния. В invariants.md — условия, которые нельзя нарушать. В failure-scenarios.md — тайм-ауты, повторные события, нарушение порядка и компенсации. В acceptance-criteria.md — сквозные проверки.
Внимание: РИСК
Если общая спецификация просто повторяет детали сервисов, она быстро устаревает. В ней должны оставаться только системные решения: владелец состояния, границы транзакции, гарантии доставки, правила повторов и компенсаций.
Агенту нужен управляемый пакет контекста
Агенту сервиса не требуется весь корпоративный репозиторий. Ему нужен собранный для конкретной задачи пакет: локальная спецификация, релевантные системные инварианты, контракты зависимостей, общие политики и явные ограничения области изменений.

Такой пакет должен формироваться воспроизводимо. Иначе два агента, запущенные разными командами, могут получить разные версии одного process.md или разные наборы архитектурных правил.
каждая задача ссылается на конкретные версии спецификаций;
агент видит только релевантные разделы общего контекста;
устаревшие документы исключаются или помечаются явно;
область допустимых изменений задаётся списком каталогов и файлов;
противоречие между источниками останавливает реализацию и формирует вопрос.
OpenAPI и AsyncAPI должны описывать одну реальность
Сквозной процесс часто начинается REST-вызовом, а продолжается событиями. OpenAPI и AsyncAPI при этом ведут разные команды и хранят в разных репозиториях. Формально оба контракта валидны, но статусы, идентификаторы и версии постепенно расходятся.

Для агента это особенно опасно: он может построить реализацию по более подробному артефакту и не заметить, что другой контракт описывает иной жизненный цикл. Поэтому общая спецификация должна связывать синхронную и асинхронную части через единую терминологию, correlation-id, модель статусов и правила публикации.
Внимание: КОНФЛИКТ
Поставщик хочет менять локальную модель независимо. Потребители событий хотят стабильную семантику. Без владельца сквозной модели спор превращается в несовместимые версии API и событий.
Transactional Outbox: паттерн или инвариант?
Типичный сервис сначала сохраняет данные в базе, затем публикует событие. Если запись прошла, а публикация нет, другие участники не узнают об изменении. Если событие отправлено до фиксации транзакции, потребитель может запросить ещё несуществующие данные.
Архитектор может потребовать Transactional Outbox. Команда — возразить, что это вмешательство в реализацию. Конфликт снимается, если разделить гарантию и механизм.
ИНВАРИАНТ |
Изменение бизнес-состояния и регистрация события не должны расходиться. Конкретный механизм может выбрать команда, если он доказывает выполнение этой гарантии. |
В SDD системная спецификация фиксирует требуемое свойство, а локальный план описывает технологическую реализацию. Агент может предложить Outbox, транзакционный журнал или другой механизм, но не вправе ослабить гарантию.
Кто владеет сквозной спецификацией
У локального spec.md обычно есть команда-владелец. У сквозного процесса ответственность часто размыта между продуктом, архитектором и несколькими системными аналитиками.
Рабочая модель требует владельца итогового результата. Он не проектирует каждый endpoint, но имеет полномочия утверждать системные инварианты, разрешать конфликты и принимать решение о допустимом риске.
архитектор обеспечивает целостность и непротиворечивость ограничений;
системные аналитики поддерживают модели сценариев и состояний;
команды сервисов отвечают за локальные спецификации и реализацию;
владелец процесса принимает решение при конфликте сроков, риска и автономии.
Внимание: РИСК
Совместная рабочая группа без одного владельца хорошо обсуждает проблему, но плохо принимает решения. Агент при этом продолжает работу с последней формально доступной версией контекста.
Проверять нужно на трёх уровнях
Линтер OpenAPI не обнаружит нарушение распределённой транзакции. Проверка должна быть многослойной.
1. Контракт: форматы, обязательные поля, безопасность, обратная совместимость.
2. Сервис: реализация API, локальная идемпотентность, публикация событий, негативные сценарии.
3. Процесс: частичные отказы, повторы, нарушение порядка, компенсации и восстановление после сбоя.
Третий уровень самый дорогой, поэтому его следует применять к критичным процессам, а не ко всем интеграциям. Агент может генерировать сценарии и тестовые данные, но организация должна определить, какие отказовые режимы являются обязательными для приёмки.
Риск чрезмерной централизации
Обнаружив разрывы контекста, легко создать единый комитет, общий репозиторий и обязательное согласование каждого изменения. На коротком горизонте качество вырастет. Затем центральная функция станет узким местом, а команды начнут создавать временные API и теневые интеграции.

Централизовать стоит системные инварианты, общие политики и модель сквозного результата. Детали реализации, внутренние структуры и оптимизации должны оставаться у команд.
Минимальная практическая модель
1. Выбрать критичный сквозной сценарий, а не пытаться сразу описать весь ландшафт.
2. Назначить владельца итогового состояния и системных инвариантов.
3. Создать process.md, invariants.md и failure-scenarios.md.
4. Связать их с локальными spec.md, OpenAPI и AsyncAPI конкретными ссылками и версиями.
5. Формировать для каждого агента воспроизводимый пакет релевантного контекста.
6. Добавить сквозные acceptance criteria и тесты частичных отказов.
7. Отслеживать расхождение design-time спецификаций и production-поведения.
Вместо вывода
Агентный SDD хорошо работает внутри ясной границы. Но микросервисная система определяется не только компонентами, а отношениями между ними. Именно в этих отношениях находятся распределённое состояние, неопределённость, повторы и конфликт владельцев.
Поэтому зрелая модель должна хранить не только сервисные .md-файлы, но и небольшой набор сквозных спецификаций, которые задают общий контекст и системные инварианты для всех агентов.
“Каждый агент может выполнить свою задачу правильно. За правильность системы всё равно должен отвечать человек.”