OpenAI 호환 프로바이더를 위한 네이티브 /v1/messages 및 /v1/responses 패스스루
OpenAI 호환 프로바이더를 위한 네이티브 /v1/messages 및 /v1/responses 패스스루
배포(deployment)의 프로바이더가 네이티브 Anthropic Messages를 지원하지 않을 때, LiteLLM은 각 /v1/messages 요청을 프로바이더의 자체 API로 변환합니다: openai/ 배포는 OpenAI Responses API로 가고(파라미터 매핑 참고), 그 외 모든 것은 /v1/chat/completions로 갑니다. 그 변환은 대상 API가 표현할 수 있는 것만 유지해요: cache_control 블록은 버려지고, thinking은 프로바이더 자체의 reasoning 파라미터로 매핑되며, 다른 Anthropic 전용 요청 세부사항은 근사되거나 손실됩니다.
많은 OpenAI 호환 서버(셀프 호스팅 vLLM, 추론 허브, Anthropic 호환 엔드포인트가 있는 모델 벤더)는 Anthropic Messages API를 네이티브로도 노출합니다. 그런 경우 Anthropic 페이로드를 변환 없이 전달하도록 배포를 옵트인할 수 있어요. v1.92.0부터 사용 가능합니다.
supported_endpoints로 옵트인
배포의 model_info.supported_endpoints에 /v1/messages를 추가하세요:
model_list:
- model_name: my-open-model
litellm_params:
model: openai/some-open-model
api_base: https://inference.example.com/v1
api_key: os.environ/EXAMPLE_API_KEY
model_info:
supported_endpoints: ["/v1/chat/completions", "/v1/messages"]
옵트인하면 프록시의 /v1/messages에 대한 요청이 cache_control(아래 참고)을 제외하고 Anthropic body를 그대로 {api_base}/v1/messages로 POST합니다. api_base의 끝에 붙은 /v1은 먼저 제거되므로, https://inference.example.com/v1과 https://inference.example.com 둘 다 https://inference.example.com/v1/messages로 해석돼요. LiteLLM은 요청이 이미 Authorization이나 x-api-key 헤더를 담고 있지 않으면 Authorization: Bearer ***을 보내고, anthropic-version을 2023-06-01로 기본 설정하며, 호출자가 보낸 것과 LiteLLM이 컨텍스트 관리 같은 기능을 위해 추가한 anthropic-beta 헤더를 모두 전달합니다. 스트리밍과 응답 파싱은 네이티브 Anthropic 배포와 같은 방식으로 동작해요.
옵트인하지 않으면 배포는 이전처럼 동작하고 요청은 변환됩니다. 같은 배포에 대한 /v1/chat/completions 호출은 어느 쪽이든 영향받지 않아요.
출처: 문서
본문
cache_control은 이식 가능한 핵심으로 축소됩니다
Messages API의 엄격한 구현은 ttl 같은 Anthropic 전용 cache_control 확장을 cache_control.ttl: 1h is not supported로 거부해요. 그리고 Claude Code 같은 클라이언트는 1h 프롬프트 캐싱이 켜져 있을 때마다 모든 프롬프트 블록에 {"type": "ephemeral", "ttl": "1h"}를 보냅니다. 그래서 기본적으로 전달된 body의 모든 cache_control은 요청 레벨과 system 블록, 도구, 메시지 content 블록, tool_result 콘텐츠에서 {"type": "ephemeral"}로 축소됩니다. tool_use.input이나 tool input_schema 같은 애플리케이션 데이터는 절대 건드리지 않아요.
업스트림이 ttl을 지원한다면 model_info에 cache_control_ttl: true로 유지하세요:
model_list:
- model_name: my-open-model
litellm_params:
model: openai/some-open-model
api_base: https://inference.example.com/v1
api_key: os.environ/EXAMPLE_API_KEY
model_info:
supported_endpoints: ["/v1/chat/completions", "/v1/messages"]
cache_control_ttl: true
빌트인 Anthropic Messages 지원이 있는 프로바이더 배포(anthropic/, bedrock/, vertex_ai/ 등)는 cache_control을 보낸 그대로 계속 전달해요.
요청에 Anthropic 전용 기능을 담아 테스트해 보세요:
curl http://0.0.0.0:4000/v1/messages \
-H "Authorization: Bearer ***" \
-H "content-type: application/json" \
-H "anthropic-version: 2023-06-01" \
-d '{
"model": "my-open-model",
"max_tokens": 64,
"system": [{"type": "text", "text": "You are concise", "cache_control": {"type": "ephemeral"}}],
"messages": [{"role": "user", "content": "Say hi in three words"}]
}'
응답은 프로바이더의 네이티브 Anthropic 형태로 돌아오며, cache_creation_input_tokens와 cache_read_input_tokens 같은 자체 usage 필드를 포함해요.
옵트인은 LiteLLM이 그렇지 않으면 변환할 프로바이더(예: openai/와 custom_openai/ 배포)에만 의미가 있어요. 빌트인 Anthropic Messages 지원이 있는 프로바이더(anthropic/, bedrock/, vertex_ai/ 등)는 이미 네이티브로 전달하며 이 옵트인을 무시합니다.
네이티브 /v1/responses 패스스루
litellm_params.model이 openai/ 접두사를 가진 배포는 이미 /v1/responses를 {api_base}/responses로 네이티브 전송합니다. custom_openai/ 같은 일반 OpenAI 호환 배포는 자체 Responses API 구성이 없으므로, 기본적으로 LiteLLM은 /v1/responses를 /v1/chat/completions로 브리징해요: 입력이 messages로 변환되고, 채팅 컴플리션이 Responses 객체로 다시 변환되며, Responses 전용 요청 필드는 근사되거나 버려집니다. 서버가 /responses를 직접 제공한다면 model_info.supported_endpoints에 /v1/responses를 추가해 요청을 변환 없이 전달하세요. v1.102.0부터 사용 가능합니다.
model_list:
- model_name: my-open-model
litellm_params:
model: custom_openai/some-open-model
api_base: https://inference.example.com/v1
api_key: os.environ/EXAMPLE_API_KEY
model_info:
supported_endpoints: ["/v1/chat/completions", "/v1/responses"]
옵트인하면 프록시의 /v1/responses에 대한 요청이 스트리밍·비스트리밍 요청 모두 Authorization: Bearer ***과 함께 {api_base}/responses(여기서는 https://inference.example.com/v1/responses)로 POST됩니다. model_info에 mode: responses가 있는 배포도 같은 방식으로 동작해요. 옵트인하지 않으면 배포는 /v1/chat/completions를 통한 브리징을 유지하며, 배포에 대한 /v1/chat/completions 호출은 어느 쪽이든 영향받지 않아요. /v1/messages와 /v1/responses 옵트인은 독립적입니다: 서버가 둘 다 제공하면 둘 다 나열하세요.
curl http://0.0.0.0:4000/v1/responses \
-H "Authorization: Bearer ***" \
-H "content-type: application/json" \
-d '{"model": "my-open-model", "input": "Say hi in three words"}'
상태 없는(stateless) 백엔드의 previous_response_id
네이티브 경로는 previous_response_id를 그대로 백엔드로 전달하므로 백엔드가 해석합니다. 응답을 저장하지 않는 OpenAI 호환 서버는 보통 400으로 거부하며, 그 오류는 호출자에게 그대로 반환됩니다. 그런 백엔드에 대해서는 매 턴 input에 전체 대화 기록을 보내거나, 옵트인을 끄고 store_prompts_in_spend_logs: true로 브리지된 경로를 사용하세요. 그러면 LiteLLM이 자체 spend logs에서 previous_response_id를 해석할 수 있어요.
| 배포 model | 옵트인 시 /v1/messages | 옵트인 없이 /v1/messages | 옵트인 시 /v1/responses | 옵트인 없이 /v1/responses |
|---|---|---|---|---|
openai/<model> |
네이티브 패스스루 | Responses API로 변환 | 네이티브 | 네이티브 |
custom_openai/<model> |
네이티브 패스스루 | /v1/chat/completions로 변환 |
네이티브 패스스루 | /v1/chat/completions로 브리징 |
일부 명명된 OpenAI 호환 프로바이더(예: hosted_vllm/)는 자체 Responses API 지원을 제공하고 옵트인 없이도 /v1/responses를 네이티브로 보냅니다. 해당 프로바이더 페이지에서 확인하세요.