Mantle API
OpenAI 호환 API로 Bedrock 모델 호출 - API Key, Responses, 서버사이드 도구
Bedrock Mantle API
OpenAI/Anthropic SDK 호환 · API Key 인증 · Chat Completions · Messages · Responses
OpenAI/Anthropic 코드를 한 줄도 안 바꾸고 Bedrock에 연결
기존 SDK 코드 마이그레이션 — 엔드포인트 URL만 교체
Mantle 필요성
OpenAI/Anthropic 코드 마이그레이션 · 엔드포인트만 교체
Mantle 필요성
기존 OpenAI·Anthropic 코드를 그대로 살리는 호환 엔드포인트의 배경
엔드포인트 URL만 바꾼다
재작성 없이 기존 SDK 코드를 Bedrock으로 옮겨 AWS의 운영 이점을 얻습니다.
- base_url 교체 — 기존 코드 한 줄도 수정 없음
- 데이터 주권 — AWS 리전 내 처리
- AWS 청구서 통합 + CloudWatch 모니터링
- API Key 인증 — Claude Code · Cursor · Cline 연결
갈아타는 비용이 0에 가깝습니다 — 마이그레이션 장벽 제거가 Mantle의 존재 이유입니다.
Bedrock Mantle 필요한 이유
이미 작성된 OpenAI/Anthropic 코드가 많은 현실 — 전면 재작성은 비용 낭비
Converse로 전면 재작성
Bedrock 네이티브 전환
- 모든 파운데이션 모델 통합 인터페이스
- 기존 OpenAI/Anthropic 코드 전부 재작성
- 재작성·재테스트 비용이 전환 이득을 상쇄
Mantle 호환 레이어
base_url만 변경
- OpenAI/Anthropic SDK 그대로 사용
- 엔드포인트 URL만 변경 — 코드 무수정
- AWS 리전 내 처리·청구 통합 등 이점 동시 획득
Converse 재작성 대신 호환 레이어로 기존 코드를 보존하는 것이 Mantle의 해법입니다.
같은 요청, 두 경로
"이 회의록을 3줄로 요약해 줘" — 어느 문으로 들어가도 같은 모델, 같은 요약
"이 회의록을 3줄로 요약해 줘"
meeting-notes.txt
같은 요청 하나
→
Bedrock Runtime
Bedrock Mantle
인증
SigV4 서명 — IAM 자격 증명
API Key
호출
boto3 converse() — 새로 작성
messages.create() 등 기존 SDK 그대로
모델
us.anthropic.claude-sonnet-5
anthropic.claude-sonnet-5
→
Claude Sonnet 5
같은 모델 — 표기만 경로별 상이
1. 출시일 8월 1일 확정
2. QA 인력 2명 충원 합의
3. 후속 회의 다음 주 화요일
같은 요약 3줄 (예시)
두 문 다 같은 모델 풀에 닿습니다 — 단, API별 지원 모델은 상이 (GPT-5.x는 Mantle 전용, Sonnet 4.6은 Messages 미지원)
요청도 모델도 답도 같습니다 — 기존 코드가 있으면 Mantle 문으로 들어가는 것이 이 모듈의 주제이고, 이 회의록 예제가 모듈 끝까지 이어집니다.
마이그레이션 비용 절감
기존 OpenAI/Anthropic 코드를 한 줄도 안 바꾸고 Bedrock 이점 획득
코드는 그대로, 인프라 혜택만 추가됩니다 — 청구·모니터링·네트워크·거버넌스가 AWS로 통합됩니다.
base_url 교체 — 바뀐 두 줄
실제 마이그레이션 결과 — 클라이언트 두 줄 밖의 코드는 전부 그대로
from openai import OpenAI
# 바뀐 곳은 클라이언트 두 줄뿐
client = OpenAI(
base_url="https://bedrock-mantle.us-east-1.api.aws/v1",
api_key=os.environ["BEDROCK_API_KEY"],
)
# 호출 코드 무수정 — 모델 ID에 openai. prefix만 추가
response = client.chat.completions.create(
model="openai.gpt-oss-120b",
messages=[{"role": "user", "content": "안녕하세요"}]
)
- base_url — api.openai.com 직행 대신 Mantle 리전 엔드포인트
- api_key — OpenAI 키(sk-…) 대신 Bedrock API Key 환경변수
- 모델 ID — openai. prefix만 추가 (gpt-oss-120b → openai.gpt-oss-120b)
- chat.completions.create() 호출부는 한 글자도 수정 없음
사용 사례
Bedrock Mantle을 선택하게 되는 팀의 상황
기존 OpenAI 코드 마이그레이션
- 기존 ChatGPT 앱을 Claude로 전환
- 최소한의 변경으로 비용 절감
- 엔드포인트 URL + API Key 교체만 필요
언제 — OpenAI SDK 의존도 높음
기존 Anthropic 코드 마이그레이션
- 기존 Claude 독립 배포 → AWS로 통합
- Anthropic SDK 호환 Messages API
- 엔드포인트만 변경, 나머지 코드 동일
언제 — Anthropic SDK 사용 중
3rd-party 도구 연결
- Claude Code, Cursor, Cline에서 Bedrock 모델 직접 사용
- API Key 발급으로 IAM 설정 불필요
- 개발자 환경 신속 구성
언제 — 3rd-party 도구 연결 필요
세 사례의 공통점은 기존 자산 재사용입니다 — 코드든 도구든 다시 만들지 않습니다.
호환 API
Chat Completions · Messages · Responses
호환 API 구조
하나의 bedrock-mantle 엔드포인트가 SDK별 호환 API 3종을 서빙하는 구조
SDK가 API를 정합니다 — OpenAI SDK는 Chat Completions·Responses, Anthropic SDK는 Messages입니다.
Chat Completions — 실물 요청·응답
OpenAI SDK · Stateless · gpt-oss 계열 — 같은 회의록 요약 요청
기존 OpenAI 파싱 코드까지 그대로 — choices[0].message.content · finish_reason · prompt_tokens 전부 OpenAI 스키마입니다.
요청 — 기존 OpenAI 코드 그대로 (base_url만 Mantle)
response = client.chat.completions.create(
# gpt-oss 등 오픈웨이트 — GPT-5.x는 Responses 전용
model="openai.gpt-oss-120b",
messages=[{"role": "user",
"content": "이 회의록을 3줄로 요약해 줘"}],
)
응답 (예시 수치) — OpenAI 와이어 포맷
{"choices": [{"message": {"role": "assistant",
"content": "1. 3분기 예산 확정
2. 출시 일정 9월 합의
3. QA 담당 지정"},
"finish_reason": "stop"}],
"usage": {"prompt_tokens": 1873,
"completion_tokens": 96}}
// 꺼내기: response.choices[0].message.content
Messages — 실물 요청·응답
Anthropic SDK · Claude 네이티브 기능 — 같은 회의록 요약 요청
InvokeModel의 Anthropic 네이티브와 같은 스키마입니다 — 차이는 인증(API Key)과 SDK뿐, Extended Thinking 등 Claude 기능 사용 가능.
요청 — 기존 Anthropic 코드 그대로 (/anthropic 경로)
response = client.messages.create(
model="anthropic.claude-sonnet-5",
max_tokens=512, # Messages는 필수
messages=[{"role": "user",
"content": "이 회의록을 3줄로 요약해 줘"}],
)
응답 (예시 수치) — Anthropic 와이어 포맷
{"content": [{"type": "text",
"text": "1. 3분기 예산 확정
2. 출시 일정 9월 합의
3. QA 담당 지정"}],
"stop_reason": "end_turn",
"usage": {"input_tokens": 1873,
"output_tokens": 96}}
// 꺼내기: response.content[0].text
Responses — 실물 요청·응답
OpenAI SDK · Stateful 세션 · 신규 권장 — 같은 회의록 요약 요청
output 배열엔 도구 호출 블록도 섞여 옵니다 — 텍스트만 원하면 output_text, 세션은 previous_response_id로 잇습니다.
요청 — input 하나로 시작 (서버가 이력 관리)
response = client.responses.create(
model="openai.gpt-oss-120b",
input="이 회의록을 3줄로 요약해 줘",
)
# 이어서 묻기 — 서버가 대화 이력 보관
follow = client.responses.create(
model="openai.gpt-oss-120b",
previous_response_id=response.id,
input="두 번째 항목을 자세히",
)
응답 (예시 수치) — output 배열 + 편의 속성
{"id": "resp_abc123",
"output": [{"type": "message",
"content": [{"type": "output_text",
"text": "1. 3분기 예산 확정
2. 출시 일정 9월 합의
3. QA 담당 지정"}]}],
"usage": {"input_tokens": 1873,
"output_tokens": 96}}
// 꺼내기: response.output_text (SDK 편의 속성)
Mantle 스트리밍
stream=True 하나 — 기존 OpenAI 스트리밍 코드가 무변경으로 동작
stream = client.chat.completions.create(
model="openai.gpt-oss-120b",
messages=[{"role": "user", "content": "안녕하세요"}],
stream=True,
)
for chunk in stream:
delta = chunk.choices[0].delta.content
if delta:
print(delta, end="", flush=True)
- stream=True 한 줄 — base_url 교체 후에도 기존 스트리밍 코드 무수정
- chunk.choices[0].delta.content — OpenAI SDK 표준 델타 경로
- Runtime의 converse_stream과 달리 이벤트 파싱을 SDK가 대신합니다
호환 API 비교
갈림길은 SDK · 지원 모델 · 전용 기능
| 항목 | Chat Completions | Messages | Responses |
|---|---|---|---|
| SDK | OpenAI | Anthropic | OpenAI |
| 지원 모델 | gpt-oss 등 오픈웨이트 (GPT-5.x·Claude ❌) | Claude | GPT-5.x·gpt-oss 등 OpenAI 계열 (Claude ❌) |
| Extended Thinking | ❌ | ✅ | ❌ |
| Prompt Caching | ❌ | ✅ | ✅ (GPT 계열 — 5.6 브레이크포인트·5.5 자동) |
| 서버측 빌트인 도구 | ❌ | ❌ | ✅ (검색·코드 인터프리터) |
| 비동기 추론 | ❌ | ❌ | ✅ (스트리밍은 3종 모두 지원) |
이력 관리 비교
최대 차이는 이력 관리 — Stateless 둘(Chat Completions·Messages)과 Stateful 하나(Responses)
| 항목 | Chat Completions | Messages | Responses |
|---|---|---|---|
| 이력 관리 | 클라이언트 (Stateless) | 클라이언트 (Stateless) | 서버 (Stateful) |
| 메시지 크기 | 누적 증가 | 누적 증가 | 고정 (새 메시지만) |
| 세션 복구 | 클라이언트 캐시 | 클라이언트 캐시 | 서버 자동 |
| 분기/되돌리기 | 직접 구현 | 직접 구현 | API 지원 |
Stateless는 매 요청에 전체 이력을 다시 보내고, Responses는 서버가 이력을 들고 있어 새 메시지만 보냅니다.
API 선택 기준
기존 코드 형식 · 필요 기능 · 세션 관리 방식으로 결정
Chat Completions
기존 OpenAI 코드 + 단순 요청/응답
- OpenAI SDK 코드를 최소 변경으로 이동
- gpt-oss 등 일부 모델만 지원 — GPT-5.6(Sol·Terra·Luna)·GPT-5.5는 Responses 전용, Claude는 Messages
언제 — 기존 OpenAI 코드의 경량 마이그레이션
Messages
기존 Anthropic 코드 + Claude 고급 기능
- Anthropic SDK 코드 그대로 이동
- Extended Thinking · Prompt Caching 등 Claude 전용 기능
언제 — 기존 Anthropic 코드 · Claude 기능 필요
Responses 추천
Stateful 대화 + 비동기 추론
- 서버가 대화 이력 관리 — 클라이언트 부담 감소
- 긴 작업 비동기 · 세션 복구 · 서버측 빌트인 도구(검색·코드 인터프리터)
- GPT-5.x·gpt-oss 등 OpenAI 계열 전용 — Claude 미지원
언제 — 신규 프로젝트 · 멀티턴 챗봇 · 에이전틱 앱
기존 코드가 있으면 해당 SDK 호환 API, Stateful 세션이 필요하면 Responses입니다.
API Key 인증
Short-term · Long-term · 비용 귀속
API Key의 역할
IAM SigV4 없이 API Key만으로 접근 — 3rd-party 도구 연결에 이상적
SigV4 — Runtime 기본
IAM 자격 증명
- 요청마다 IAM 자격 증명으로 서명 계산
- boto3/AWS SDK가 서명을 대행 — AWS 밖 도구는 불가
- IAM 정책으로 세밀한 권한 제어
API Key — Mantle
헤더 한 줄 — Bearer 또는 x-api-key(경로별 관례)
- IAM 자격 증명 없이 키 하나로 인증
- OpenAI/Anthropic SDK · Claude Code · Cursor · Cline 연결
- Project 단위 발급 — 모델·키 수명·비용 귀속 관리
AWS 밖 생태계 도구는 SigV4를 모릅니다 — API Key가 Mantle 접근의 열쇠입니다.
발급부터 호출까지
콘솔 발급에서 첫 호출까지 — 키는 환경변수로만
-
1
API keys 메뉴
Bedrock 콘솔 좌측 내비게이션의 API keys — Short-term/Long-term 탭 선택
-
2
API Key 발급
Short-term(세션 만료, 최대 12시간) 또는 Long-term(만료 기간 설정 — 콘솔이 전용 IAM 유저 자동 생성)
-
3
환경변수 설정
BEDROCK_API_KEY 환경변수에 저장 — 코드에 하드코딩 금지
-
4
SDK 초기화
OpenAI/Anthropic SDK에 base_url + api_key 전달
-
5
API 호출
기존 SDK 코드와 동일하게 호출 — 엔드포인트만 다름
발급부터 호출까지 한 흐름입니다 — 키는 환경변수로만 관리하고 코드에 넣지 않습니다.
API Key 종류 비교
AWS 공식 권장 — 프로덕션은 자동 갱신 Short-term, Long-term은 탐색용
Short-term Key
- 만료: 기본 1시간, 최대 12시간
- 생성: aws-bedrock-token-generator 라이브러리 (provide_token)
- 용도: 프로덕션 권장 — 코드에서 자동 갱신
- 보안: 자동 만료 + 갱신 패턴으로 유출 창 최소
- 관리: provide_token이 갱신 담당 — 회전 불필요
provide_token(region=...) 호출 한 줄로 발급·자동 갱신. AWS 공식 문서가 프로덕션 용도로 권장하는 방식.
Long-term Key
- 만료: 커스텀 설정 (30일, 90일 등)
- 생성: 콘솔에서 Create API Key
- 용도: 탐색·평가 (공식 권장 범위)
- 현실: 키 자동 갱신이 안 되는 3rd-party 도구(Claude Code·Cursor)에 사용
- 보안: 쓴다면 로테이션 정책 필수 (권장 90일 이내)
공식 문서는 "탐색 전용, 프로덕션은 Short-term 사용" 경고를 명시. 3rd-party 도구처럼 갱신 코드를 못 넣는 곳에만 제한적으로.
직관과 반대입니다 — 프로덕션이 Short-term(자동 갱신), Long-term은 탐색·도구 연결용. 수명이 길수록 유출 시 피해 창도 깁니다.
프로젝트 단위 비용 귀속
Projects(OpenAI 호환) · Workspaces(Anthropic 호환) — 헤더 한 줄로 팀·앱별 격리와 비용 추적
핵심 포인트
- 같은 리소스, 두 이름
- Projects API 하나 — OpenAI 계열은 Projects, Messages는 Workspaces 명칭
- 요청 귀속 헤더
- OpenAI-Project / anthropic-workspace 헤더에 프로젝트 ID
- 비용 추적
- AWS 태그(팀·환경·비용 센터)로 Cost Explorer 지출 배분
- 접근 격리
- IAM 리소스로 프로젝트 지정 — 계정 분리 없이 워크로드 경계
코드
# 워크스페이스(프로젝트) 생성 — 태그가 비용 추적 단위
curl -X POST "https://bedrock-mantle.us-east-1.api.aws/v1/organization/projects" \
-H "Authorization: Bearer $BEDROCK_API_KEY" \
-d '{"name": "Chatbot-Production",
"tags": {"Team": "NLP", "CostCenter": "41250"}}'
# 응답 id(proj_...)를 요청 헤더에 — 워크스페이스 귀속
response = client.messages.create(
model="anthropic.claude-sonnet-5",
max_tokens=1024,
extra_headers={"anthropic-workspace": "proj_abc123def456"},
messages=[{"role": "user", "content": "..."}],
)
선택 기준
Runtime vs Mantle · Anthropic 두 경로 · 최종 선택
Anthropic 코드의 두 경로
같은 Messages API — 인증 방식이 mantle과 runtime을 가르는 기준
코드는 같고 인증이 다릅니다 — API Key가 필요하면 mantle 경로, IAM 통제 아래 두려면 AnthropicBedrock(SigV4)을 선택합니다.
bedrock-mantle /anthropic — API Key
import anthropic
# ① API Key 인증 — IAM 없이 접근 (3rd-party 도구에 적합)
client = anthropic.Anthropic(
base_url='https://bedrock-mantle.us-east-1.api.aws/anthropic',
api_key='<BEDROCK_API_KEY>'
)
response = client.messages.create(
model='anthropic.claude-sonnet-5',
max_tokens=1024,
messages=[{'role': 'user', 'content': 'Hello!'}]
)
print(response.content[0].text)
AnthropicBedrock — SigV4 직행
from anthropic import AnthropicBedrock
# ② SigV4 인증으로 bedrock-runtime을 직접 호출 (mantle 경유 아님)
client = AnthropicBedrock(
aws_region='us-east-1'
)
# Messages API 시그니처는 완전히 동일
response = client.messages.create(
model='us.anthropic.claude-sonnet-5',
max_tokens=1024,
messages=[{'role': 'user', 'content': 'Hello!'}]
)
print(response.content[0].text)
와이어에서 본 두 요청
같은 회의록 요약 요청의 실제 HTTP 실물 — 다른 곳은 세 군데뿐
BEDROCK RUNTIME — SigV4 · Converse
서명은 boto3가 자격 증명으로 매 요청 자동 계산 — IAM 정책의 통제를 받습니다
BEDROCK MANTLE — API Key · Messages
키는 고정 문자열 헤더 하나 — 서명 계산이 없어 3rd-party 도구도 붙습니다
① 엔드포인트 — amazonaws.com vs api.aws
② 인증 헤더 — 매 요청 서명 vs 고정 키
③ 모델 지정 — URL 경로 vs body 필드
메시지 본문은 사실상 동일
와이어 레벨의 차이는 엔드포인트·인증·모델 지정 위치 세 곳입니다 — 본문이 같으므로 SDK만 바꾸면 어느 쪽으로도 보낼 수 있습니다.
Bedrock Runtime vs Mantle 최종 선택
새 코드는 Runtime, 기존 코드는 Mantle — 가격은 동일, 모델 가용성은 엔드포인트별 상이(GPT-5.x는 Mantle 전용)
Bedrock Runtime (새 코드)
- 인증: IAM SigV4
- SDK: boto3 (AWS 네이티브)
- 특징: 모든 Bedrock 파운데이션 모델 지원, Guardrails, Knowledge Bases
- 코드: Converse API 표준 인터페이스
- 권장: 에이전트, 신규 프로젝트
언제 — 새로 짜는 코드
Bedrock Mantle (기존 코드)
- 인증: API Key
- SDK: OpenAI SDK, Anthropic SDK
- 특징: 기존 코드 마이그레이션 (한 줄도 안 바꿈)
- 코드: Chat Completions, Messages, Responses
- 권장: 마이그레이션, 3rd-party 도구
언제 — 기존 OpenAI/Anthropic 코드
하이브리드
- 에이전트 코드: Converse + Strands SDK (Runtime)
- 챗봇 프론트엔드: Responses API (Mantle)
- 레거시 마이그레이션: Chat Completions (Mantle)
- 병행 운영 가능 — 겹치는 모델(Claude Sonnet 5 등) 한정
언제 — 조직 전체 마이그레이션
새 코드는 Runtime(Converse), 기존 코드는 Mantle입니다 — 겹치는 모델은 병행 운영도 가능하지만, 모델 풀은 엔드포인트별로 다릅니다.
실습 — Bedrock Mantle API
같은 Bedrock 모델을 세 가지 호환 API로 호출합니다 — SDK는 OpenAI · Anthropic 그대로
학습 목표
- Chat Completions — OpenAI SDK에 base_url 한 줄 전환
- Messages API — Anthropic SDK로 같은 모델 호출
- Responses API — Stateful 대화 이어가기
Chat Completions · Messages · Responses — 호환 API