A2A Task Lifecycle

Как выглядит единица работы, переданная чужому агенту: объект Task с уникальным идентификатором, который проходит через фиксированный набор состояний. По статусу клиент понимает, ждать ли ещё, забирать результат или разбираться с отказом.

Словарь протокола

Четыре объекта, из которых собирается любое взаимодействие:

  • Task — единица работы с уникальным ID. То, что один агент поручает другому. Хранит своё состояние.
  • Message — одно сообщение в диалоге между клиентом и исполнителем. Имеет роль (user или agent) и состоит из частей.
  • Part — наименьшая единица контента: TextPart, FilePart (байты или ссылка), DataPart (структурные данные, например формы).
  • Artifact — результат задачи, собранный из частей. Неизменяемый: после создания не редактируется. Одна задача может вернуть несколько артефактов, а при стриминге части дописываются по мере готовности.

Разделение на Message и Artifact важнее, чем кажется: переписка и результат живут отдельно, поэтому результат можно забрать и передать дальше, не таща за собой всю историю диалога.

Состояния задачи

Состояние Что означает
submitted Задача принята, работа ещё не началась
working В процессе
input-required Исполнителю нужны уточнения — точка переговоров
auth-required Нужна авторизация; исполнитель делегирует её получение клиенту
completed Успешно завершена, артефакт готов
failed Сбой в процессе выполнения
rejected Отказ на входе: агент не берётся за задачу
canceled Отменена клиентом

Отличие rejected от failed — не формальность. Первое означает, что исполнитель посмотрел на задачу и сказал «это не ко мне», второе — что взялся и сломался. Реакция клиента разная: в первом случае искать другого исполнителя, во втором ретраить или эскалировать.

Состояние input-required превращает протокол из «выстрелил и жди» в переговорный: многошаговое взаимодействие с уточнениями укладывается в одну задачу, а не в цепочку из нескольких.

Рядом стоит auth-required — механизм In-Task Authorization (§7.6). Исполнитель, упёршийся в нехватку прав, не падает с ошибкой, а перекладывает получение авторизации на клиента и ждёт. Практически это значит, что запрос доступа к чужой системе — штатная ветка сценария, а не сбой. В материалах до версии 1.0 этого состояния нет, поэтому в старых разборах перечисляют семь состояний вместо восьми.

Как приходят обновления

Два механизма, и выбор между ними — архитектурное решение:

  • Streaming (SSE) — исполнитель шлёт события по мере продвижения: обновления статуса и дописываемые части артефакта. Клиент подписывается методом SendStreamingMessage (REST-биндинг POST /message:stream) и не опрашивает сервер. Имя tasks/sendSubscribe из ранних версий устарело: в 1.0 операции переименованы в SendMessage и SendStreamingMessage.
  • Push-уведомления — исполнитель сам стучится на вебхук клиента. Годится, когда задача долгая и держать соединение бессмысленно.

Транспорт под этим — JSON-RPC 2.0 поверх обычного HTTP, то есть ничего экзотического: метод, параметры, идентификатор для корреляции.

Чем это похоже на чекпоинты

Прямая параллель: статусы задач и промежуточные обновления — по сути те же чекпоинты и апдейты состояния, что в LangGraph Checkpointers, только работающие по сети между чужими агентами. Разница в том, что здесь нет общего хранилища состояния: каждая сторона держит своё, а синхронизируется через статусы.

Три развилки, которые протокол оставляет вам

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

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

Реакция на failed у чужого агента. Выбор между ретраем, сменой исполнителя и эскалацией определяется не предпочтением, а тем, что означает отказ: транзиентная ошибка на стороне исполнителя лечится повтором, отказ по существу задачи повтором не лечится и требует другого исполнителя или человека. Поскольку чужой агент причину обычно не сообщает достоверно, безопасная политика — один повтор с выдержкой, затем смена исполнителя, затем эскалация; бесконечный ретрай по чужому failed превращается в распределённый цикл, который никто не видит целиком.

Сколько держать задачу в auth-required. Бессрочное ожидание накапливает висящие задачи и удерживает ресурсы, поэтому таймаут нужен всегда; вопрос только в его величине. Она задаётся тем, кто приносит авторизацию: если человек в интерактивном сценарии — минуты, если фоновая система с расписанием — часы. По истечении задача переводится в терминальное состояние с явной причиной, а не удаляется молча: иначе инициатор не отличит «не дождались» от «потерялось».

Связано с

  • Agent2Agent Protocol — протокол целиком
  • Agent Card — как выбирается исполнитель до постановки задачи
  • LangGraph Checkpointers — аналогия между статусами задачи и чекпоинтами графа
  • Human in the Loop — состояние input-required как штатная точка входа человека