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 связывает независимых агентов: один выступает клиентом, другой - исполнителем. Перед отправкой задачи клиент читает карточку и отвечает на вопросы:
- Подходит ли этот агент под намерение пользователя?
- Какой endpoint принимать задачи?
- Какие MIME-типы на входе и выходе?
- Нужна ли аутентификация и какая именно?
- Поддерживаются ли поток событий и 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:
apiKeyhttp(Basic / Bearer)oauth2openIdConnectmutualTLS
securitySchemes описывает доступные методы. security задаёт требование по умолчанию:
- несколько объектов в массиве
security= альтернативы (OR); - несколько ключей в одном объекте = нужно всё сразу (AND).
В карточке публикуют как аутентифицироваться, а не секреты. Не кладите API-ключи, refresh-токены и внутренние hostname в JSON.
Discovery: как карточку находят
Типичный путь:
- Клиент знает базовый домен агента.
- Запрашивает
https://agent.example.com/.well-known/agent-card.json. - Валидирует обязательные поля.
- Выбирает skill по описанию, tags и examples.
- Аутентифицируется по
security. - Отправляет задачу на
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 вроде «делает всё по сайту».
Публичная карточка - поверхность атаки и поверхность маршрутизации одновременно. Держите её точной и минимально достаточной.
Частые ошибки
- Перепутан
urlи URL карточки. - Пустой массив
skills. Агент становится практически ненаходимым для роутинга. - Описание без границ. Не сказано, чего агент не делает (оплата, удаление, смена цен).
- Нет
examples. Оркестратор хуже понимает валидный ввод. - localhost в production-карточке. Endpoint должен быть достижим для клиентов.
- Один skill на весь продукт. Лучше несколько узких skills с разными правами и MIME.
Мини-чеклист перед публикацией
- Карточка отдаётся по HTTPS с корректным
Content-Type: application/json. - Есть
name,description,version, endpoint и хотя бы один skill. descriptionи skill-описания конкретны.- У ключевых skills есть
examplesиtags. capabilitiesсоответствуют реальному серверу.- В JSON нет секретов.
- Endpoint из карточки отвечает на тестовую задачу.
- Версия увеличивается при 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-версией и явной документацией.