# Milestone: 다중 Provider Protocol Profile과 Native Anthropic Messages

## 위치

- Roadmap: [ROADMAP.md](../../../../ROADMAP.md)
- Phase: [PHASE.md](../../../../phase/operational-observability-provider-management/PHASE.md)

## 목표

OpenAI Chat Completions를 공통 cloud provider 실행 기준으로 두고 provider별 차이는 선언형 protocol profile overlay와 제한된 확장 driver로 흡수한다. Edge가 Anthropic Messages 입력과 응답 변환을 직접 소유하여 Claude Code가 `agent-client` gateway 없이 IOP를 호출하게 하고, 기존 Responses driver와 표면은 선택적 capability로 유지하되 공통 provider 완료 기준에는 포함하지 않는다.

## 상태

[완료]

## 승격 조건

- 없음

## 구현 잠금

- 상태: 해제
- SDD: 필요
- SDD 문서: [SDD.md](../../../sdd/operational-observability-provider-management/multi-provider-protocol-profile-native-messages/SDD.md)
- SDD 사유: 외부 HTTP/SSE 계약, provider별 endpoint/path/auth/capability profile, Anthropic↔OpenAI 변환과 Edge-Node tunnel wire를 함께 변경한다.
- 잠금 해제 조건:
  - [x] SDD 잠금이 해제되어 있다.
  - [x] SDD 사용자 리뷰가 없거나 승인/해결되었다.
  - [x] Acceptance Scenario가 Milestone 기능 Task와 연결되어 있다.
  - [x] Evidence Map이 완료 시 `Roadmap Completion`과 최종 검증 evidence로 검증 가능하게 연결되어 있다.
- 결정 필요: 없음

## 범위

- `openai_chat`, `anthropic_messages`와 기존 선택적 `openai_responses` driver가 공유하는 endpoint/path, auth header, request option, capability provider profile schema
- 공통 base profile을 상속해 endpoint/capability/extension만 덮어쓰고 runtime에서는 완전한 immutable profile로 해소되는 선언형 profile overlay
- OpenAI, Gemini, Anthropic, GLM, Kimi, MiniMax, MiMo, Grok, Seulgi GPT의 Chat Completions profile
- Anthropic, MiniMax, MiMo, Seulgi Claude처럼 native Messages를 제공하는 upstream의 `anthropic_messages` profile
- Edge의 canonical `POST /v1/messages`, `POST /v1/messages/count_tokens`, Anthropic 방식 model discovery와 기존 `/anthropic/v1/*` client 설정을 위한 migration alias
- Anthropic Messages와 OpenAI Chat Completions 사이의 system/content/tool/thinking/usage/error/stream 변환
- 기존 `openai_compat`, `seulgivibe_claude`, `seulgivibe_openai` type/config의 호환 migration
- 반복 가능한 fixture/contract test와 provider profile 구현 시 대표 모델 1개로 수행하는 일회성 live smoke

## 기능

### Epic: [protocol-core] 공통 Protocol Driver와 Profile

provider별 차이를 경로 분기 코드가 아니라 검증 가능한 profile과 protocol driver 경계로 수렴시킨다.

- [x] [profile-contract] `openai_chat`, `anthropic_messages`와 기존 선택적 `openai_responses` driver가 공통 provider profile의 endpoint, operation path, auth declaration, model mapping, capability와 extension을 소비하고 base profile overlay를 immutable runtime profile로 해소하도록 config/runtime 계약을 만든다. 검증: overlay cycle과 잘못된 protocol/path/auth/capability 조합은 config load에서 거부되고 legacy type alias는 동일 runtime profile로 정규화된다.
- [x] [path-resolution] base URL에 `/v1`, `/v1beta/openai`, `/api/paas/v4` 같은 provider prefix가 있어도 operation path를 중복 결합하지 않는 profile 기반 URL resolver를 적용한다. 검증: OpenAI, Gemini, GLM, Kimi, MiniMax, MiMo, Grok, Seulgi fixture의 최종 URL이 기대값과 일치한다.
- [x] [profile-catalog] OpenAI, Gemini, Anthropic, GLM, Kimi, MiniMax, MiMo, Grok와 Seulgi의 Chat/Messages 지원 범위를 base profile+overlay catalog와 custom profile 예시로 제공한다. 검증: 각 built-in/custom profile이 공통 schema validation과 request fixture를 통과하고 미지원 operation은 dispatch 전에 명시적으로 거부된다.
- [x] [contract-sync] provider profile config, Edge-Node tunnel operation과 public Chat/Messages 표면의 inner/outer 계약 및 현재 구현 spec을 동기화한다. 검증: contract/spec index와 구현 경로가 새 source of truth를 가리키고 중복 계약 원문이 남지 않는다.

### Epic: [messages-ingress] Edge Native Anthropic Messages

Claude Code가 IOP Edge를 Anthropic-compatible endpoint로 직접 사용하고 대상 profile에 따라 native passthrough 또는 Chat 변환을 수행하게 한다.

- [x] [messages-surface] Edge에 canonical `POST /v1/messages`, `POST /v1/messages/count_tokens`, `GET /v1/models` Anthropic variant와 `/anthropic/v1/*` migration alias를 추가하고 IOP principal auth를 모든 표면에 공통 적용한다. 검증: `ANTHROPIC_BASE_URL`과 auth token/helper를 사용한 Claude Code 형태의 non-stream/stream/count-tokens/model-list fixture가 `agent-client` 프로세스 없이 Edge에 도달하고 `anthropic-version`이 `/v1/models` 응답 schema를 명확히 선택한다.
- [x] [messages-native] `anthropic_messages` upstream은 request/response/error/SSE body 의미를 보존하는 raw tunnel로 전달한다. 검증: Anthropic, MiniMax, MiMo, Seulgi Claude fixture에서 header allowlist, model rewrite, content block ordering, terminal event가 보존된다.
- [x] [messages-chat-bridge] `openai_chat` upstream에는 Anthropic system/content/tool/tool-result/tool-choice/thinking/usage/error와 streaming event를 양방향 변환한다. 검증: text-only, mixed content, tool round-trip, reasoning, stop reason, usage와 provider error golden fixture가 Anthropic 응답 계약으로 수렴한다.
- [x] [responses-regression] 기존 `/v1/responses` passthrough/normalized driver, body/stream 계약과 `agent-client/pi` 소비 동작을 선택적 capability로 유지한다. 검증: 기존 Responses route/stream/provider-auth 회귀 테스트가 통과하며 새 provider 공통 인증 기준에는 Responses live smoke가 요구되지 않는다.

### Epic: [qualification] Provider Qualification

지속 구독 없이 profile 구현 품질을 재현 가능한 fixture와 제한된 실호출 근거로 남긴다.

- [x] [fixture-suite] 각 provider profile의 URL, header, model rewrite, non-stream/stream parsing과 오류 mapping을 credential-free deterministic fixture로 검증한다. 검증: 전체 fixture/contract suite가 네트워크와 provider 구독 없이 반복 실행된다.
- [x] [live-smoke] 새 profile을 구현하거나 protocol profile이 실질적으로 바뀌고 관련 fixture/contract 검증으로 판단할 수 없을 때에만 host-local SOPS credential을 process-local 변수로 주입해 대표 모델 1개에 한 번의 짧은 generation smoke를 실행하고 provider/profile/model/revision/date/result를 sanitized qualification evidence로 남긴다. provider API credential은 IOP inbound principal token과 혼용하지 않는다. 검증: live smoke는 opt-in이며 일반 local test·CI·문서/secret 관리 변경·자동 재시도에서 호출되지 않고, 고정된 짧은 입력·한 단어 응답·작은 provider별 output cap만 사용하며, raw credential은 config·artifact·로그에 남지 않는다.

## 완료 리뷰

- 상태: 통과
- 요청일: 2026-08-01
- 완료 근거: [protocol core 완료 기록](../../../../../agent-task/archive/2026/08/m-multi-provider-protocol-profile-native-messages/01_protocol_core/complete.log), [Messages ingress 완료 기록](../../../../../agent-task/archive/2026/08/m-multi-provider-protocol-profile-native-messages/02+01_messages_ingress/complete.log), [contract/spec 동기화 완료 기록](../../../../../agent-task/archive/2026/08/m-multi-provider-protocol-profile-native-messages/05+03,04_contract_spec_sync/complete.log), [fixture suite 완료 기록](../../../../../agent-task/archive/2026/08/m-multi-provider-protocol-profile-native-messages/06+01,02_fixture_suite/complete.log), [live smoke 완료 기록](../../../../../agent-task/archive/2026/08/m-multi-provider-protocol-profile-native-messages/07+05,06_live_smoke/complete.log)가 기능 Task 10개 전체에 PASS 및 검증 근거를 직접 기록한다.
- 검토 항목: 현재 코드·inner/outer 계약·구현 스펙과 관련 커밋 `f2306f4d`에서 profile overlay, Edge Anthropic ingress/native·bridge, Responses capability 보존이 동일하게 확인됐다. 종료 감사에서 Anthropic 전용 `x-api-key`와 schema 선택 범위를 Anthropic surface로 제한하고, host 없는 absolute operation URL을 config load에서 거부하도록 보완한 뒤 관련 Go test, race, vet, Pi 설치 테스트와 credential-free Lemonade E2E를 통과했다.
- Spec sync: update not needed — `edge-node-execution`, `provider-pool-config-refresh`, `openai-compatible-surface` 현재 구현 스펙이 profile 해소, public auth/schema 선택, Edge-Node 실행 경계를 이미 반영하며 이번 보완은 문서화된 계약을 좁혀 지킨다.
- 리뷰 코멘트: 기능 Task, 구현 잠금, SDD gate, code audit와 spec sync gate가 모두 충족되었고 현재 Milestone 범위의 남은 차단 항목은 없다.

## 범위 제외

- `/v1/responses` 공통 provider 표준화 또는 모든 provider에 대한 Responses 지원 강제
- provider credential의 저장, 사용자별 slot/alias 선택과 secret delivery
- provider 간 자동 fallback, token slot 자동 rotation/round-robin
- provider별 비공개 기능을 공통 schema에 강제로 승격하는 작업
- 상시 live provider CI와 모든 provider 계정/구독 유지

## 작업 컨텍스트

- 관련 경로: `apps/edge/internal/openai`, `apps/edge/internal/service`, `apps/node/internal/adapters`, `packages/go/config`, `proto/iop/runtime.proto`, `agent-client/claude`, `agent-client/pi`, `agent-contract`
- 표준선(선택): 공통 cloud API 기준은 Chat Completions이고 provider별 차이는 base profile+overlay로 흡수한다. runtime dispatch는 상속 관계가 아니라 검증 완료된 concrete profile만 소비하며, 공통 schema로 표현할 수 없는 차이만 protocol driver extension으로 제한한다.
- 표준선(선택): Anthropic Messages는 Edge가 직접 노출하며 native Messages upstream은 passthrough, Chat-only upstream은 Edge-owned bridge를 사용한다. `agent-client/claude`는 migration 참고 구현이지 최종 runtime dependency가 아니다.
- 표준선(선택): 기존 Responses 구현은 유지하지만 이 Milestone의 provider 공통 qualification baseline과 정기 live smoke 대상은 아니다.
- qualification 기본 모델 설정 (사용자 결정, 2026-08-01): Gemini `openai_chat`의 기본 live qualification request는 `gemini-3.6-flash`와 `reasoning_effort=high`이고, OpenAI `openai_chat`의 기본 live qualification request는 `gpt-5.6-luna`와 `reasoning_effort=high`다. Anthropic `anthropic_messages`의 기본 live qualification request는 `claude-sonnet-5`와 `output_config.effort=high`다. 이 기본값은 향후 해당 profile의 대표 model smoke에 적용하며, 각 호출의 반환 model identifier와 token usage를 별도 sanitized evidence로 남긴다.
- OpenAI 기본값 적용 경계 (2026-08-01): SOPS credential을 이용한 OpenAI model discovery에서 `gpt-5.6-luna` availability를 확인했다. 현재 Edge `reasoning_effort` validation은 `high`를 허용한다. 다만 provider profile 구현과 Edge 경유 live smoke는 아직 완료되지 않았으므로, 이 기본값은 기존 direct-upstream connectivity evidence를 대체하거나 runtime 적용 완료를 뜻하지 않는다.
- Anthropic 기본값 적용 경계 (2026-08-01): SOPS credential을 이용한 Anthropic model discovery에서 `claude-sonnet-5` availability를 확인했다. `output_config.effort=high`는 Anthropic Native Messages request의 provider-native option이므로, `anthropic_messages` profile/extension contract와 Edge native tunnel 구현 뒤에만 Edge 경유로 전달한다. 현재 Haiku direct-upstream evidence를 Sonnet 5 qualification 통과나 runtime 적용 완료로 바꾸지 않는다.
- qualification credential 운영: provider API credential은 host-local SOPS에서 해당 smoke process의 변수로만 복호화하고, Edge inbound principal token과 혼용하지 않는다. raw credential은 tracked config, CI, 로그, artifact와 qualification record에 남기지 않는다.
- API-key smoke 비용 가드: fixture/contract 검증과 model discovery만으로 충분하면 generation을 호출하지 않는다. 필요한 generation은 profile 변경당 대표 model 하나에 한 번만 실행하고, 고정된 짧은 입력과 한 단어 응답만 사용한다. OpenAI-compatible preflight는 `max_completion_tokens=128`, Anthropic Messages smoke는 `max_tokens=64`를 넘기지 않으며, 빈 본문·cap 절단·오류는 긴 요청이나 자동 재시도로 확대하지 않고 실패로 기록한다. repository 내용, 사용자 데이터, 긴 대화 이력, 파일, 이미지, tool 호출과 큰 context는 smoke 입력으로 금지한다.
- qualification 실행 근거 (2026-08-01): Gemini `openai_chat` direct upstream smoke에서 `gemini-3.6-flash`와 `reasoning_effort=high`를 사용해 HTTP 200, `finish_reason=stop`, 한 단어 응답을 확인했다. API가 반환한 model identifier는 `gemini-3.6-flash`이며 별도 concrete revision은 반환하지 않았다.
- qualification 실행 근거 (2026-08-01, 기본값 설정 전 connectivity smoke): OpenAI `openai_chat` direct upstream smoke에서 request model `gpt-5-mini`, `reasoning_effort=minimal`, `max_completion_tokens=128`로 HTTP 200, `finish_reason=stop`, 한 단어 응답을 확인했다. API가 반환한 concrete model identifier는 `gpt-5-mini-2025-08-07`이고 token usage는 prompt 32, completion 11, total 43이었다.
- qualification 실행 근거 (2026-08-01): Anthropic `anthropic_messages` direct upstream smoke에서 `anthropic-version=2023-06-01`, request model `claude-haiku-4-5-20251001`, `max_tokens=64`로 HTTP 200, `stop_reason=end_turn`, 한 단어 응답을 확인했다. API가 반환한 model identifier는 `claude-haiku-4-5-20251001`이고 token usage는 input 48, output 6이었다.
- qualification 재시도 근거 (2026-08-01): Kimi `openai_chat` direct upstream smoke의 첫 `kimi-k3` 호출은 `max_completion_tokens=64`에서 `finish_reason=length`와 completion 188 tokens를 반환해 실패했다. 사용자가 명시적으로 승인한 한 번의 재시도에서 `max_completion_tokens=256`, 같은 고정 한 단어 입력/응답 제약으로 HTTP 200, `finish_reason=stop`, 한 단어 응답을 확인했다. API가 반환한 model identifier는 `kimi-k3`이고 token usage는 prompt 124, completion 109, total 233이었다. 256보다 큰 상한과 자동 재시도는 금지한다.
- qualification 상태: Gemini, OpenAI, Anthropic, Kimi의 각 1개 profile이 수동 direct-upstream smoke를 통과했다. 이는 Edge/Node 경유 검증이나 profile 구현 완료를 뜻하지 않으며, 나머지 provider qualification은 여전히 미완료다.
- 선행 작업: 없음
- 후속 작업: [사용자별 Provider Credential Slot과 Alias Routing](../../../../phase/operational-observability-provider-management/milestones/principal-provider-credential-slot-routing.md)
- 확인 필요: 없음
