Код
— это граф.
AOA — Python-фреймворк, где бизнес-операция — стержень всей архитектуры. Операция сама объявляет, кто имеет право её выполнять, от чего она зависит и что произойдёт при сбое; из каталога операций собирается граф, который проверяет сам себя и не даёт инфраструктуре смешаться с бизнес-логикой. Нарушение ловится на старте, а не в проде через три недели.
pip install aoa-action-machine01 — Обзор
Архитектура живёт в коде.
Не в головах и не в документах.
Системы гибнут не от багов — а от того, что их со временем перестают понимать, когда команда меняется, а сложность растёт. Нас учат писать код, применять паттерны, следовать стилям — но не учат, как управлять сложностью и сохранять систему читаемой через год, два, пять. Каждая минута, потраченная на разбор «что здесь происходит», — это минута, украденная у развития.
В AOA принят другой подход: он переносит знания об архитектуре и системе из головы и устаревающих документов — в код, как машиночитаемое намерение: исполняемое, проверяемое, наблюдаемое.
Спроектируйте модель, затем код.
Сущности, их связи и жизненный цикл объявляются как чистая доменная модель — не привязанная к ORM или конкретной базе. Целостность всей модели проверяется на старте.
Спроектировать модель →Один класс — вся операция.
Роли, шаги, компенсации, ошибки, кеш и зависимости объявлены в одном месте: Params на входе, Result на выходе и ни одной боковой двери между ними.
Action X-Ray.
Встраивает видимость debugger в архитектуру: ход операции и её состояние на каждом шаге можно наблюдать online даже в production — без остановки процесса.
Открыть Action X-Ray ↗Порты гексагональной архитектуры, не зависимости.
@depends / @connection / @context_requires объявляют порты Action — адаптеры подключаются снаружи. box.resolve(T) отдаёт только объявленное.
Подменяйте мир, а не код.
Настоящий пайплайн выполняется без изменений — но на подменённом мире: пользователе, моках, контексте. Что здесь прошло, то и работает в продакшене.
02 — Maxitor
Граф выше — настоящий.
Вот инструмент, который его рисует.
Каждый domain, роль и зависимость становятся узлом в момент импорта — четыре разных представления одной и той же работающей системы, и все они — неотредактированные экспорты.
03 — Возможности
Больше, чем пайплайн.
Один и тот же объявленный граф питает кэширование, бизнес-события, observability и агентные фреймворки — без единой строчки клеевого кода.
Машина, которая их исполняет.
Каждый Action запускает одна машина: роли, кеш, события и откаты — её работа.
Кэш, объявленный.
cache_key сразу ведёт к результату; при промахе запускается аспект, а on_cache_write сохраняет значение.
События — это факты, а не строчки лога.
box.info(Channel.business, …) порождает типизированный факт — его читают и Maxitor, и OCEL, и дашборды.
Observer не может вмешаться.
Уберите все observer — поведение не изменится. Телеметрия — это гарантия, а не надежда.
Одно место, куда стекаются ошибки.
Единственный обработчик в конце пайплайна решает, что операция вернёт после сбоя.
Саги откатываются сами.
Сбой разворачивает завершённые шаги в обратном порядке; откат объявлен рядом со шагом.
Сначала RBAC. Потом — ABAC, всё глубже.
check_roles — чистый RBAC: есть ли роль. grant.when / guard= — лёгкий ABAC по вызову. access_decide() — сложный ABAC: объект и факт.
Domain и Role — карта системы.
Domain — точка сборки операции: граф, матрица доступа, визуализация. Role несёт полномочия через наследование. Вместе они и есть эта матрица.
04 — Расширение
Ядро маленькое.
Экосистема — нет.
Тот же объявленный граф подключает операцию к внешнему миру: агентным фреймворкам, очередям, интерфейсам, наблюдаемости. Ядро не растёт — растёт то, что вокруг него.
Типизированный узел в LangGraph.
LangGraphController встраивает Action в агентный граф — те же контракты, тот же откат.
Один Action. Любой фронт.
HTTP-маршрут и вызов AI-инструмента — это одна и та же операция с одними и теми же гарантиями.
OCEL/OCPM — настоящий процесс, а не диаграмма.
Каждый запуск уже даёт lifecycle events. Process mining видит по ним настоящий процесс и вовлечённые сущности — а не однажды нарисованную диаграмму.
OTel — те же события, трейсом.
Тот же плагин, что строит online-проекцию Action X-Ray, отдаёт события в OpenTelemetry: один источник — трейсы и живой запуск разом.
Intent-Based UI — не булево, а вердикт.
Маршрут → типизированная возможность: verdict() объясняет отказ, call() вызывает. Один контракт — React, mobile, Flet.
Digital twin
Actom объединяет сущность, поведение и агента в одной декларации — актор с состоянием, наблюдаемый через Action X-Ray. Файлы становятся графом-двойником системы.
05 — Концепции
Пять тем.
Каждая станет отдельной страницей.
Пять самостоятельных углов на одну систему — от грамматики деклараций до места AOA среди других фреймворков.
01
Принудительная грамматика
Грамматика превращает каждое правило в объявление (@check_roles, @depends, средства проверки, именования); при импорте эти объявления объединяются в граф — таким образом, код является спецификацией, а граф — это его машиночитаемая форма: проверяется при запуске, рисуется в Maxitor, отслеживается Action X-Ray — а не документация, которая плавает где-то рядом с кодом.
02
Конституция AOA
Восемь примитивов и набор обязательных деклараций — не стиль оформления, а закон, который машина проверяет при каждом импорте. Нарушить его тихо нельзя: несоответствие останавливает запуск, а не всплывает в проде.
03
Разделение бизнес-логики и инфраструктуры
Action знает домен и правила; как достучаться до Postgres, Kafka или стороннего API, знает адаптер за интерфейсом Gateway или Resource. Бизнес-код не импортирует драйверы напрямую — граница проходит по декларации, а не по соглашению между разработчиками.
04
Принципы интенционально-ориентированного программирования
Код объявляет намерение — что должно произойти и при каких условиях, — а не последовательность вызовов конкретных библиотек. Реализация подставляется через порты (@depends, @connection) и может смениться, пока намерение остаётся прежним.
05
Сравнение с другими фреймворками
FastAPI и Django дают маршрутизацию и ORM, но не проверяют роли, зависимости и переходы состояний при импорте. LangGraph явно строит граф, но для оркестрации шагов LLM, а не бизнес-операций. AOA ближе к обоим сразу — исполняемый граф прикладной архитектуры, а не только транспорт или пайплайн модели.
06 — Практические рецепты
Одна задача.
Один рецепт.
Ориентированы на задачу, а не на обучение — вы уже знаете, что строите. Здесь сказано, как.
Скелет Action: Params, пайплайн аспектов, чекеры, подключения.
Руководство по выбору примитива, который действительно подходит под вашу задачу.
Оберните базу данных, очередь или SDK в управляемую, инжектируемую зависимость.
Откройте доступ к существующим Action по новому протоколу, не трогая их.
Подключите другой backend кэша к cache_key / on_cache_write.
Наблюдайте за событиями жизненного цикла машины, без права вмешиваться.
Подключите собственную схему аутентификации к @check_roles.
Направьте box.info / box.warning туда, где на самом деле живут ваши логи.
Объявите новую грамматику участия, к которой смогут подключаться другие примитивы.
Добавьте собственный срез к тому, что Action может видеть о вызове.
Постепенно переносите существующую кодовую базу, Action за Action.
07 — faq
Вопросы — ответы.
Разве это не просто Clean Architecture с кучей декораторов?
Разница — в контроле. Clean Architecture — это набор соглашений, которые ревьюер проверяет вручную. Контракты AOA — @check_roles, @depends, чекеры state — проверяются машиной до запуска операции, а не тем, кто вспомнил посмотреть.
Нужно ли переписывать существующее приложение на FastAPI или Django?
Нет. aoa-fastapi-adapter открывает существующие Action как обычные маршруты. Вы внедряете AOA Action за Action, а не фреймворк за фреймворком.
Сколько стоит пайплайн аспектов во время выполнения?
Каждый аспект — это обычный async-вызов: без сериализации, без границы процесса. Цена — это проверки, которые вы сами запросили, а не фреймворк вокруг них.
Нужен ли Maxitor, чтобы использовать AOA?
Нет. Maxitor читает те же Domain, Role и Action, которые вы уже объявили, — это просмотрщик, а не зависимость. AOA работает и без него.
Чем @compensate отличается от транзакции базы данных?
Транзакция откатывает одно хранилище данных. @compensate откатывает бизнес-операцию, которая могла затронуть платёжный шлюз, почтовый сервис и базу данных — а у них нет общей границы транзакции.
Когда AOA — не тот инструмент?
Для скрипта, разового CLI-инструмента или сервиса с одной операцией и без требований к комплаенсу — правильным выбором будут обычные функции.
⭐ Если вам нравится AOA, поставьте звезду на GitHub и присоединяйтесь к обсуждению в GitHub Discussions.
