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)

백엔드 에이전트에 항상 전송되는 관리자 설정 헤더예요. 클라이언트가 보거나 덮어쓰면 안 되는 서버 간 토큰 또는 내부 자격 증명에 사용하세요.

  1. LiteLLM 대시보드에서 Agents 로 이동합니다.
  2. 에이전트를 만들거나 편집합니다.
  3. Authentication Headers 패널을 엽니다.
  4. 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은 그 값을 추출해 백엔드 에이전트로 전달해요. 값은 클라이언트가 제어하고, 어떤 헤더가 전달될 자격이 있는지는 관리자가 제어합니다.

  1. LiteLLM 대시보드에서 Agents 로 이동합니다.
  2. 에이전트를 만들거나 편집합니다.
  3. Authentication Headers 패널을 엽니다.
  4. 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_headersx-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/agentsGET /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가 공개적으로 접근 가능하면 여기에 민감한 장기 토큰을 저장하지 마세요. 대신 단기 토큰이나 환경 변수로 주입된 시크릿을 고려하세요.

더 알아보기 (Learn more)