A2A 에이전트 카드
A2A 에이전트 카드
LiteLLM은 A2A 호환 에이전트를 프록시하여, 가상 키(virtual key), 팀 범위 지정, 관찰 가능성(observability), 그리고 통합된 에이전트 카드를 통해 클라이언트에 노출할 수 있어요.
이 페이지는 LiteLLM이 현재 지원하는 A2A 에이전트 카드 필드, 호출 방식, 그리고 /a2a/{agent_id}/.well-known/agent.json에서 제공되는 프록시된 에이전트 카드의 기대 동작을 설명합니다.
프로바이더별 설정은 다음을 참고하세요:
- LangGraph Platform 에이전트 등록하기
출처: 문서
본문
에이전트 카드 지원
아래 필드는 A2A v1.0 스펙(§4.4 에이전트 디스커버리 객체)을 반영해요. ✅는 필드가 LiteLLM이 클라이언트에 제공하는 에이전트 카드에 존재한다는 뜻이고, ❌는 없음을 뜻합니다.
AgentCard (§4.4.1)
| 필드 | 지원 여부 |
|---|---|
protocolVersion |
✅ |
name |
✅ |
description |
✅ |
supportedInterfaces |
✅ |
provider |
✅ |
version |
✅ |
documentationUrl |
✅ |
capabilities |
✅ |
securitySchemes |
✅ |
securityRequirements |
✅ |
defaultInputModes |
✅ |
defaultOutputModes |
✅ |
skills |
✅ |
signatures |
❌ |
iconUrl |
✅ |
AgentProvider (§4.4.2)
| 필드 | 지원 여부 |
|---|---|
url |
✅ |
organization |
✅ |
AgentCapabilities (§4.4.3)
| 필드 | 지원 여부 |
|---|---|
streaming |
✅ |
pushNotifications |
❌ |
extensions |
❌ |
extendedAgentCard |
❌ |
truthy한 streaming이 없는 capabilities 블록은 스트리밍할 수 없는 에이전트를 의미해요. 그런 에이전트에 대한 스트리밍 채팅 컴플리션은 단일 차단 message/send로 실행되고 단일 청크로 재생됩니다. capabilities 블록이 없는 카드는 message/stream을 유지해요.
AgentExtension (§4.4.4)
| 필드 | 지원 여부 |
|---|---|
uri |
❌ |
description |
❌ |
required |
❌ |
params |
❌ |
AgentSkill (§4.4.5)
| 필드 | 지원 여부 |
|---|---|
id |
✅ |
name |
✅ |
description |
✅ |
tags |
✅ |
examples |
✅ |
inputModes |
✅ |
outputModes |
✅ |
securityRequirements |
❌ |
AgentInterface (§4.4.6)
| 필드 | 지원 여부 |
|---|---|
url |
✅ |
protocolBinding |
✅ |
tenant |
❌ |
protocolVersion |
✅ |
AgentCardSignature (§4.4.7)
| 필드 | 지원 여부 |
|---|---|
protected |
❌ |
signature |
❌ |
header |
❌ |
LiteLLM에서 A2A가 동작하는 방식
LiteLLM에 A2A 에이전트를 등록하면:
- 기본 URL(일부 프로바이더는 assistant 식별자)을 제공합니다.
- LiteLLM은 에이전트의
/.well-known/agent-card.json, 다음으로/.well-known/agent.json, 그다음/agentCard/v1.0에서 업스트림 에이전트 카드를 가져와, 응답하는 첫 경로에서 멈춥니다. 에이전트의litellm_params에agent_card_path를 설정하면(예: Microsoft Foundry가 제공하는 경로인agentCard/v1.0) 해당 경로를 직접 가져와요. - LiteLLM UI에서 파싱된 카드를 검토하고, 어떤 스킬과 필드를 노출할지 선택하며, 클라이언트용 프로토콜 버전(
1.0또는0.3)을 고릅니다. - LiteLLM은 정리된 카드를 저장하고
GET /a2a/{agent_id}/.well-known/agent.json에서 제공합니다. - 클라이언트는 A2A JSON-RPC 2.0으로
POST /a2a/{agent_id}에서 에이전트를 호출합니다 (아래 Supported A2A methods 참고).
프로토콜 버전 관리
LiteLLM은 업스트림 에이전트 응답을 각 에이전트에 고정된 protocolVersion으로 변환합니다. 클라이언트는 업스트림 에이전트가 네이티브로 말하는 버전과 무관하게 항상 사용자가 선택한 버전을 보게 돼요.
protocolVersion |
클라이언트에 제공되는 형태 |
|---|---|
"1.0" (새 카드 기본값) |
Protobuf JSON 봉투 — result.message, 스트림 statusUpdate / artifactUpdate |
"0.3" |
레거시 kind 구분 JSON — result.kind == "message" |
이 값은 에이전트 카드 UI 또는 등록 시 agent_card_params에서 설정할 수 있어요. 지원되지 않는 값은 HTTP 400으로 거부됩니다.
completion-bridge 에이전트(LangGraph, Bedrock AgentCore 등)는 추가 프로바이더 설정이 필요 없어요. 클라이언트가 특정 wire format을 기대할 때만 protocolVersion을 고정하세요.
protocolVersion이 고정되지 않았을 때의 클라이언트 협상은 Protocol versioning 문서를 참고하세요.
지원되는 A2A 메서드
아래 모든 메서드는 POST /a2a/{agent_id}에서 허용됩니다 (message/send의 경우 POST /a2a/{agent_id}/message/send에서도). LiteLLM은 A2A SDK의 PascalCase 별칭(예: GetTask → tasks/get)도 받아들여요.
| 메서드 | 지원 | LiteLLM 처리 방식 |
|---|---|---|
message/send |
✅ | LiteLLM A2A SDK(asend_message)로 라우팅 — 로깅, 가드레일, 비용 추적 |
message/stream |
✅ | LiteLLM 스트리밍 핸들러로 라우팅 — NDJSON/SSE 응답 |
tasks/get |
✅ | 에이전트의 agent_card_params.url로 JSON-RPC 전달 |
tasks/list |
✅ | 업스트림으로 JSON-RPC 전달 |
tasks/cancel |
✅ | 업스트림으로 JSON-RPC 전달 |
tasks/resubscribe |
✅ | 업스트림으로 JSON-RPC 전달 (스트리밍/SSE) |
tasks/pushNotificationConfig/set |
✅ | 업스트림으로 JSON-RPC 전달 |
tasks/pushNotificationConfig/get |
✅ | 업스트림으로 JSON-RPC 전달 |
tasks/pushNotificationConfig/list |
✅ | 업스트림으로 JSON-RPC 전달 |
tasks/pushNotificationConfig/delete |
✅ | 업스트림으로 JSON-RPC 전달 |
agent/getAuthenticatedExtendedCard |
✅ | 업스트림으로 JSON-RPC 전달; result.url은 프록시로 재작성 |
PascalCase 별칭 (SDK)
| SDK / 별칭 이름 | Wire 메서드 |
|---|---|
SendMessage |
message/send |
SendStreamingMessage |
message/stream |
GetTask |
tasks/get |
ListTasks |
tasks/list |
CancelTask |
tasks/cancel |
SubscribeToTask |
tasks/resubscribe |
CreateTaskPushNotificationConfig |
tasks/pushNotificationConfig/set |
GetTaskPushNotificationConfig |
tasks/pushNotificationConfig/get |
ListTaskPushNotificationConfigs |
tasks/pushNotificationConfig/list |
DeleteTaskPushNotificationConfig |
tasks/pushNotificationConfig/delete |
GetExtendedAgentCard |
agent/getAuthenticatedExtendedCard |
요구사항
- task 및 push-notification 메서드는
agent_card_params.url이 실제 A2A JSON-RPC 서버를 가리켜야 해요. LiteLLM은 인증 헤더 외에는 요청 본문을 그대로 전달합니다. - completion-bridge 전용 에이전트(예:
custom_llm_provider가 있고url이 없는 LangGraph/Bedrock AgentCore)는message/send와message/stream만 지원합니다. 업스트림 URL이 설정되지 않으면 Task API는 오류를 반환해요. message/send/message/stream전용: LiteLLM은 params에서 LiteLLM 고유 키(예:guardrails)를 제거할 수 있어요. Task 메서드 params는id같은 A2A 필드가 보존되도록 그대로 전달됩니다.
예시: 두 단계 task 흐름
curl -X POST "http://localhost:4000/a2a/my-agent" \
-H "Authorization: Bearer ***" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": "r1",
"method": "message/send",
"params": {
"message": {
"kind": "message",
"role": "user",
"messageId": "m1",
"parts": [{"kind": "text", "text": "Hello"}]
}
}
}'
응답의 result.id를 task id로 사용하세요:
curl -X POST "http://localhost:4000/a2a/my-agent" \
-H "Authorization: Bearer ***" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": "r2",
"method": "tasks/get",
"params": {"id": "<task-id-from-step-1>"}
}'
스킬 라우팅
클라이언트는 메시지 메타데이터에 skillId를 포함해 특정 스킬을 호출해요:
{
"jsonrpc": "2.0",
"id": "req-1",
"method": "message/send",
"params": {
"message": {
"messageId": "msg-001",
"role": "user",
"parts": [{"kind": "text", "text": "..."}],
"metadata": {"skillId": "triage_ticket"}
}
}
}
LiteLLM은 metadata를 포함한 전체 메시지 봉투를 업스트림 에이전트에 그대로 전달합니다. skillId를 읽고 내부적으로 라우팅하는 것은 업스트림 에이전트의 책임이에요.
에이전트 카드 편집
LiteLLM UI의 에이전트 상세 페이지에서 지원되는 필드를 편집할 수 있어요. Re-sync from upstream 버튼을 사용하면 등록 이후 업스트림 에이전트가 추가한 새 스킬이나 capabilities를 가져오며, diff를 보여주고 선택적으로 변경을 수락할 수 있습니다.