에이전트에 연결하기 전 OpenAI 호환 API를 검증하는 방법

채팅, 구조화된 JSON, 도구 호출 왕복, SSE 종료, 검증 오류를 각각 시험합니다. Python 검사기와 로컬 실패 테스트, 실제 호출 결과를 제공합니다.

한 구멍에는 맞지만 모든 구멍에는 맞지 않는 부품을 보여주는 검사 게이지.

채팅 요청 한 번이 성공했다고 OpenAI 호환 API에서 에이전트가 정상 작동하는 것은 아닙니다. 구조화된 출력, 도구 실행 결과의 재전달, 스트리밍 종료, 처리 가능한 오류처럼 에이전트가 실제로 사용하는 기능을 시험하세요. 각 시험의 엔드포인트와 정확한 모델 ID를 기록해야 합니다. 호환성은 공급업체의 영구적인 속성이 아니라 특정 경로·요청·응답의 특성입니다.

이 글의 작은 Python 검사기는 Chat Completions 형식을 대상으로 최대 6회 요청하고 자동 재시도는 하지 않습니다. OpenCode, Copilot, n8n 설정 튜토리얼과는 별개입니다. 먼저 클라이언트가 호출할 경로를 검사한 뒤 클라이언트를 설정하고 다시 시험하세요. 여기서 통과해도 Responses API, 부하 처리, 애플리케이션의 모든 매개변수 지원을 보증하지는 않습니다.

검사기를 받고 검사 범위 이해하기

check_api.py를 받으세요. 도구 호출은 최초 요청과 결과를 돌려주는 두 번째 요청이 필요하므로, 5개 검사에 최대 6회 요청을 사용합니다.

검사요구 조건통과해도 입증되지 않는 것
기본 채팅지정한 짧은 답이 있는 해석 가능한 Chat Completions 응답도구, 스트리밍, 이미지 이해
구조화 출력엄격한 스키마 요청 수락, 반환 JSON의 스키마와 정답 값 일치모든 JSON Schema 키워드, 임의 데이터의 안정적 추출
도구 호출 왕복타입·이름·인수·호출 ID 확인, 로컬 결과 재전달, 정확한 최종 답스트리밍 인수, 병렬 도구, 원격 도구의 안전성
스트리밍SSE 콘텐츠 유형, 이벤트 해석, 기대 텍스트, stop, [DONE]Responses 이벤트 호환성, 재연결 동작
검증 오류잘못된 필드 타입에 HTTP 400/422와 JSON 오류 객체모든 오류 종류, 재시도 정책, 과금 규칙

로컬 회귀 테스트는 HTTP 호출을 고정 응답으로 대체합니다. 소켓을 열지 않고 키도 필요 없습니다. check_api.py 옆에 저장하고 아래 설명의 의존성을 설치한 뒤 실행하세요.

python test_check_api.py
python -O test_check_api.py

2026년 11월 7일 두 모드에서 모두 9개 사례가 예상 결과를 냈습니다. 정상 교환, 잘린 스트림, 잘못된 도구 답, 잘못된 도구 타입, 스키마 값 오류, 잘못된 채팅 답, null 콘텐츠, 인증 오류, 요청 한도 오류입니다. 실제로 실행한 로컬 검사기 테스트이지 호스팅 모델 호출은 아닙니다. 사례의 통과란 관찰한 상태가 기대 상태와 일치했다는 뜻입니다. 의도적으로 깨진 응답이 모두 PASS를 반환하면 안 됩니다. 모의 응답의 통과를 공급업체 실측 결과로 인용하지 마세요. 실제 호출에는 날짜, 경로, 모델, 사용량 증거가 따로 필요합니다.

엔드포인트와 비용 범위 정하기

선택한 공급업체 문서에서 API 루트를 복사합니다. 이 스크립트는 /v1 루트에 /chat/completions를 붙입니다. 전체 /chat/completions 경로나 모델 소개 페이지를 루트로 넣지 마세요. 인증 문제를 조사하기 전에 모델이 해당 프로토콜을 지원하는지 확인합니다.

Ofox는 현재 API 문서와 정확한 모델의 문서부터 확인하세요. OpenAI 호환이라는 말이 모든 OpenAI 엔드포인트를 뜻하지는 않습니다. 도구 사용에 Responses가 필요한 모델이라면 Responses 전환 가이드를 사용하세요. 이 검사기의 URL만 바꿔서는 메시지 형식이 바뀌지 않습니다.

호출 권한이 있는 저비용 모델을 선택하고 현재 가격을 확인한 뒤 가능하면 계정 단위 지출 제한을 설정하세요. 합성 프롬프트와 작은 출력 토큰 제한을 사용하지만 토큰 매개변수는 금액 상한을 보장하지 않습니다. 공급업체가 필드를 거부하거나 다르게 처리할 수 있고 추론 토큰 처리도 다릅니다. 예제가 짧다는 이유로 비싼 모델에 실행하지 마세요.

기본 제한 필드는 max_completion_tokens입니다. 모델 문서가 max_tokens를 요구하면 해당 옵션을 사용합니다. 제한 필드가 거부되면 문서에 명시된 API 규격에 맞춰 요청을 고쳐야 하며, 이를 텍스트 생성 자체가 불가능하다는 증거로 해석하면 안 됩니다.

격리된 환경에서 한 번 실행하기

지원되는 TLS 라이브러리가 있는 최신 Python 3 환경을 사용합니다. 애플리케이션 의존성에 영향을 주지 않도록 가상 환경을 만드세요.

python3 -m venv .venv
source .venv/bin/activate
python -m pip install requests jsonschema

평소의 로컬 비밀정보 관리 방식으로 LLM_API_KEY를 설정합니다. 명령 인수, 공개 노트북, 스크린샷, 다운로드한 스크립트에 키를 넣지 마세요. 지원된다면 임시 제한 키를 사용하세요.

python check_api.py \
  --base-url https://api.example.com/v1 \
  --model YOUR_EXACT_MODEL_ID \
  --token-field max_completion_tokens \
  --max-output 256 \
  --out first-run.json

api.example.com과 YOUR_EXACT_MODEL_ID는 자리표시자입니다. 문서화된 엔드포인트와 실제 모델 ID로 교체하세요. 명시적인 로컬 루프백 시험을 제외하면 HTTPS가 필요합니다. 잘못된 목적지가 Bearer 인증 정보를 다른 곳으로 조용히 전달하지 못하도록 리디렉션은 비활성화돼 있습니다. 기존 보고서 덮어쓰기도 거부하므로 다시 실행할 때는 새 파일명을 쓰세요.

연결·읽기 타임아웃과 완성된 SSE 줄 사이의 경과 시간 확인이 있지만 전체 실행 시간을 강제하는 타임아웃은 아닙니다. 서버가 불완전한 줄을 조금씩 보내면 읽기가 계속될 수 있습니다. 대화형으로 실행하고 멈춘 요청은 중단하세요. 무인 프로덕션 모니터로 쓰려면 프로세스 수준의 강제 시간 제한과 응답 크기 제한을 먼저 구현해야 합니다.

점수 대신 증거로 결과 읽기

PASS는 특정 검사의 조건을 만족했다는 뜻입니다. FAIL은 요청 거부나 예상 조건 불충족, UNKNOWN은 전송 문제 또는 예상 밖 형식 때문에 신뢰할 결론을 내릴 수 없다는 뜻입니다. 상세 필드와 실제 HTTP 상태를 보고 조치하세요.

네트워크 오류는 도구 미지원의 증거가 아닙니다. 401은 JSON Schema 오류가 아닙니다. 의도적으로 잘못 보낸 요청에서 429가 나와도 타입 검증 성공이 아닙니다. 검증 단계 전에 요청 제한에 걸렸을 수 있기 때문입니다. 검사기는 인증·요청 제한 오류를 검증 오류 테스트의 성공으로 인정하지 않습니다.

다섯 결과를 평균 내 ‘80% 호환’이라고 하지 마세요. 도구가 필수인 에이전트는 다른 네 검사가 통과해도 도구를 못 쓰는 경로로 작동할 수 없습니다. 애플리케이션 기능을 필수와 선택으로 나눈 요구사항 표를 유지하세요.

Ofox에서 수행한 실제 6회 요청

2026년 11월 7일 https://api.ofox.ai/v1에서 계정에 표시된 openai/gpt-6-luna를 max_completion_tokens: 256으로 시험했습니다. 잘못된 매개변수 요청을 포함해 총 6회였고 재시도는 없었습니다. 실제 JSON 결과에 응답 시간과 반환 사용량이 있습니다. 이 번역본은 같은 실행을 설명하며 새 호출을 주장하지 않습니다.

검사관찰 결과
기본 채팅PASS: 요구한 답과 정상 종료
구조화 출력PASS: 스키마와 SKU·수량 정답 일치
도구 왕복PASS: 두 번째 답이 정확히 17
스트리밍PASS: 텍스트, 종료 사유, [DONE] 확인
잘못된 매개변수PASS: JSON 오류 객체와 HTTP 400

저장한 실제 API 결과 JSON을 표시하는 영어 로컬 보고서 뷰어.

화면은 저장한 JSON을 로컬에서 표시한 것입니다. Ofox 대시보드나 추가 실시간 테스트가 아닙니다.

이 결과는 해당 날짜의 모델·경로·시험 입력에 한정됩니다. 모든 모델, 서버 내부의 엄격한 스키마 강제, Responses, 도구 인수 스트리밍, fallback, 클라이언트 추가 필드를 인증하지 않습니다. 잘못된 요청의 400은 기대한 성공 조건이지 서비스 장애가 아닙니다.

도구 결과를 모델에 돌려줘야 하는 이유

tool_calls가 있다는 사실은 상호작용의 절반만 보여줍니다. 애플리케이션은 호출을 검증하고 허용된 도구를 실행한 다음 일치하는 호출 ID로 결과를 반환해야 합니다. 두 번째 모델 답이 결과를 올바르게 사용했는지도 확인합니다.

검사기는 읽기 전용 로컬 함수 lookup_stock 하나를 제공합니다. 가상 SKU 000102의 재고는 고정값 17입니다. 타입, 함수명, JSON 인수, 호출 ID를 검증한 뒤 결과를 돌려주며 최종 답도 정확히 17이어야 합니다. 모델이 지정한 임의 함수나 셸 명령은 실행하지 않습니다.

범위를 좁히면 실패를 찾기 쉽습니다. 최초 호출은 맞는데 두 번째 요청이 실패하면 모델을 바꾸기 전에 도구 결과 메시지와 호출 ID를 확인하세요. 170은 ‘17’을 포함해도 오답입니다. 명시적인 검증 예외를 사용하므로 Python 최적화 모드에서도 검사가 유지됩니다.

실제 서비스에서는 스키마로 인수를 검증하고 가능한 작업을 제한하며 실행 전 권한을 처리하세요. 유효한 도구 호출이 이메일 전송, 결제, 데이터베이스 변경의 허가는 아닙니다.

유효한 JSON과 완료된 작업 구분하기

구조화 출력 예제의 정답은 {"sku":"000102","quantity":3}입니다. SKU는 문자열, 수량은 정수이고 두 필드는 필수이며 추가 필드는 금지합니다. 검사기는 스키마를 검증한 다음 정답 값과 비교합니다. 한 응답이 맞았다고 서버가 strict 모드를 강제했다는 뜻은 아닙니다. 게이트웨이가 필드를 무시했어도 모델이 우연히 같은 JSON을 만들 수 있습니다. 제공한 입력에서 관찰한 동작으로 기록하세요.

JSON 파싱은 성공해도 SKU의 앞자리 0이 사라질 수 있고, 타입은 맞아도 값이 틀릴 수 있습니다. 일반 JSON 모드는 지원하지만 엄격한 스키마 요청은 거부할 수도 있습니다. 서로 다른 능력이므로 초록색 결과를 얻으려고 strict를 조용히 제거하지 마세요.

OpenAI 구조화 출력 문서(영어)는 구조화 응답과 함수 호출을 구분합니다. 선택한 엔드포인트의 규격을 따르세요. 다른 API 형식의 응답 필드를 복사하는 것은 호환성 검사가 아닙니다. 실제 목적이 추출이라면 정답이 있는 문서로 텍스트→JSON 검증 절차(영어)를 이어가세요. 작은 고정 스키마는 첫 점검일 뿐입니다.

스트림의 끝까지 확인하기

텍스트가 조금 출력돼도 응답은 불완전할 수 있습니다. 검사기는 SSE 이벤트를 읽고 텍스트 델타를 합치며 종료 사유와 Chat Completions의 [DONE]을 요구합니다. 그럴듯한 텍스트가 있어도 잘린 스트림은 실패입니다.

이는 선택한 검사 프로필의 기준이지 모든 API의 공통 규칙은 아닙니다. Responses는 이벤트 형식이 다르고 공급업체별 스트림 사용량 반환도 다를 수 있습니다. 이 검사기는 stream_options를 요청하지 않으며 스트리밍 사용량이 없다는 이유만으로 실패시키지 않습니다. 과금·모니터링에 필요하면 문서화된 사용량 옵션을 따로 시험하세요.

연결이 끊겨도 외부 작업이 이미 실행됐을 수 있는 흐름을 무조건 재전송하지 마세요. 도구나 후속 작업의 실행 여부부터 확인합니다. 스트림 연결 끊김 해결 글은 특정 클라이언트 문제를 다루며, 일반적인 네트워크 재시도만으로 에이전트의 안전한 재개가 보장되지는 않습니다.

문제를 일으킨 계층에서 해결하기

관찰먼저 조사할 것
모든 요청이 401/403키, 계정 접근, 엔드포인트 권한
404 또는 model-not-foundURL, 모델 ID, 계정 사용 가능 여부; 모델 없음 오류 가이드(영어)
채팅 통과, strict 스키마 실패응답 형식과 지원하는 스키마 하위 집합
최초 도구 요청 실패프로토콜, 모델 능력, 요청 필드
도구 결과 요청 실패호출 ID, 메시지 기록, 도구 결과 형식
텍스트는 나오지만 끝나지 않음SSE 프레이밍, 프록시 버퍼링, 연결 종료, 프로필 불일치
n8n 인증 성공 후 실행 실패실제 작업 엔드포인트; n8n 경로 진단

필수 검사가 통과하면 OpenCode 사용자 지정 공급업체(영어)나 원하는 클라이언트를 설정하고 작은 작업을 다시 실행하세요. 클라이언트는 검사기에 없는 필드를 보낼 수 있습니다. 직접 API 통과가 앱 동작을 보장한다고 보지 말고 두 결과를 모두 보관하세요.

보고서를 공유하기 전 비공개 엔드포인트명, 요청 ID, 계정별 내용이 있으면 제거합니다. 샘플은 합성 작업 결과, 모델, 시간, 상태, 사용량만 기록하고 키는 쓰지 않습니다. 모델 버전이나 경로가 바뀔 때마다 날짜가 있는 증거를 남기는 편이 포괄적인 ‘호환’ 표시보다 유용합니다.