ИИ-агенты · Автоматизация · Программирование · База данных · Архитектура29 сентября в 18:33 · 4 мин

Агентский ящик: Как избежать гонок состояний при передаче управления ИИ и человеку

Надежная координация между автономным ИИ-агентом и человеком в контуре принятия решений требует более простой очереди сообщений. Архитектура «Агентского ящика» (Agent Inbox), реализованная на базе конечных автоматов и атомарных проверок целостности данных, устраняет критические гонки состояний, обеспечивая предсказуемость переходов и защиту от конкурентных записей.

# Надёжная координация в контуре ИИ и человека: как избежать гонок состояний

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

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

Конечный автомат вместо цепочки сообщений

Фундаментальная ошибка многих систем заключается в том, что они рассматривают взаимодействие как поток событий. В *Agent Inbox* каждая задача (строка доски) рассматривается как состояние в конечном автомате. У каждой задачи в любой момент времени есть единственный владелец. Переходы между состояниями происходят не автоматически, а через строго определённые операции с маркерами версии.

Система поддерживает шесть основных состояний: tracked (отслеживается), partial (частично выполнена), missing (данные отсутствуют), na (не применимо), done (завершено) и blocked (блокировано). Состояние blocked — критическое для процесса принятия решений: именно здесь управление передается человеку. Важно различать момент, когда человек закончил работу (handled_at), и момент, когда агент подтвердил получение этого результата (outcome). Если агент упал до обработки ответа, строка остается в статусе blocked с заполненным handled_at. Это позволяет системе найти все ответившие, но не обработанные задачи простым запросом.

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

Двойной канал и приоритет обработки

Человек может дать ответ двумя путями: непосредственно в чате или через интерфейс «ящика». Простой перезаписи данных здесь недостаточно. Система использует асимметричное правило приоритета, защищенное атомарными операциями.

1. Приоритет ящика (Inbox): Если ответ записан через основной интерфейс, он безусловно заменяет предыдущие версии и сбрасывает метку просмотра (reply_seen_at). Это гарантирует, что актуальные данные всегда находятся в фокусе внимания системы. 2. Ограничение чата: Ответ, сохраненный из чата, может быть записан только в том случае, если ответ в системе еще не существует или он уже был «забрит» на обработку (reply_seen_at IS NOT NULL).

Это предотвращает ситуацию, когда ответ в чате перезапишет актуальный ответ из ящика до того, как агент успеет его взять. Все обновления выполняются одним транзакционным UPDATE с условием, исключая «окно уязвимости», когда между чтением и записью человек мог бы изменить свой ответ.

Атомарность и защита ревизий

Чтобы избежать создания противоречивых задач для одной зависимости (двойных карточек), действует инвариант: один вопрос — одно место взаимодействия. Если контекст задачи изменился (например, возникла новая информация), агент не создает новую строку. Он обновляет существующую, увеличивая версию (revision).

Ключевым механизмом защиты от гонок служит операция board_advance. Она реализует принцип Compare-and-Swap (CAS) на уровне приложения. Чтобы перевести доску на следующий шаг, агент должен предоставить ожидаемую версию строки (expected_revision) и версию самой доски (board_version). Если любое из этих значений изменилось с момента последнего чтения, операция завершается ошибкой, требуя пересчета состояния.

Хотя база данных SQLite с режимом WAL (Write-Ahead Logging) обеспечивает быструю запись и параллельное чтение, она не защищает от логических гонок. Например, если два процесса одновременно проверяют условие и затем пытаются записать результат, возможна потеря данных. Именно описанные выше проверочные блоки внутри транзакций (board_advance) и атомарные условия при обновлении ответов обеспечивают целостность данных.

Что остается вне архитектуры

Модель *Agent Inbox* решает ключевые проблемы координации, но есть еще несколько вызовов. Текущая реализация работает с локальными файлами SQLite. Поддержка общей распределенной базы данных и сетевой аутентификации пока находится в разработке. Кроме того, механизм восстановления контекста при удаленном ответе требует дополнительных решений для полной синхронизации сессий агента.

Тем не менее, базовая модель доказала свою эффективность: исправление проблем с аннотациями, введение типа ответа для уточнения (clarify) и расширение правил приоритета показали, что четкое владение состоянием критически важно. Вне зависимости от сложности модели, контракты между агентом и человеком должны быть явными, с каждым переходом статуса и маркером подтверждения.

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

Первоисточники

Habr AI ↗
← Вернуться в эфир