← К списку статей

Agent Card в A2A: полный пример JSON и разбор полей

Agent Card - JSON-документ, по которому клиентский агент понимает, кого вызвать, куда слать задачу и какие навыки доступны. В протоколе A2A (Agent2Agent) карточка обычно публикуется по адресу /.well-known/agent-card.json: без неё агент плохо обнаруживается, с размытым описанием - плохо маршрутизируется.

  • Agent Card - публичный контракт возможностей агента
  • Discovery - поиск карточки по well-known URL или registry
  • skills - конкретные навыки, а не общее «умею всё»
  • capabilities - streaming, push, расширенная карточка
  • security - схемы аутентификации в стиле OpenAPI

Зачем нужна Agent Card

A2A связывает независимых агентов: один выступает клиентом, другой - исполнителем. Перед отправкой задачи клиент читает карточку и отвечает на вопросы:

  1. Подходит ли этот агент под намерение пользователя?
  2. Какой endpoint принимать задачи?
  3. Какие MIME-типы на входе и выходе?
  4. Нужна ли аутентификация и какая именно?
  5. Поддерживаются ли поток событий и webhook-уведомления?

Карточка - не маркетинговый текст. Её парсят оркестраторы и LLM-роутеры. Чем точнее description, skills и examples, тем стабильнее выбор исполнителя.

Полный пример JSON

Ниже - рабочий пример карточки для агента, который ищет товары на сайте, считает стоимость и создаёт заявку после подтверждения. Поля даны в camelCase, как в типичных JSON-карточках A2A.

{
  "name": "Site Commerce Agent",
  "description": "Ищет товары в каталоге сайта, рассчитывает стоимость и срок, создаёт заявку после подтверждения пользователя. Работает с каталогом, корзиной-черновиком и статусами заказов. Не выполняет оплату и не меняет цены.",
  "version": "1.2.0",
  "protocolVersion": "0.3.0",
  "url": "https://api.example.com/a2a",
  "documentationUrl": "https://docs.example.com/a2a/commerce-agent",
  "iconUrl": "https://example.com/icons/commerce-agent.svg",
  "provider": {
    "organization": "Example Shop",
    "url": "https://example.com"
  },
  "capabilities": {
    "streaming": true,
    "pushNotifications": true,
    "stateTransitionHistory": true,
    "extendedAgentCard": false
  },
  "defaultInputModes": [
    "text/plain",
    "application/json"
  ],
  "defaultOutputModes": [
    "text/plain",
    "application/json"
  ],
  "skills": [
    {
      "id": "search-products",
      "name": "Поиск товаров",
      "description": "Ищет товары по запросу, категории, цене и наличию. Возвращает список кандидатов с id, названием, ценой и кратким описанием.",
      "tags": ["catalog", "search", "products"],
      "examples": [
        "Найди ноутбуки до 800 евро с доставкой на этой неделе",
        "Покажи доступные тарифы для команды из 20 человек"
      ],
      "inputModes": ["text/plain", "application/json"],
      "outputModes": ["application/json", "text/plain"]
    },
    {
      "id": "calculate-quote",
      "name": "Расчёт стоимости",
      "description": "Считает цену, налоги, доставку и срок для выбранных позиций и количества. Не создаёт заказ.",
      "tags": ["pricing", "quote", "shipping"],
      "examples": [
        "Посчитай стоимость 3 единиц product_id=sku-1042 с доставкой в Берлин",
        "Сравни тариф Basic и Pro для 50 пользователей"
      ],
      "inputModes": ["application/json", "text/plain"],
      "outputModes": ["application/json"]
    },
    {
      "id": "create-lead",
      "name": "Создание заявки",
      "description": "Создаёт черновик заявки или лида после явного подтверждения пользователя. Требует контакт и согласие на обработку данных.",
      "tags": ["lead", "order-draft", "crm"],
      "examples": [
        "Создай заявку на тариф Pro для команды ACME, контакт: ops@acme.example",
        "Оформи черновик заказа по расчёту quote_id=q-7781"
      ],
      "inputModes": ["application/json"],
      "outputModes": ["application/json", "text/plain"]
    },
    {
      "id": "get-order-status",
      "name": "Статус заказа",
      "description": "Возвращает статус оплаты и доставки по order_id для авторизованного пользователя или публичного трек-номера.",
      "tags": ["orders", "status", "tracking"],
      "examples": [
        "Какой статус у заказа ORD-20441?",
        "Где посылка с трек-номером TRK-998877?"
      ]
    }
  ],
  "securitySchemes": {
    "bearer": {
      "type": "http",
      "scheme": "bearer",
      "bearerFormat": "JWT"
    },
    "oauth2": {
      "type": "oauth2",
      "flows": {
        "clientCredentials": {
          "tokenUrl": "https://auth.example.com/oauth/token",
          "scopes": {
            "catalog:read": "Чтение каталога и расчётов",
            "leads:write": "Создание заявок",
            "orders:read": "Чтение статусов заказов"
          }
        }
      }
    }
  },
  "security": [
    {
      "oauth2": ["catalog:read"]
    },
    {
      "bearer": []
    }
  ]
}

В A2A v1.0 endpoint часто описывают массивом supportedInterfaces вместо одного верхнеуровневого url. Смысл тот же: указать, куда клиент шлёт задачи и каким binding пользоваться (JSONRPC, HTTP+JSON, GRPC и т.д.).

Пример фрагмента для v1.0:

{
  "supportedInterfaces": [
    {
      "url": "https://api.example.com/a2a",
      "protocolBinding": "JSONRPC",
      "protocolVersion": "1.0"
    }
  ]
}

Разбор полей верхнего уровня

Поле Обязательность Назначение
name Да Человекочитаемое имя агента
description Да Кратко и конкретно: что делает, чего не делает
version Да Версия самого агента (лучше semver)
url / supportedInterfaces Да* Endpoint(ы) для задач, не URL самой карточки
skills Да Минимум один skill
capabilities Рекомендуется Честные флаги возможностей
defaultInputModes / defaultOutputModes Рекомендуется MIME по умолчанию
provider Нет Организация-владелец
documentationUrl / iconUrl Нет Документация и иконка для UI
protocolVersion Зависит от версии схемы Версия протокола (в v0.3 часто наверху)
securitySchemes / security Нет Как клиенту аутентифицироваться

* В схемах v0.3 обычно обязателен url. В v1.0 роль endpoint берёт на себя supportedInterfaces.

name и description

name нужен людям и логам. description читают роутеры. Плохо: «Полезный агент для сайта». Хорошо: перечислить операции, ограничения и формат результата.

version

Это версия реализации агента, не обязательно версия протокола. Меняйте major при breaking changes в skills или контракте ответа. Клиенты могут кэшировать карточку и обновлять её по смене версии.

url - частая ошибка

url - адрес, куда уходят message/send / задачи. Это не путь к /.well-known/agent-card.json.

Неправильно:

"url": "https://example.com/.well-known/agent-card.json"

Правильно:

"url": "https://api.example.com/a2a"

capabilities

Флаг Смысл
streaming Поддержка потоковых ответов (SSE / stream)
pushNotifications Webhook-уведомления о долгих задачах
stateTransitionHistory История переходов статусов задачи
extendedAgentCard После auth доступна расширенная/приватная карточка

Ставьте true только если реально реализовали поведение. Клиент, который откроет stream к агенту без streaming, получит ошибку.

defaultInputModes и defaultOutputModes

MIME-типы по умолчанию для всего агента. У skill можно переопределить. Типичные значения: text/plain, application/json, application/pdf, image/png.

Разбор skills

Skill - единица маршрутизации. Один skill = одна понятная способность.

Поле Обязательность Комментарий
id Да Уникальный в рамках агента, удобен kebab-case
name Да Короткое имя для UI
description Да Что принимает, что возвращает, какие ограничения
tags Нет Ключевые слова для поиска и фильтрации
examples Нет, но очень желательно 2-3 реальных промпта для оркестратора
inputModes / outputModes Нет Override MIME для этого skill

Примеры - не украшение. Без них модель-оркестратор угадывает входы только по описанию и чаще ошибается.

Плохой skill:

{
  "id": "website",
  "name": "Website",
  "description": "Работает с сайтом"
}

Хороший skill - как в полном примере выше: конкретный id, границы ответственности, tags и examples.

Аутентификация: securitySchemes и security

Схемы обычно повторяют подход OpenAPI:

  • apiKey
  • http (Basic / Bearer)
  • oauth2
  • openIdConnect
  • mutualTLS

securitySchemes описывает доступные методы. security задаёт требование по умолчанию:

  • несколько объектов в массиве security = альтернативы (OR);
  • несколько ключей в одном объекте = нужно всё сразу (AND).

В карточке публикуют как аутентифицироваться, а не секреты. Не кладите API-ключи, refresh-токены и внутренние hostname в JSON.

Discovery: как карточку находят

Типичный путь:

  1. Клиент знает базовый домен агента.
  2. Запрашивает https://agent.example.com/.well-known/agent-card.json.
  3. Валидирует обязательные поля.
  4. Выбирает skill по описанию, tags и examples.
  5. Аутентифицируется по security.
  6. Отправляет задачу на url / supportedInterfaces.

Карточку также публикуют в registry или каталогах агентов. Тогда discovery идёт через поиск, а well-known остаётся источником истины у владельца.

Проверка локально:

curl -s https://api.example.com/.well-known/agent-card.json

Что нельзя публиковать в Agent Card

  • API-ключи, пароли, private keys;
  • внутренние URL админок и staging без защиты;
  • операции, недоступные внешним клиентам;
  • завышенные capabilities («streaming: true» без реализации);
  • размытые skills вроде «делает всё по сайту».

Публичная карточка - поверхность атаки и поверхность маршрутизации одновременно. Держите её точной и минимально достаточной.

Частые ошибки

  1. Перепутан url и URL карточки.
  2. Пустой массив skills. Агент становится практически ненаходимым для роутинга.
  3. Описание без границ. Не сказано, чего агент не делает (оплата, удаление, смена цен).
  4. Нет examples. Оркестратор хуже понимает валидный ввод.
  5. localhost в production-карточке. Endpoint должен быть достижим для клиентов.
  6. Один skill на весь продукт. Лучше несколько узких skills с разными правами и MIME.

Мини-чеклист перед публикацией

  1. Карточка отдаётся по HTTPS с корректным Content-Type: application/json.
  2. Есть name, description, version, endpoint и хотя бы один skill.
  3. description и skill-описания конкретны.
  4. У ключевых skills есть examples и tags.
  5. capabilities соответствуют реальному серверу.
  6. В JSON нет секретов.
  7. Endpoint из карточки отвечает на тестовую задачу.
  8. Версия увеличивается при breaking changes.

Итог

Agent Card - главный discovery-контракт в A2A. Полный JSON с точными skills, честными capabilities и явным security даёт клиентским агентам достаточно данных, чтобы найти исполнителя и не вызвать лишнее.

Если нужна помощь с проектированием Agent Card, A2A-сервером или связкой агента с API сайта - свяжитесь со мной.

Часто задаваемые вопросы

Где должна лежать Agent Card?

Стандартный публичный путь - /.well-known/agent-card.json на домене агента. Дополнительно карточку можно зарегистрировать в каталоге или registry, но well-known URL остаётся удобной точкой discovery без отдельного индекса.

Чем url отличается от адреса карточки?

Адрес карточки нужен для discovery, url (или supportedInterfaces) - для выполнения задач. Клиент сначала читает JSON-карточку, затем отправляет сообщения/задачи на рабочий endpoint агента.

Сколько skills должно быть в карточке?

Столько, сколько реально разных способностей с разными входами или правами. Обычно лучше 3-7 узких skills, чем один общий «сделай всё». Для роутинга важны точные границы, tags и examples.

Обязательна ли аутентификация в Agent Card?

Не всегда. Публичный read-only агент может работать без security. Для записи, персональных данных и платных операций укажите securitySchemes и security, а секреты храните вне карточки.

Нужно ли обновлять карточку при каждом деплое?

Обновляйте, когда меняются skills, endpoint, capabilities, auth или смысл агента. Технический patch без изменения контракта можно отражать в version; breaking changes лучше сопровождать major-версией и явной документацией.

Контакты