Учебник

Как один AI-агент находит другого: Agent Registry, A2A Agent Card и JSON Capability Discovery

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

Прошлая заметка, разбор полей Agent Card, раскрыла обязательную таблицу 1.0. Сегодня поля не заполняем заново и не повторяем, почему Registry — каталог. Следующий вопрос оркестратора: как из фразы «нужен коллега, который классифицирует возвраты» дойти до вызываемой Card? Официальный ответ — на A2A Agent Discovery: три стратегии, одна Card. Спецификация не задаёт API запроса курируемого каталога — см. Considerations на той же странице. Каталог Google Cloud — одна реализация; форму сверяйте с Registry JSON schemas. Этот текст идёт по прыжкам. Боковое делегирование против вызова инструментов вниз — в A2A vs MCP; слой не повторяем.

Открытие — не протокол. Находят Card

A2A стандартизирует самоописание, не телефонную книгу. Удалённый агент пишет способности JSON-визиткой. Клиент по ней решает, подходит ли, как подключаться, какую Task слать. Метод зависит от среды: публичная сеть, корпоративный каталог, жёсткий URL на ноутбуке. Все три могут привести к одной Card. Назвать «открытие» ещё одним разговорным протоколом — и ревью сразу уйдёт в сторону. Протокол по-прежнему A2A. Меняется дверь в well-known или в каталог.

Официальная страница открытия в «Role of the Agent Card» всё ещё говорит верхнеуровневый url языком 0.3. Новые карты — 1.0: точка входа в supportedInterfaces. См. что нового в v1.0. Если прыжок читает старое поле, это не главный контракт 1.0. Как писать поля — в прошлой заметке. Сегодня только: каким прыжком карта попала в руки и какие ключи проверить первыми.

Успешный поиск — не разрешение на tools/call. Напротив по-прежнему непрозрачный агент. Выбираете skill, выбираете интерфейс, отправляете Task. Считать попадание поиска таблицей функций — и многоходовые уточнения разорвут arguments. Как прыжок MCP проверяет параметры — во внутренней статье про Schema. Сегодня останавливаемся на «кого нашли и почему верим, что он это сделает».

Стратегия Что уже известно Следующий прыжок
Well-known URIДомен или хостGET /.well-known/agent-card.json
Курируемый каталогКлючевые слова / теги навыкаСпросить каталог, затем снять Card или ссылку
Прямая конфигурацияURL или вся картаПропустить поиск, читать карту

Три официальные стратегии: выбрать дорогу, потом идти

Well-known подходит открытому агенту или открытию, когда вы контролируете имя хоста. Путь по RFC 8615: https://{agent-server-domain}/.well-known/agent-card.json. Клиент знает домен или выводит его, шлёт HTTP GET, получает JSON. Реализация простая, хорошо автоматизируется. Если на визитке чувствительные навыки или внутренний URL, сам GET нужно аутентифицировать. Внутреннюю точку не вешают голой в открытую сеть.

Курируемый каталог подходит предприятию или рынку: промежуточный сервис собирает Card, клиенты спрашивают по skills, tags, provider, capabilities, каталог возвращает карты или ссылки. Выигрыш — управление и поиск по способности. Цена — кормить каталог. A2A этот API не задаёт. Google Agent Registry, общинный registry и свой каталог пишут форму запроса каждый сам. Не проверяйте трёх поставщиков одной «универсальной discover JSON».

Прямая конфигурация подходит тесной связке, закрытому агенту, ноутбуку. URL карты живёт в переменной окружения, файле или закрытом API. Связь статична — это самый дешёвый путь. Карта сдвинулась — клиенты должны сдвинуться. В проде считать «жёстко на ноутбуке» единственной поверхностью открытия — это записная книжка 2025-го. Три дороги могут сосуществовать: каталог ищет кого, well-known читает визитку, даже если каталог упал, конфигурация сеет пару устойчивых хостов при старте.

Есть имя хоста: GET well-known

Самый чистый прыжок — три шага. (1) Получить домен, например returns.agents.example.com. (2) GET https://returns.agents.example.com/.well-known/agent-card.json. (3) Ответ — Card, прошедшая схему 1.0. Неверный путь, внутренний алиас вместо HTTP, несовпадение имени в сертификате — в тикете будет «открытие не удалось». Карта может быть целой. GET не долетел.

Спецификация просит заголовки кэша на точке Card. Cache-Control: max-age=… не даёт промежуточным узлам и клиентам каждый раз снимать полную карту. ETag может быть version или хешем содержимого. После истечения — условный запрос (If-None-Match), не безусловный GET. Нет заголовков от сервера — клиент может поставить короткий default, но не кэшировать навсегда карту, у которой skills могут смениться.

Публичной карте достаточно, чтобы оркестратор мог выбрать. Чувствительные навыки и вторая внутренняя точка — на аутентифицированную расширенную карту. Вторую копию снимаете, только если capabilities.extendedAgentCard истинно. Прыжок открытия не должен предполагать расширенную карту до аутентификации. Каталог, который отдаёт разные Card по личности, и одна well-known карта на всех — две модели раскрытия. В ревью пишите двумя предложениями.

Есть каталог: искать tags, затем снять Card

Нет имени хоста, есть только фраза «найди того, кто классифицирует возвраты» — идёте в курируемый каталог. Запрос ест skills[].tags и имена навыков на Card, не топологию со слайдов. Оркестраторы внутри проекта Google, Gemini Enterprise и Agent Gateway ищут записи по ключевым словам навыка. Это поведение продукта, не стандартный RPC A2A. Сообщество и другие облака держат свой search. Фикстура ревью должна утверждать «запрос → список попаданий → в каждой строке cardUrl или вложенная Card». Путь одного поставщика в спецификацию не поднимайте.

Каталог вернул ссылку — следующий прыжок всё ещё well-known или URL карты, который он дал. Вернул вложенную Card — всё равно сверяйте со схемой 1.0: успешная регистрация не равна законному набору полей. Запись NO_SPEC с хостом и без skills даёт пустую поверхность поиска — это уже было в #5. Сегодня напоминание: ключевой прыжок по пустому индексу — не сломанный протокол.

Упавший каталог сам по себе не заканчивает открытие. Если имя хоста уже есть, клиент всё равно должен GET well-known. Считать каталог единственной правдой — сделать поверхность одноточечной. Оставьте в посевной конфигурации один-два устойчивых хоста, вернитесь к поиску по словам, когда каталог оживёт. Это ближе к трём сосуществующим стратегиям спецификации, чем «каталог 500 — стоим».

После попадания: сверить skills, выбрать интерфейс, отправить Task

Попадание поиска значит только «возможно, он». Оркестратор всё равно идёт по skills[]: id — тот ли род работы, tags правда ли бьют в запрос, принимаете ли границу в description. Не оборачивайте skill в MCP inputSchema. Подсказки 1.0 — examples и MIME. Неверный skill, затем Task: отказ на делегировании, не на открытии. Но фикстура должна писать «попадание ≠ выбор» двумя шагами.

После выбора читайте supportedInterfaces. Первый элемент предпочтителен. Клиент выбирает привязку, которую умеет: JSONRPC, GRPC, HTTP+JSON. Нет общей привязки — открытие удалось, разговор нет. Верхнеуровневый url из 0.3 не главная точка 1.0. Смотрите и флаги: streaming ложно, а вы всё равно подписываетесь на поток — спецификация хочет ошибку способности, не тихий откат в unary.

JSON ниже — фикстура обхода, не официальный API какого-либо каталога. Запрос, попадание и предпочтительный интерфейс сложены в один объект, чтобы diffить рядом с Card в репозитории. Следующий глагол — message/send. Чек-листы проверки и подписи оставим более поздней заметке.

{
  "kind": "discovery-trace",
  "note": "CI/review fixture — not an official A2A or Google Registry API",
  "query": {
    "tags": ["returns", "classify"]
  },
  "strategy": "curated-registry",
  "hits": [
    {
      "name": "Returns Specialist",
      "cardUrl": "https://returns.agents.example.com/.well-known/agent-card.json",
      "matchedTags": ["returns", "classify"],
      "skillId": "classify-return"
    }
  ],
  "selected": {
    "skillId": "classify-return",
    "preferredInterface": {
      "url": "https://agents.example.com/returns/a2a",
      "protocolBinding": "JSONRPC",
      "protocolVersion": "1.0"
    },
    "next": "message/send"
  }
}
Этот прыжок Вход Что утверждать
Искать в каталогеТеги или имя навыкаСписок попаданий не пуст и несёт ссылку
Снять well-knownИмя хоста или cardUrlJSON парсится; проходит схему 1.0
Выбрать / взять интерфейсПолная Card 1.0id навыка совпал; клиент говорит этот интерфейс

Кэш, устаревшие индексы и фикстуры

Карты двигают редко: добавили навык, сменили аутентификацию. Поверхность открытия всё равно стареет. Индекс каталога отстаёт, well-known уже отдаёт новую version, поиск всё ещё указывает на старые tags. Минимум две фикстуры: снимок попадания каталога и только что снятая Card. Слова не бьют — сначала tags и лаг индекса, потом уже клиент 1.0, прочитавший карту 0.3.

{
  "hop": "well-known",
  "method": "GET",
  "url": "https://returns.agents.example.com/.well-known/agent-card.json",
  "requestHeaders": {
    "If-None-Match": "1.0.3"
  },
  "response": {
    "status": 304,
    "etag": "1.0.3",
    "cacheControl": "max-age=3600"
  }
}

Спецификация прямая: чувствительные данные требуют аутентификации. Предпочитайте динамические учётные данные вне карты. Статический секрет в Card не пишите. Фикстура открытия с токеном или паролем интранета падает на ревью сразу. Публичную карту пишите так, будто её снимут. Кэш расширенной карты идёт за сессией. Не лейите его в то же ведро, что max-age публичной карты.

Plugin SKILL.md и MCP tools/list тоже не источники открытия. Как кодирующий агент в том же репозитории растит навыки — это ящик. Как находят агента возвратов другой команды — это Card. Свалить оба в один capability.json — и три сорванных прыжка сядут в одну строку тикета.

В браузере хватит: Форматировать JSON — парсятся ли фикстура и Card; Проверить JSON Schema — Card 1.0 после попадания; JSON Diff — снимок каталога против только что снятой Card, поймать drift tags / интерфейса. Данные не уходят с машины. Дальше: разбор полей Agent Card и обзор Registry. Подписи и чек-лист проверки — в следующей практической заметке.

Связанное: A2A Agent Card JSON Schema, Google Agent Registry, A2A vs MCP.

Частые вопросы

Есть каталог — всё равно GET well-known?

Да. Каталог потребляет Card, не заменяет их. Спецификация пишет well-known как стандартный путь публичного открытия. Каталог упал — клиент, у которого есть имя хоста, всё равно должен читать визитку.

Есть ли в A2A стандартный RPC «искать агентов»?

Нет. Страница открытия прямо говорит: текущая спецификация не предписывает API курируемого каталога. Каждый каталог задаёт свой запрос. Стандартны форма Card и путь well-known.

Нашли — можно tools/call?

Нет. Попадание — результат открытия. Напротив непрозрачный агент; вы отправляете Task. Детерминированные параметры остаются у инструментов MCP. Не пишите их в прыжок открытия.

Как долго кэшировать?

Сначала Cache-Control и ETag сервера. Нет заголовков — короткий default и условные запросы после истечения. Сменились навыки или аутентификация — должна сдвинуться version. Клиент не должен вести прод по старым tags.

Итог и следующие шаги

В 2026-м «автоматически найти другого агента» складывается в три прыжка: выбрать стратегию, получить Card, по skills и интерфейсам решить, делегировать ли. Каталог — одна дверь, не сам протокол.

Порядок выкладки: сначала правильно повесить well-known у открытого агента; нужен поиск по словам — подключить один каталог поставщика и свою фикстуру запроса; после попадания проверить Card 1.0 и отправить Task. Как писать поля — прошлая заметка. Что такое каталог — #5. Проверка и подписи — позже. Трассу JSON и Card из репозитория сверяйте в JSONVue.