A2A 에이전트 인증 헤더
A2A 에이전트 인증 헤더
클라이언트에서 백엔드 A2A 에이전트로 인증 자격 증명(Bearer 토큰, API 키 등)을 전달하는 방법을 다뤄요.
개요
LiteLLM이 백엔드 A2A 에이전트로 요청을 프록시할 때, 에이전트는 자체 인증 헤더를 요구할 수 있어요. 이를 공급하는 방법은 세 가지가 있습니다:
| 방법 | 누가 설정 | 동작 방식 |
|---|---|---|
| 정적 헤더 (Static headers) | 관리자 (UI / API) | 클라이언트 요청과 무관하게 항상 전송 |
| 클라이언트 헤더 전달 (Forward client headers) | 관리자 (UI / API) | 클라이언트 요청에서 추출해 전달할 헤더 이름을 지정 |
| 관례 기반 (Convention-based) | 클라이언트 (관리자 설정 없음) | 클라이언트가 x-a2a-{agent_name}-{header} 전송 — 자동으로 라우팅 |
세 가지 방법 모두 결합할 수 있어요. 키 충돌 시 정적 헤더가 항상 우선합니다.
출처: 문서
본문
방법 1: 정적 헤더 (Static Headers)
백엔드 에이전트에 항상 전송되는 관리자 설정 헤더예요. 클라이언트가 보거나 덮어쓰면 안 되는 서버 간 토큰 또는 내부 자격 증명에 사용하세요.
- LiteLLM 대시보드에서 Agents 로 이동합니다.
- 에이전트를 만들거나 편집합니다.
- Authentication Headers 패널을 엽니다.
- Static Headers 아래에서 Add Static Header 를 클릭하고 헤더 이름과 값을 입력합니다.
curl -X POST http://localhost:4000/v1/agents \
-H "Authorization: Bearer ***" \
-H "Content-Type: application/json" \
-d '{
"agent_name": "my-agent",
"agent_card_params": { ... },
"static_headers": {
"Authorization": "Bearer internal-server-token",
"X-Internal-Service": "litellm-proxy"
}
}'
기존 에이전트를 업데이트하려면:
curl -X PATCH http://localhost:4000/v1/agents/{agent_id} \
-H "Authorization: Bearer ***" \
-H "Content-Type: application/json" \
-d '{ "static_headers": { "Authorization": "Bearer new-token" } }'
클라이언트 호출(특별한 헤더 불필요):
curl -X POST http://localhost:4000/a2a/my-agent \
-H "Authorization: Bearer ***" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0", "id": "1", "method": "message/send",
"params": { "message": { "role": "user", "parts": [{"kind": "text", "text": "Hello"}], "messageId": "msg-1" } }
}'
백엔드 에이전트는 클라이언트가 그 값을 전혀 알지 못한 채 Authorization: Bearer intern...oken을 수신해요.
방법 2: 클라이언트 헤더 전달 (Forward Client Headers)
관리자는 헤더 이름 목록을 지정합니다. 클라이언트가 해당 헤더를 포함한 요청을 보내면, LiteLLM은 그 값을 추출해 백엔드 에이전트로 전달해요. 값은 클라이언트가 제어하고, 어떤 헤더가 전달될 자격이 있는지는 관리자가 제어합니다.
- LiteLLM 대시보드에서 Agents 로 이동합니다.
- 에이전트를 만들거나 편집합니다.
- Authentication Headers 패널을 엽니다.
- Forward Client Headers 아래에 헤더 이름을 입력하고 Enter를 누릅니다 (예:
x-api-key,Authorization).
curl -X POST http://localhost:4000/v1/agents \
-H "Authorization: Bearer ***" \
-H "Content-Type: application/json" \
-d '{
"agent_name": "my-agent",
"agent_card_params": { ... },
"extra_headers": ["x-api-key", "x-user-token"]
}'
클라이언트 호출(전달할 헤더 포함):
curl -X POST http://localhost:4000/a2a/my-agent \
-H "Authorization: Bearer ***" \
-H "x-api-key: user-s...lue" \
-H "Content-Type: application/json" \
-d '{ ... }'
백엔드 에이전트는 x-api-key: ***을 수신해요.
헤더 이름 매칭은 대소문자를 구분하지 않습니다. 클라이언트가 X-API-Key를 보내고 extra_headers가 x-api-key를 나열해도 매칭됩니다.
방법 3: 관례 기반 전달 (Convention-Based Forwarding)
클라이언트는 관리자 사전 설정 없이 다음 명명 관례를 사용해 특정 에이전트로 헤더를 전달할 수 있어요:
x-a2a-{agent_name_or_id}-{header_name}: value
LiteLLM은 이 헤더를 자동으로 파싱해 일치하는 에이전트에만 라우팅합니다.
예시:
| 클라이언트가 보낸 헤더 | 에이전트 이름/ID | 아래로 전달됨 |
|---|---|---|
x-a2a-my-agent-authorization: Bearer *** |
my-agent |
authorization: Bearer *** |
x-a2a-my-agent-x-api-key: *** |
my-agent |
x-api-key: *** |
x-a2a-abc123-authorization: Bearer *** |
에이전트 ID abc123 |
authorization: Bearer *** |
curl -X POST http://localhost:4000/a2a/my-agent \
-H "Authorization: Bearer ***" \
-H "x-a2a-my-agent-authorization: Bearer agent-...oken" \
-H "Content-Type: application/json" \
-d '{ ... }'
같은 요청에서 보낸 x-a2a-other-agent-authorization 헤더는 my-agent에 전달되지 않으며 조용히 무시됩니다.
사람이 읽을 수 있는 이름(예: my-agent)과 UUID(예: abc123-...) 둘 다 유효해요. 클라이언트에 편리한 쪽을 쓰면 됩니다.
병합 우선순위 (Merge Precedence)
여러 방법이 같은 헤더 이름을 제공하면 정적 헤더가 우선합니다:
dynamic (forwarded/convention) → merged ← static (overlays, wins)
예시:
| 출처 | Authorization 값 |
|---|---|
클라이언트가 보냄 (extra_headers 또는 관례) |
Bearer client-token |
관리자 설정 static_headers |
Bearer server-token |
| 백엔드 에이전트가 수신 | Bearer server-token |
이렇게 하면 관리자가 제어하는 자격 증명이 클라이언트 요청으로 덮어써질 수 없습니다.
LiteLLM이 백엔드 자격 증명을 직접 발급하는 경우(에이전트의 databricks_oauth 블록 또는 Microsoft Entra 필드), 그 발급된 Authorization은 두 출처 모두보다 우선하며, 같은 이름의 클라이언트 헤더는 어떤 대소문자( authorization, Authorization )든 제거되어 백엔드가 Authorization 줄 하나만 받게 돼요.
세 가지 방법 모두 결합하기
# Register agent with static + forwarded headers
curl -X POST http://localhost:4000/v1/agents \
-H "Authorization: Bearer ***" \
-H "Content-Type: application/json" \
-d '{
"agent_name": "my-agent",
"agent_card_params": { ... },
"static_headers": {
"X-Internal-Token": "secret123"
},
"extra_headers": ["x-user-id"]
}'
# Client call using all three mechanisms
curl -X POST http://localhost:4000/a2a/my-agent \
-H "Authorization: Bearer ***" \
-H "x-user-id: user-42" \
-H "x-a2a-my-agent-x-request-id: req-abc" \
-H "Content-Type: application/json" \
-d '{ ... }'
백엔드 에이전트는 다음을 수신해요:
X-Internal-Token: secret123 ← static header (always)
x-user-id: user-42 ← forwarded (in extra_headers)
x-request-id: req-abc ← convention-based (x-a2a-my-agent-*)
X-LiteLLM-Trace-Id: <uuid> ← LiteLLM internal
X-LiteLLM-Agent-Id: <agent-id> ← LiteLLM internal
헤더 격리 (Header Isolation)
각 에이전트 호출은 격리된 HTTP 연결을 사용해요. 에이전트 A에 대해 설정된 헤더는 두 에이전트가 동시에 실행되고 요청을 받고 있어도 에이전트 B에 절대 전송되지 않습니다.
API 레퍼런스
POST /v1/agents / PATCH /v1/agents/{agent_id}
| 필드 | 타입 | 설명 |
|---|---|---|
static_headers |
object | {"Header-Name": "value"} — 항상 전달 |
extra_headers |
string[] | 클라이언트 요청에서 추출해 전달할 헤더 이름 |
Agent 응답
두 필드 모두 GET /v1/agents 및 GET /v1/agents/{agent_id}에서 반환됩니다:
{
"agent_id": "...",
"agent_name": "my-agent",
"static_headers": { "X-Internal-Token": "secret123" },
"extra_headers": ["x-user-id"],
...
}
static_headers 값은 데이터베이스에 저장되고 API에서 반환돼요. 자격 증명처럼 취급하세요: API가 공개적으로 접근 가능하면 여기에 민감한 장기 토큰을 저장하지 마세요. 대신 단기 토큰이나 환경 변수로 주입된 시크릿을 고려하세요.