Глава 24

Task и Artifact образуют жизненный цикл работы

Task - это сердце A2A. Он хранит идентификатор, context, status, history и artifacts. Терминальные состояния завершают работу; interrupted-состояния позволяют запросить ввод или authentication. А Artifact - это материализованный результат, а не просто последнее сообщение: именно он, а не текст в чате, является тем, ради чего задача существовала.

Сам жизненный цикл проще всего увидеть как цепочку состояний.

  1. Message
  2. submitted
  3. working
  4. artifact
  5. completed

За этой линией стоит таблица состояний - каждое говорит клиенту, что делать дальше.

State · Класс · Что делает client

  • submitted - Active; Сохраняет taskId, ждет update
  • working - Active; Показывает progress, может cancel
  • input_required - Interrupted; Показывает вопрос и отправляет follow-up
  • auth_required - Interrupted; Проходит разрешенный auth flow
  • completed - Terminal; Валидирует artifacts
  • failed - Terminal; Классифицирует retry/escalation
  • canceled - Terminal; Не ожидает дальнейших updates
  • rejected - Terminal; Не повторяет без изменения запроса

Состояния делятся на три класса, и это деление определяет поведение клиента. Active (submitted, working) - клиент ждёт и показывает прогресс. Interrupted (input_required, auth_required) - клиент отвечает на вопрос или проходит auth. Terminal (completed, failed, canceled, rejected) - дальнейших обновлений не будет, и реакция на каждый терминал разная: валидировать artifacts, классифицировать retry, не повторять без изменения запроса.

Сам artifact в нашем примере несёт сразу два представления - Markdown для человека и JSON для кода.

TypeScript
    try {
      const review = reviewRelease(reference.service, reference.version);
      const artifact: Artifact = {
        artifactId: randomUUID(),
        name: "release-review.md",
        description: "Детерминированный отчёт о готовности релиза",
        parts: [
          {
            content: { $case: "text", value: reviewToMarkdown(review) },
            metadata: undefined,
            filename: "release-review.md",
            mediaType: "text/markdown"
          },
          {
            content: { $case: "data", value: review },
            metadata: undefined,
            filename: "release-review.json",
            mediaType: "application/json"
          }
        ],
        metadata: { decision: review.decision },
        extensions: []
      };

      eventBus.publish(AgentEvent.artifactUpdate({
        taskId,
        contextId,
        artifact,
        append: false,
        lastChunk: true,
        metadata: undefined
      }));

Пройти по состояниям вручную и почувствовать переходы помогает симулятор.

Интерактивная лаборатория 5

Симулятор A2A lifecycle

Events еще не опубликованы.
Artifact может обновляться по частям. При streaming сервер публикует artifact-обновления с семантикой append/lastChunk. Клиент собирает их по artifactId и не считает каждый chunk новым результатом - иначе один отчёт превратится в десяток.

Мы знаем, из чего состоит работа A2A-агента. Теперь соберём самого агента - и первое архитектурное решение здесь про то, что отделить от протокола.

Проверка знаний

A2A Task в состоянии input_required. К какому классу оно относится и что делает клиент?

Ссылки