Проблема: как узнать, что умеет чужой агент?
Представь: в сети живут десятки агентов-сервисов. Ты хочешь собрать пайплайн — нужен агент, который умеет искать в вебе. Но как ты узнаешь, что вон тот сервис по адресу research.example.com — именно исследователь, а не бухгалтер? Какой у него эндпоинт? Он вообще принимает текст или только файлы? Нужен ли токен?
Спрашивать вживую нельзя — агент это не человек. Нужен машиночитаемый способ самоописания: стандартный документ, который любой клиент прочитает и поймёт без предварительной договорённости. В вебе эту роль играют OpenAPI-спеки и robots.txt; в A2A — Agent Card.
Одна визитка отвечает сразу на три вопроса клиента: «Кто ты и что умеешь?» (резюме — name, description, skills), «Как с тобой говорить?» (контракт — url, capabilities, форматы), «Как войти?» (доступ — authentication). Прочитал карточку — знаешь всё, чтобы отправить задачу.
Где лежит и как её находят
Ключевая идея — предсказуемый адрес. Agent Card публикуется по well-known пути, как robots.txt у сайтов. Клиенту достаточно знать домен агента — путь до карточки стандартный:
домен агента: https://research.example.com
│
▼ клиент делает GET по стандартному пути
https://research.example.com/.well-known/agent.json
│
▼
┌─────────────────────┐
│ Agent Card (JSON) │ ← кто, skills, url, auth
└─────────────────────┘
│
▼ теперь клиент знает, как слать задачу
Три способа, как клиент вообще узнаёт про агента:
- Прямой адрес — знаешь домен, читаешь
/.well-known/agent.json. Простейший случай. - Каталог / реестр (registry) — сервис-«жёлтые страницы», где перечислены агенты и их карточки. Клиент ищет по навыкам («кто умеет web_research?») и получает список карточек.
- Передача в общении — один агент по ходу работы сообщает другому URL карточки третьего агента (динамическое расширение сети).
Стандартный адрес превращает обнаружение в соглашение без договорённости: не нужно заранее обмениваться эндпоинтами. Как браузер всегда знает, где искать favicon.ico, так A2A-клиент всегда знает, где визитка. Это делает агентов по-настоящему обнаружимыми.
Анатомия Agent Card
Разберём, из каких блоков состоит визитка и зачем каждый. Условно поля делятся на четыре группы: идентификация, подключение, возможности и навыки.
Полная карточка выглядит так (набор и имена полей зависят от версии спецификации — здесь показан характерный вид):
{
"name": "Research Agent",
"description": "Ищет информацию в вебе и делает структурированную выжимку",
"version": "1.2.0",
"provider": { "organization": "DataTalks", "url": "https://datatalks.ru" },
"url": "https://research.example.com/a2a",
"authentication": { "schemes": ["bearer"] },
"capabilities": {
"streaming": true,
"pushNotifications": false
},
"defaultInputModes": ["text/plain"],
"defaultOutputModes": ["text/plain", "application/json"],
"skills": [
{
"id": "web_research",
"name": "Web research",
"description": "Поиск по теме и выжимка ключевых фактов с источниками",
"tags": ["search", "summarization"],
"examples": ["Собери факты про рынок EV в 2025", "Что нового в A2A?"]
}
]
}
Ключевые поля и зачем они
Пройдёмся по полям, на которые клиент реально смотрит при выборе:
| Поле | Что описывает | Зачем клиенту |
|---|---|---|
name / description | Кто агент и чем занимается | Быстрый отсев: подходит ли вообще |
url | Эндпоинт A2A-сервиса | Куда слать message/send |
authentication | Схемы доступа (bearer, apiKey…) | Как получить/передать токен |
capabilities | Возможности: streaming, push | Можно ли стримить прогресс долгой задачи |
defaultInput/OutputModes | Форматы вход/выход (MIME) | Примет ли текст/файлы; что вернёт |
skills[] | Конкретные навыки с id, tags, examples | Главное поле выбора — что именно умеет |
Skills — сердце карточки. Именно по ним клиент (или оркестратор) решает, кому отдать задачу. Хорошее описание навыка содержит id (машинный ключ), человекочитаемые name/description, tags для поиска и examples — примеры запросов, которые агент обрабатывает. Examples особенно важны: по ним и человек, и LLM-роутер быстро поймут, о чём навык.
Вспомни JSON Schema для tool calling (модуль 02): там ты описываешь функцию, чтобы LLM понял, когда её вызвать. Agent Card — то же самое, но уровнем выше: описываешь целый агент, чтобы другой агент понял, когда делегировать ему задачу. Skills в карточке играют роль «инструментов», доступных оркестратору.
Как клиент выбирает агента
Обнаружение — половина дела; вторая — выбор. Когда карточек несколько (из реестра), клиент/оркестратор сопоставляет задачу с навыками. Часто это делает сама LLM: ей дают список Agent Card, и она выбирает подходящего — ровно как выбирает инструмент по tool schema.
import httpx
# 1. DISCOVERY — читаем визитку по well-known пути
card = httpx.get("https://research.example.com/.well-known/agent.json").json()
# 2. ПРОВЕРКА пригодности — есть ли нужный навык и формат
def fits(card, need_tag: str) -> bool:
skills_ok = any(need_tag in s.get("tags", []) for s in card["skills"])
text_ok = "text/plain" in card.get("defaultInputModes", [])
return skills_ok and text_ok
assert fits(card, "search")
# 3. АУТЕНТИФИКАЦИЯ по объявленной схеме
assert "bearer" in card["authentication"]["schemes"]
headers = {"Authorization": f"Bearer {TOKEN}"}
# 4. ОТПРАВКА задачи на объявленный url (метод message/send из прошлого урока)
resp = httpx.post(card["url"], headers=headers, json={
"jsonrpc": "2.0", "id": 1, "method": "message/send",
"params": {"message": {"role": "user",
"parts": [{"kind": "text", "text": "Собери факты про рынок EV 2025"}]}}
})
Заметь: весь код опирается только на поля карточки — skills, defaultInputModes, authentication, url. Клиент ничего не знает о внутренностях агента и не должен. Карточка — единственный контракт.
Как писать хорошую карточку
- Честность важнее маркетинга. Описывай то, что агент реально умеет. Завышенные skills → клиенты шлют задачи, которые агент проваливает.
- Гранулярные skills. Один навык = одна понятная способность. Лучше три чётких навыка, чем один «умею всё».
- Заполняй examples и tags. По ним агента находят в реестре и выбирают LLM-роутеры. Пустые examples = агент невидим для умного выбора.
- Версионируй.
versionпозволяет клиентам отслеживать изменения контракта. - Не раскрывай лишнего. Карточка публична — не клади в description секреты, внутренние URL или детали реализации.
A2A развивается: набор и написание полей (например, форматы модальностей, структура authentication, наличие расширенной/аутентифицированной карточки) могут отличаться между версиями спецификации. Держи в голове структуру — идентификация, подключение, возможности, навыки, — а точные ключи сверяй с официальной схемой своей версии.
Типичные ошибки
Если положить agent.json по произвольному адресу, клиенты его не найдут автоматически. Смысл well-known — предсказуемость. Публикуй по /.well-known/agent.json.
«Умный ассистент, помогаю со всем» — бесполезно для выбора. Ни человек, ни LLM-роутер не поймут, когда тебя звать. Конкретные навыки с examples — обязательны.
Agent Card доступна всем, кто знает домен. Токены, внутренние эндпоинты, детали инфраструктуры в ней — утечка. Только контракт, ничего чувствительного.
Объявил streaming: true, но не поддерживаешь — клиент рассчитывает на прогресс и ломается. Карточка — контракт: что объявлено, то должно работать.
Шпаргалка
ЧТО: JSON-визитка агента в A2A — резюме + API-контракт + точка входа
ГДЕ: /.well-known/agent.json (предсказуемый well-known путь, как robots.txt)
ОБНАРУЖЕНИЕ:
прямой адрес (знаю домен) · реестр/каталог (поиск по навыкам) · передача в общении
4 ГРУППЫ ПОЛЕЙ:
① идентификация — name, description, version, provider (кто и чем занят)
② подключение — url, authentication.schemes (куда слать + как войти)
③ возможности — capabilities (streaming/push), defaultInput/OutputModes
④ навыки — skills[]: id, name, description, tags, examples ← ГЛАВНОЕ
ВЫБОР: клиент/LLM сопоставляет задачу ↔ skills (как выбор tool по schema)
код опирается ТОЛЬКО на поля карточки — внутренности агента скрыты
ХОРОШАЯ КАРТОЧКА:
честная · гранулярные skills · заполненные examples/tags · версионирование
без секретов (карточка публична)
ГРАБЛИ:
• не по well-known пути → не найдут
• размытые/пустые skills → невидим для выбора
• секреты в публичной карточке → утечка
• объявил capability, но не реализовал → клиент ломается
СВЯЗЬ: Agent Card ≈ tool schema, но для ЦЕЛОГО агента (модуль 02: JSON Schema)
Практическое задание
Задание: спроектируй Agent Card
- Напиши Agent Card для агента-переводчика: name, description, version, url, authentication, capabilities, defaultInput/OutputModes, минимум два skills с id, tags и examples.
- Объясни, по какому пути его опубликуешь и почему именно там.
- Представь реестр из трёх карточек (переводчик, исследователь, аналитик). Опиши, как LLM-роутер выберет агента под задачу «переведи и суммаризируй статью». Сколько агентов и в каком порядке?
- Найди в своей карточке потенциальные утечки: есть ли что-то, что не должно быть публичным?
- Сравни поле
skillsс JSON Schema инструмента из модуля 02. Что общего, в чём разница уровней? - Со звёздочкой: подними локальный A2A-сервер (SDK/пример), открой его
/.well-known/agent.jsonв браузере, разбери реальные поля и сверь со спецификацией своей версии.
Что дальше
Agent Card говорит, что агент умеет. Но внутри агент сам может подключать инструменты и данные — и здесь в мультиагентную картину входит MCP. Следующий урок — как MCP работает в мультиагентных системах и как уживается с A2A.