/ Дневник курса / Урок 10 /

Протокол A2A: общий язык агентов, паспорт исполнителя и спор о зрелости

Зачем нужен слой «агент ↔ агент», как устроены паспорт агента и жизненный цикл задачи и почему протокол зрелый на синтаксисе, но сырой в управлении.

  • a2a
  • agent-interoperability
  • mcp
  • multi-agent
  • protocols

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

1. Зачем агентам общий протокол: арифметика связей

A2A (Agent2Agent) — открытый протокол делегирования задач между автономными агентами: один публикует, что умеет, второй поручает ему работу и следит за статусом. Нужен он там, где агентов больше одного и принадлежат они разным владельцам. Считать удобнее парами: связать четыре агента попарно — шесть интеграций, десять — 45, сотня — 4950, и у каждой пары свой формат сообщений и своя схема авторизации. Задачи такого вида принято называть N×M. Общий протокол ломает эту арифметику: каждый учит стандарт один раз, а не соседа.

каждый с каждым: n(n−1)/2        через протокол: n подключений

    A ─────────── B                  A           B
    │ ╲         ╱ │                   ╲         ╱
    │   ╲     ╱   │                    ╲       ╱
    │     ╲ ╱     │                     ╲     ╱
    │      ╳      │                      [A2A]
    │     ╱ ╲     │                     ╱     ╲
    │   ╱     ╲   │                    ╱       ╲
    │ ╱         ╲ │                   ╱         ╲
    C ─────────── D                  C           D

    4 агента → 6 связей              4 агента → 4 подключения
    10 → 45 · 100 → 4950             10 → 10 · 100 → 100
    свой формат и своя схема         одно обнаружение,
    авторизации у каждой связи       один формат
Рисунок — экономика связей: без общего протокола четыре агента дают шесть парных интеграций, десять агентов — 45, сотня — 4950, и каждая пара несёт свой формат и свою авторизацию; с общим протоколом каждый агент подключается один раз, и сотня агентов даёт сто подключений.

Слой «агент ↔ агент» включается на границе организаций: другая команда, другой вендор, другая платформа. Корпоративный агент хочет заказать анализ рынка у внешнего research-агента — и упирается в четыре вопроса, на которые собственная обвязка ответа не даёт: как передать задачу и забрать результат в предсказуемом формате; как следить за статусом исследования, которое идёт часами, а не секундами; как ограничить права, чтобы исполнитель сделал ровно то, о чём просили; как убедиться, что на том конце тот, за кого он себя выдаёт.

На эти четыре вопроса и отвечает A2A. Google анонсировал протокол весной 2025, а 23 июня 2025 передал в Linux Foundation под лицензией Apache-2.0. Спецификацию ведёт технический комитет из представителей восьми компаний: Google, Microsoft, Cisco, AWS, Salesforce, ServiceNow, SAP, IBM.

2. Вертикаль и горизонталь: агент к инструментам, агент к агенту

Два протокола делят пространство по направлению связи, и это устойчивее, чем сравнение списков возможностей. MCP (Model Context Protocol — стандарт подключения агента к внешним инструментам и данным) работает по вертикали: подаёт одному агенту инструменты, ресурсы, контекст. Его вопрос — «как агенту прочитать базу или вызвать API». Метафора — разъём USB-C: один порт, через который агент дотягивается до всего.

A2A работает по горизонтали: обнаружение, делегирование, статусы, артефакты между несколькими автономными агентами. Его вопрос — «как агенту поручить задачу другому агенту». У него и метафора другая, телефонная сеть: вы звоните абоненту, не зная и не спрашивая, что у него внутри.

        ваши инструменты                    его инструменты
        БД · API · файлы                    (вам не видны)
               │                                   │
               │ MCP — вертикаль                   │ MCP
               ▼                                   ▼
      ┌────────────────┐       A2A        ┌────────────────┐
      │   ваш агент    │ ←──────────────→ │  чужой агент   │
      └────────────────┘   горизонталь    └────────────────┘
                  «как поручить задачу другому агенту»
Рисунок — два направления связи: MCP уходит вертикально от агента к его инструментам и данным, A2A идёт горизонтально между агентами разных владельцев, и внутренности соседа при этом остаются закрытыми.

Спецификация формулирует это прямо: A2A и MCP — комплементарные протоколы для разных аспектов агентных систем. MCP описывает, как агенту воспользоваться конкретной возможностью, A2A — как агенты партнёрствуют и делегируют работу друг другу. Оба протокола живут под Linux Foundation, так что вопрос «кто кого вытеснит» снят и на уровне управления проектами.

Практический выбор укладывается в три строки:

Что нужно Чем решать
Локальная логика внутри одного процесса обычный вызов функции
Данные или инструмент для вашего агента MCP — вертикаль
Автономный агент чужой команды или вендора A2A — горизонталь

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

3. Паспорт агента: что в карточке и как её находят

Agent Card (карточка агента: JSON-документ, которым агент публикует свои возможности, требования к аутентификации и адреса для вызова) — точка входа во всё остальное. Каждый A2A-совместимый агент обязан её отдавать; клиент читает карточку до разговора и решает, годится ли исполнитель.

{
  "name": "Research Agent",
  "skills": [{ "id": "market-research", "description": "анализ рынка" }],
  "capabilities": { "streaming": true },
  "supportedInterfaces": [
    { "url": "https://api.acme.ai/a2a",
      "protocolBinding": "JSONRPC", "protocolVersion": "1.0" }
  ],
  "securitySchemes": { "oauth2": {} },
  "signatures": [{ }]
}

Канонический адрес — GET /.well-known/agent-card.json; суффикс подан на регистрацию в IANA. Логика та же, что у robots.txt: клиент знает, куда смотреть, без предварительной договорённости. Путь /.well-known/agent.json из ранних материалов действовал до версии 0.3, а теперь это легаси, то есть устаревший вариант, и на нём легко обжечься, копируя код из статей 2025 года.

Отдельно про supportedInterfaces: это массив интерфейсов в порядке предпочтения; каждая запись несёт url, protocolBinding (JSONRPC, GRPC или HTTP+JSON) и protocolVersion. Плоские поля url и preferredTransport из версий до 1.0 исчезли — ещё одна ловушка при чтении старых примеров.

Механизмов обнаружения в спецификации три, а не один (§ 8.2): well-known URI, реестры и каталоги агентов, прямая конфигурация адреса карточки. В корпоративном контуре обычно выигрывает второй — реестр даёт единую точку, где видно, кто вообще выставлен наружу.

И принципиальное свойство: карточка описывает агента снаружи, не раскрывая внутренностей. Спецификация закрепляет это в § 1 — агенты обмениваются информацией «without needing access to each other’s internal state, memory, or tools», без доступа к внутреннему состоянию, памяти и инструментам друг друга. Непрозрачность соседа здесь не ограничение, а требование к дизайну.

4. Задача как единица работы: восемь состояний и два способа получать обновления

Task (задача с уникальным идентификатором) — единица работы, которую один агент поручает другому; задача сама хранит своё состояние. Вокруг неё три объекта: Message — одно сообщение в диалоге с ролью user или agent; Part — наименьшая единица контента (TextPart, FilePart, DataPart); Artifact — результат, собранный из частей и неизменяемый после создания.

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

В версии 1.0 перечисление состояний содержит девять значений, но одно из них служебное (TASK_STATE_UNSPECIFIED) — содержательных восемь.

                        ┌──── клиент ответил ────┐
                        ▼                        │
  submitted ───────→ working ───────────→ input-required
      │                 │  │
      │                 │  └───────────→ auth-required
      │                 │                (клиент приносит права)
      │                 ▼
      │      completed · failed · canceled
      │      артефакт  · сбой   · отмена
      ▼
   rejected
   отказ на входе: «это не ко мне»
Рисунок — жизненный цикл задачи: из submitted путь ведёт либо в rejected (исполнитель не взялся), либо в working; оттуда задача уходит в переговорные состояния input-required и auth-required и возвращается обратно, а закрывается одним из трёх терминальных — completed с артефактом, failed или canceled.

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

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

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

5. Три паттерна общения и границы ответственности

Взаимодействий в протоколе три, и отличаются они тем, сколько ходов занимает договорённость. Запрос-ответ — короткая задача, один артефакт, клиент ждёт («переведи этот текст»). Делегирование — долгая работа, прогресс через streaming или push, клиент не висит на линии («сделай ресёрч рынка»). Переговоры — многоходовый обмен через состояние input-required («забронируй» → «нужны даты»).

Роль в A2A — функция в конкретной задаче, а не постоянное звание: тот же агент выступает клиентом в одном обмене и исполнителем в другом.

CLIENT AGENT              ОБЩАЯ ЗОНА (A2A)         REMOTE AGENT
─────────────────────────────────────────────────────────────────────
сформулировать задачу     версия протокола         честная карточка
выбрать по карточке       схема аутентификации     принять или отклонить
хранить свой контекст     что считать «выполнено»  работать в рамках skills
принять артефакт          кто пишет и хранит лог   не просить лишних прав
решить, доверять ли       что делать при failed    вернуть артефакт и статус
Рисунок — три зоны ответственности: клиент отвечает за постановку задачи, выбор исполнителя, свой контекст и доверие к результату; исполнитель — за честность карточки, работу в границах объявленных навыков и возврат артефакта; в общей зоне остаются версия протокола, схема аутентификации, определение «выполнено», журналирование и реакция на сбой.

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

6. Честность карточки: что закрывает подпись, а что нет

Утверждение «честность карточки — вопрос доверия, а не техники» верно на две трети. Разрыв идёт по трём уровням, и техника закрывает только первый.

УРОВЕНЬ                       ЧЕМ РЕШАЕТСЯ
────────────────────────────────────────────────────────────────────
Карточку не подменили         подпись JWS (RFC 7515) поверх
по дороге                     канонизации JCS (RFC 8785):
                              любая правка становится заметной

Карточку отдаёт тот,          ничем внутри протокола; нужна
за кого себя выдаёт           workload-identity (SPIFFE/SPIRE)
                              и авторизация в сервисной сети (mesh)

Навык заявлен честно,         ничем: репутация, тестовый прогон,
но выполняется плохо          проверка результата
Рисунок — три уровня честности карточки: подмену содержимого ловит криптографическая подпись поверх канонической формы JSON, привязку карточки к реальной рабочей нагрузке протокол не гарантирует вовсе, а качество заявленного навыка не проверяется никакой техникой.

Первый уровень — спецификация (§ 8.4) разрешает подписывать карточку по JWS (JSON Web Signature — стандарт подписи JSON-документа), причём перед подписью карточку обязательно приводят к канонической форме по JCS (RFC 8785, детерминированная сериализация JSON). Без канонизации подпись развалится на банальном переупорядочивании ключей.

Второй уровень Red Hat формулирует точнее всех: карточка несёт метаданные и подпись, но «nothing inherently ties that metadata back to the workload actually serving it at runtime» — ничто в самом документе не привязывает эти метаданные к процессу, который отдаёт карточку в рантайме. Их аналогия бьёт в цель: визитку с надписью «врач» может напечатать кто угодно. Что мешает вредоносной нагрузке в кластере опубликовать карточку «I am the Payment Processor»? Отсюда предложение привязывать карточку к утверждённой workload-identity через SPIFFE/SPIRE (выдача рабочей нагрузке проверяемого криптографического удостоверения) и разрешать вызовы по идентичности в сервисной сети. Сдвиг тут глубже, чем кажется: обнаружение идёт не по имени сервиса, а по навыку («найди агента, умеющего разбирать финансовые таблицы»), и старая модель «может ли сервис A звать сервис B» на это не ложится.

Третий уровень техникой не берётся. Агент может добросовестно заявить навык и делать его плохо. Это область репутации и проверки результата, а не криптографии.

7. Контроль межагентного обмена: доверие, права, аудит, политики

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

  • Доверие — кто звонит? TLS на транспорте, проверка каждого запроса по схеме из карточки (API-ключ, OAuth2, OpenID Connect, mutual TLS), подпись карточки против подмены.
  • Права — что можно? Наименьшие привилегии: авторизация по навыкам, действиям и OAuth-скоупам. Дополнительные доступы запрашивают отдельным ходом через auth-required, а не подсовывают в промпт.
  • Аудит — что произошло? Логи задач, статусов, артефактов и запросов. Терминальные состояния (completed, failed, rejected) — естественные точки аудита.
  • Политики — что запрещено? Какие навыки видны внешним клиентам, какие действуют лимиты, как проверять вебхук перед отправкой push, как изолировать исполнение.

Человек встраивается сюда штатно. Типовой поток: клиент читает карточку, получает токен доступа по схеме client credentials (машинная авторизация — клиент предъявляет свой идентификатор и секрет, человек тут не участвует), запрашивает данные — и прежде чем они уйдут, владельцу приходит push с запросом подтверждения. Пока владелец не ответит «да», токен не выдаётся, а сам факт одобрения попадает в аудит.

Особняком стоит agent session smuggling (подмешивание инструкций в уже установленную межагентную сессию) — единственный задокументированный класс атаки именно на A2A-обмен. Вредоносный агент прячет команды между обычными запросами и ответами; в разобранном исследователями сценарии доверенный агент-исследователь за несколько ходов диалога склоняет агента-клиента к несанкционированной биржевой сделке. Рычаг даёт сам характер обмена: сессия stateful — состояние живёт между ходами, и агенты помнят, о чём говорили минуту назад. Корень — презумпция доверия: агентов по умолчанию проектируют доверчивыми к соседям по контуру. Агент-самозванец (rogue-агент) опаснее вредоносного документа тем, что ведёт диалог, подстраивает стратегию и наращивает ложное доверие за несколько ходов.

Оговорка, без которой эту атаку нельзя цитировать: исследователи прямо пишут, что уязвимости в самом протоколе тут нет. Техника эксплуатирует неявные доверительные отношения и сработала бы в любом stateful-протоколе. Защита многослойная: человек в контуре на критичных действиях, криптографическая верификация удалённого агента, обнаружение инструкций не по теме через привязку к контексту задачи.

8. Спор о зрелости: что поддаётся проверке

Оценки готовности A2A расходятся радикально — от «протокол, на котором уже выпускают в продакшен» до «сырой и вообще замороженный проект». Спор разрешают факты — и не в пользу привычной рамки «зрелый или сырой».

Версия 1.0.0 вышла 12 марта 2026, дальше пошли патч-релизы. Тезис о «замороженном проекте» рассыпается при первом взгляде на репозиторий: a2aproject/A2A не архивирован, 270 коммитов за последние 52 недели, правки идут по существу спецификации, а не по косметике — в конце июля 2026 уточняли семантику скоупов для In-Task Authorization.

Тезис «Google в агентов не верит» не выдерживает проверки датой. 23 июня 2025 компания отдала в Linux Foundation спецификацию, SDK и инструментарий — с семью соучредителями и заявленным мотивом сделать протокол независимым от вендора и развиваемым сообществом («vendor-agnostic and community-driven»). Так снимают вендорную привязку, а не сворачивают направление.

Реальные внедрения фиксирует пресс-релиз Linux Foundation от 9 апреля 2026: более 150 организаций против 50 годом раньше, а число SDK выросло с одной реализации на Python до пяти, готовых к продакшену. Развёртывания идут в цепочках поставок, финансовых сервисах, страховании и IT-операциях.

Кто действительно выпустил, а не заявил. Microsoft: A2AAgent в Agent Framework оборачивает любой A2A-совместимый endpoint в обычный AIAgent, вызывается привычными RunAsync / RunStreamingAsync — при этом пакет Microsoft.Agents.AI.A2A ставится с флагом --prerelease, то есть работает, но в стабильный канал ещё не переехал. Copilot Studio подключается к внешнему A2A-агенту по сквозному сценарию и передаёт вместе с задачей контекстные метаданные. AWS добавил поддержку в Bedrock AgentCore Runtime.

А теперь сторона скептика. Она права, но не в том, на что указывает. В продакшен-разборах звучит претензия: между планировщиками нет стандартизованных протоколов обмена промежуточными статусами. Разрыв реальный — только он не внутри A2A, а над ним.

Cisco в том же пресс-релизе называет протокол «the syntactic layer» — слоем синтаксиса, который сделал обмен надёжным, и добавляет, что богатая семантика ещё впереди.

То же самое формально разбирает препринт arXiv:2606.31498: анализ пробелов (gap-анализ) пяти протоколов (MCP, A2A, ACP, ANP, ERC-8004) по шести измерениям управления показал, что голосования и права на особое мнение нет ни в одном из пяти, а совещательность либо отсутствует, либо в лучшем случае частична. Вывод авторов лучше привести дословно: управление сообществом агентов — «a missing architectural layer above current interoperability standards, not a missing feature within them». Недостающий архитектурный слой над стандартами, а не недостающая фича внутри них.

И последнее, практическое: переход с 0.3 на 1.0 сломал обратную совместимость. Материалы и код старше марта 2026 читайте с поправкой — имена операций, поля карточки и перечень состояний там другие.

Итог

  • A2A снимает задачу из разряда N×M: без него сотня агентов даёт 4950 парных интеграций, у каждой пары свой формат и своя авторизация; с ним — сто подключений.
  • MCP и A2A не конкурируют: первый тянет инструменты в агента по вертикали, второй связывает агентов по горизонтали; в живой системе стоят оба — и оба под Linux Foundation.
  • Карточка агента — контракт и точка входа: навыки, схема аутентификации, supportedInterfaces; канонический адрес /.well-known/agent-card.json, механизмов обнаружения три.
  • Восемь содержательных состояний задачи превращают делегирование в переговоры: input-required — уточнения, auth-required — штатный запрос прав, rejected — право сказать «не ко мне».
  • Подпись карточки доказывает, что документ не подменили, но не то, что его отдаёт настоящий владелец, — этот разрыв снимает workload-identity, а качество навыка не проверить ничем, кроме результата.
  • Протокол зрелый на уровне синтаксиса и внедрённый в проде; сырым остаётся слой договорённостей о смысле и управлении поверх него.

FAQ

A2A уже готов для продакшена?

На уровне обмена сообщениями — да. Версия 1.0.0 вышла 12 марта 2026, дальше идут патч-релизы; репозиторий активен, спецификацию правят по существу. Linux Foundation в апреле 2026 отчиталась о более чем 150 организациях, пяти готовых к продакшену SDK и развёртываниях в цепочках поставок, финансах, страховании и IT-операциях. Незакрытым остаётся слой выше протокола: коллективные решения, голосование и разрешение разногласий между агентами не описаны ни в одном из существующих стандартов интероперабельности.

Нужно ли выбирать между A2A и MCP?

Нет, они отвечают за разные направления. MCP подключает одного агента к инструментам, данным и ресурсам — это вертикаль, «как прочитать базу или вызвать API». A2A связывает независимых агентов между командами, фреймворками и организациями — горизонталь, «как поручить задачу другому агенту». Спецификация называет их комплементарными, и в реальной системе обычно работают оба: MCP внутрь агента, A2A наружу.

Где лежит карточка агента и что в ней должно быть?

Канонический адрес — /.well-known/agent-card.json, суффикс подан на регистрацию в IANA. Внутри: идентификация, перечень навыков с описаниями, поддерживаемые возможности вроде стриминга, схемы аутентификации и массив supportedInterfaces с адресом, биндингом протокола и версией для каждого интерфейса. Обнаружить карточку можно тремя способами: по well-known URI, через реестр агентов или по заранее прописанному адресу.

Что сломалось при переходе с версии 0.3 на 1.0?

Обратная совместимость. Операции tasks/send и tasks/sendSubscribe переименованы в SendMessage и SendStreamingMessage (REST-биндинги POST /message:send и /message:stream). Плоские поля карточки url и preferredTransport заменены массивом supportedInterfaces. Добавилось состояние auth-required, поэтому в старых разборах перечисляют семь содержательных состояний вместо восьми. Путь /.well-known/agent.json объявлен устаревшим.

Можно ли доверять подписанной карточке агента?

Подпись решает одну задачу из трёх. JWS поверх канонической формы JCS делает подмену заметной (свойство tamper-evident): изменить содержимое незаметно не выйдет. Но ничто в самом документе не связывает его с рабочей нагрузкой, которая его отдаёт, — для этого нужна отдельная workload-identity, например через SPIFFE/SPIRE, и авторизация вызовов на уровне сервисной сети. А качество заявленного навыка криптография не проверяет вовсе: здесь работают только тестовый прогон и репутация.

Что такое agent session smuggling и это дыра в A2A?

Это техника, при которой вредоносный агент подмешивает инструкции в уже установленную межагентную сессию, пряча их между обычными запросами и ответами. Исследователи Unit 42 показали сценарий, где доверенный агент за несколько ходов диалога склоняет агента-клиента к несанкционированной биржевой сделке. Уязвимости в самом протоколе тут нет — атака эксплуатирует презумпцию доверия между агентами и воспроизводится в любом stateful-обмене. Лечится человеком в контуре на критичных действиях, верификацией удалённого агента и обнаружением инструкций не по теме.

Когда A2A не нужен?

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

Источники

Числовые ориентиры в тексте — срез на начало августа 2026: число организаций, состав SDK и метрики репозитория меняются, а спецификацию активно правят. Имена операций, поля карточки и перечень состояний сверяйте с текущей версией текста спецификации, а не с материалами старше марта 2026.