27 KiB
OpenAI-Compatible API Contract
계약 메타
- id:
iop.openai-compatible-api - boundary:
outer - status: active
- 원본 경로:
apps/edge/internal/openai/routes.goapps/edge/internal/openai/chat_handler.goapps/edge/internal/openai/responses_handler.goapps/edge/internal/openai/types.goapps/node/internal/adapters/openai_compat/openai_compat.gopackages/go/config/config.goconfigs/edge.yaml
- human docs:
docs/openai-compatible-api-contract.md
범위
이 문서는 외부 프로젝트가 IOP Edge의 OpenAI-compatible HTTP 표면을 호출할 때 확인할 계약 원문이다.
IOP 내부 실행은 adapter + target 기준이며, OpenAI-compatible 경계에서는 호환성을 위해 model을 사용한다.
IOP 고유 실행 문맥은 별도 iop wrapper field를 만들지 않고 OpenAI request의 metadata에 둔다.
Auth
Edge 설정의 openai.bearer_token이 비어 있지 않으면 OpenAI-compatible HTTP 표면은 다음 헤더를 요구한다.
Authorization: Bearer <token>
토큰이 없거나 일치하지 않으면 401 unauthorized OpenAI-compatible error response를 반환한다. openai.bearer_token이 빈 값이면 auth를 적용하지 않는다.
Principal token hash mapping auth
Edge 설정에 openai.principal_tokens[]가 설정된 경우, caller는 기존과 동일한 Authorization: Bearer <token> 헤더를 보낸다. Edge는 요청된 raw token의 SHA-256 hash를 계산하여 token_hash_sha256과 매칭한다. 매칭 성공 시 내부 dispatch metadata 후보로 iop_principal_ref, iop_principal_alias, iop_token_ref, iop_principal_source가 채워진다. 매칭할 entry가 없으면 401 unauthorized를 반환한다.
Metadata 정책
- caller-provided
metadata.user는 identity source가 아니며 사용되지 않는다. - caller가
metadata.iop_principal_*를 보내도 authenticated context 값이 overwrite한다.
Legacy fallback
openai.principal_tokens[]가 설정되어 있더라도, raw token이 어떤 principal_tokens entry에도 매칭되지 않으면 openai.bearer_token이 설정된 경우 legacy 단일 bearer auth가 unmapped fallback으로 동작한다. openai.bearer_token과 openai.principal_tokens[]가 모두 설정된 경우, principal token 매칭이 실패하면 legacy fallback을 시도하고, 그래도 실패하면 401 unauthorized를 반환한다.
Provider auth forwarding
openai.provider_auth.enabled=true이면 caller는 provider별 raw user token을 openai.provider_auth.from_header에 담아 보낸다. 기본 header는 X-IOP-Provider-Authorization이다.
Edge는 이 값을 provider tunnel request의 openai.provider_auth.target_header로 전달한다. 기본 target header는 Authorization, 기본 scheme은 Bearer다.
이 provider token은 IOP inbound auth인 Authorization: Bearer <token>과 분리된다. openai.bearer_token 또는 openai.principal_tokens[]가 쓰는 IOP auth token을 외부 provider credential로 재사용하지 않는다.
금지:
- raw provider token을 Edge config, tracked docs, roadmap, task artifact, metric label에 저장하지 않는다.
- host-local
~/.claude/anthropic_key.sh,~/.codex/config.toml, env helper 파일을 OpenAI-compatible provider token source of truth로 읽지 않는다. - missing required provider auth error body나 log에 raw header 값을 echo하지 않는다.
Responses API
Endpoint:
POST /v1/responses
Content-Type: application/json
CLI agent 실행으로 라우팅되는 요청의 최소 형태:
{
"model": "codex",
"input": "현재 워크스페이스의 테스트 상태를 확인해줘.",
"metadata": {
"workspace": "/config/workspace/iop"
}
}
현재 /v1/responses에서 허용하는 표준형 요청 예시:
{
"model": "codex",
"instructions": "응답은 짧게 작성해.",
"input": "현재 워크스페이스의 테스트 상태를 확인해줘.",
"stream": false,
"background": false,
"max_output_tokens": 4096,
"temperature": 0,
"top_p": 1,
"metadata": {
"workspace": "/config/workspace/iop",
"request_id": "req-001",
"task_id": "task-123"
}
}
필드 의미:
model: Edge가 내부adapter + target으로 해석할 외부 route 이름이다. IOP Edge에서는 라우팅을 위해 필수다.instructions: OpenAI Responses API의 top-level instruction field다. 있으면input앞에 배치해 agent 실행 prompt를 만든다.input: agent에게 전달할 사용자 요청이다. 현재 구현은 string input만 지원한다.stream: 현재 구현은false또는 생략만 지원한다.background: 현재 구현은false또는 생략만 지원한다.metadata.workspace: CLI process를 실행할 작업 디렉터리다. CLI agent route에서는 필수 실행 문맥이다.metadata: OpenAI 표준 metadata container다. string key/value를 허용하고, IOP는workspace만 실행 문맥으로 해석한다. 나머지 key는 caller-defined metadata로 보존하되source는 지원하지 않는다.metadata.request_id,metadata.task_id: caller-defined metadata 예시다. 특별한 wrapper나 제품 전용 field가 아니다.max_output_tokens: 출력 길이 상한이다. 내부 provider option의max_tokens로 전달된다.temperature: 생성 다양성 option이다. 대상 adapter가 지원하지 않으면 무시될 수 있다.top_p: nucleus sampling option이다. 대상 adapter가 지원하지 않으면 무시될 수 있다.
금지:
metadata.cli같은 CLI 전용 wrapper를 추가하지 않는다.metadata.inference처럼modelroute와 겹치는 target wrapper를 추가하지 않는다.metadata.nomadcode처럼 특정 소비자 제품명에 묶인 wrapper를 추가하지 않는다.metadata.source처럼 의미가 불명확한 호출 출처 field를 추가하지 않는다.- root-level
iop같은 별도 wrapper field를 추가하지 않는다. /v1/responses에optionswrapper를 추가하지 않는다. Responses API option은 OpenAI 표준 top-level field를 따른다.session_id,timeout_sec같은 IOP 실행 제어 field를 request body 계약에 추가하지 않는다. logical session과 timeout은 route/config 기본값을 따른다.- workspace를 prompt 본문에 섞어 전달하지 않는다.
현재 구현 메모:
/v1/responses는 non-streaming 요청만 지원한다.- OpenAI-compatible provider model group route(provider pool,
openai_compat,vllm)의/v1/responses호출은 raw passthrough parity가 구현되기 전까지400 invalid_request_error로 거부한다. 이 경로는 normalizedSubmitRun으로 fallback하지 않는다. metadata는 최대 16개 string key/value를 허용한다. key는 64자 이하, value는 512자 이하를 기준으로 한다.- CLI route의
metadata.workspace는 이 문서의 계약 기준이다. 구현은 이 값을 Edge service의 run workspace와 Node CLI adapter의 process working directory로 전달해야 한다. metadata.workspace는RunRequest.Workspace로 전달하고 generic run metadata에는 복사하지 않는다.- 다른 Responses API 표준 field는 구현 필요가 생길 때 계약을 갱신한 뒤 추가한다.
Generic Authoring Handoff
외부 caller가 IOP Edge HTTP 표면으로 workspace authoring 작업을 넘길 때의 최소 요청 형태:
{
"model": "codex",
"input": "Todo 항목에 필요한 산출물을 현재 checkout에 작성해줘.",
"metadata": {
"workspace": "/config/workspace/work-slot-123",
"task_id": "todo-123"
}
}
이 handoff는 model, input, metadata.workspace, 필요한 caller-defined metadata만으로 충분해야 한다.
호출자는 metadata.cli, 소비자 전용 metadata wrapper, root-level iop wrapper, IOP CLI 직접 실행, prompt 본문 workspace 주입을 요구받지 않는다.
Workspace-bound route는 workspace가 없거나 상대 경로이면 OpenAI-compatible error로 거부한다. 존재하지 않는 경로, 권한 오류, agent process exit failure는 기본 cwd fallback으로 숨기지 않고 호출자가 실패로 구분할 수 있어야 한다.
Chat Completions
/v1/chat/completions도 같은 metadata 원칙을 따른다. CLI route의 workspace는 metadata.workspace에 둔다. Chat Completions의 provider sampling option은 해당 endpoint의 OpenAI-compatible top-level request field를 따르며, /v1/responses와 마찬가지로 별도 options wrapper를 두지 않는다.
{
"model": "codex",
"messages": [
{
"role": "user",
"content": "현재 워크스페이스의 테스트 상태를 확인해줘."
}
],
"metadata": {
"workspace": "/config/workspace/iop"
}
}
현재 지원하는 Chat Completions request field:
modelmessagesstreammetadatamax_tokensmax_completion_tokenstemperaturetop_ppresence_penaltyfrequency_penaltyseedstopresponse_formattoolstool_choiceparallel_tool_callsstream_optionsstorethinkreasoning_effortthinking_token_budgetinclude_reasoning
Chat Completions response mode
OpenAI-compatible inference provider route는 요청 metadata의 iop_response_mode로 응답 경로를 고른다.
metadata.iop_response_mode생략 또는passthrough: provider HTTP status/header/body를 Node가 열어 기존 Edge-Node tunnel로 relay하고, Edge가 caller에게 쓴다. Chat Completions 성공 응답의 top-levelmodelecho가 provider-served model이면 caller가 요청한 IOP model alias로 정규화한다. reasoning/content/tool_calls 같은 provider payload field는 보존한다. purepassthrough응답 body에는 IOP sideband field/event를 섞지 않고,X-IOP-Response-Modeheader도 붙이지 않는다.metadata.iop_response_mode="passthrough+sideband": provider body와 IOP route/usage/assembled observation을 명시적 IOP extension surface로 함께 노출한다. streaming 응답은 provider SSE event 경계 사이에event: iop.sideband를 추가하고, non-streaming 응답은iop.chat.passthrough_sidebandenvelope로 provider body와iop_sideband를 함께 반환한다. 이 모드는 provider-original byte-identical response로 표시하지 않는다.metadata.iop_response_mode="transformed": OpenAI-compatible provider model group route(provider pool,openai_compat,vllm)에서는 지원하지 않으며400 invalid_request_error로 거부한다. 이 제한은 provider model group이 normalizedSubmitRunpath로 회귀하지 않게 하기 위한 것이다. non-provider normalized route에서는 raw tunnel을 쓰지 않고 normalized IOP output path를 사용하며X-IOP-Response-Mode: transformed로 라벨링한다.
알 수 없는 metadata.iop_response_mode 값은 silent fallback 없이 400 invalid_request_error로 거부한다.
현재 Chat Completions provider route는 raw passthrough와 passthrough+sideband만 지원한다. /v1/responses raw passthrough parity는 별도 구현/계약 갱신 대상이며, parity 전 provider model group /v1/responses 요청은 normalized path로 처리하지 않는다.
Think 제어 field:
think(bool, optional): thinking/reasoning 생성 활성화 여부. 생략하면 provider 기본값을 유지한다.false는 thinking 생성을 끄도록 요청하고,true는 provider가 지원하면 thinking 생성을 명시 활성화한다.reasoning_effort(string, optional):none,low,medium,high중 하나.none은think=false와 같은 disable 의미로 처리한다.low/medium/high는 provider가 지원하는 경우에만 전달한다.thinking_token_budget(int, optional): thinking token budget. 0 이상이어야 한다.include_reasoning(bool, optional): OpenAI-compatible 응답에서reasoning_content노출 여부. non-provider normalized route에서는 생략하거나true이면 provider reasoning delta/message를 노출할 수 있고,false이면 provider가 reasoning을 생성해도 response의reasoning_content를 제거한다. provider-pool purepassthrough는 provider body 보존이 우선이며, 현재 IOP가 이 field만으로 reasoning field를 제거한다고 보장하지 않는다.
dev-corp gemma4:26b provider-pool passthrough 파라미터 범위
이 표는 dev-corp의 gemma4:26b provider-pool route에서, 현재 IOP 설정과 provider/vLLM 최적화 값을 변경하지 않고 standard OpenAI-compatible caller가 요청 파라미터만 바꿔 측정할 때의 현재 계약 범위다. Pi TUI의 고정 호출 방식이나 다른 model/provider route의 동작으로 일반화하지 않는다.
| 요청 파라미터 | 현재 기대 동작 | 권장 판정 |
|---|---|---|
stream=false, think 생략 |
provider에 non-stream Chat Completions 요청으로 전달되고 Edge는 provider JSON body를 relay한다. reasoning field가 있으면 보존될 수 있다. | standard OpenAI-compatible caller에서 non-stream 동작 측정 가능. reasoning을 숨기려면 client에서 choices[].message.reasoning_content, reasoning 등 provider reasoning field를 제거한다. |
stream=true, think 생략 |
provider SSE body를 relay한다. reasoning delta가 있으면 보존될 수 있다. | streaming 동작 측정 가능. client는 choices[].delta.reasoning_content, reasoning, reasoning_text 같은 reasoning delta를 선택적으로 무시한다. |
include_reasoning=false |
field는 수신/전달될 수 있지만 pure passthrough에서 IOP-side filtering을 보장하지 않는다. provider가 무시하면 reasoning field가 그대로 올 수 있다. |
현재 IOP 설정을 바꾸지 않는 조건에서는 hide-only 스위치로 보지 않는다. client-side filtering을 기준으로 둔다. |
think=false |
Edge validation conflict가 없으면 요청은 통과하고 model catalog의 default thinking budget 주입은 억제된다. 이후 provider body에 think:false가 반영될 수 있으나, 현재 gemma4:26b provider 최적화 값과 충돌하거나 backend별로 무시/실패/품질 저하가 날 수 있다. |
“숨기기만” 하는 옵션이 아니다. dev-corp gemma4:26b 기본 안정 호출에서는 생략한다. |
reasoning_effort="none" |
think=false와 같은 disable 의도로 해석되어 default thinking budget 주입을 억제한다. provider tunnel에서는 runtime/provider 지원 여부에 의존한다. |
think=false와 같은 이유로 기본 안정 호출에서는 생략한다. |
명시적 thinking_token_budget |
0 이상이면 conflict validation 후 provider tunnel body에 반영될 수 있다. catalog 기본 budget 대신 caller 값으로 provider thinking budget을 바꾸는 요청이다. | 최적화된 gemma4:26b 기본값을 바꾸는 측정으로만 사용한다. 일반 표준 안정 호출에서는 생략한다. |
metadata.iop_response_mode="passthrough+sideband" |
provider content는 보존하고 IOP sideband observation만 추가한다. reasoning hide를 수행하지 않는다. | route/usage 관측이 필요할 때만 사용한다. |
metadata.iop_response_mode="transformed" |
provider model group route에서는 400 invalid_request_error로 거부한다. |
dev-corp gemma4:26b provider-pool에서는 사용하지 않는다. |
/v1/responses 호출 |
provider model group raw passthrough parity 전까지 지원하지 않는다. | gemma4:26b provider-pool 외부 호출은 /v1/chat/completions 기준으로 측정한다. |
현재 구현에서 think=false를 “provider에는 기본 think를 유지하되 IOP가 응답에서 reasoning만 감추는 hide-only 모드”로 해석하지 않는다. 그런 동작이 필요하면 provider/vLLM 설정 변경이 아니라 Edge provider-pool passthrough 응답 filtering 정책을 별도 구현/계약 갱신해야 한다.
Reasoning-only 완료 처리 (non-provider normalized route):
- provider가 reasoning은 생성했지만 최종 assistant
content와tool_calls없이 완료하면 Edge는 성공 응답을 빈 content로 끝내지 않는다. include_reasoning생략 또는true인 요청은 기존 reasoning 본문을reasoning_content에 유지하고,content가 비어 있으면 reasoning 본문을 fallback content로도 반환한다.finish_reason이stop이 아니면 fallback content 뒤에 IOP notice를 붙인다.include_reasoning=false인 요청은 reasoning 본문을 노출하지 않는다. 대신content에 IOP notice를 넣어 "reasoning was hidden" 상태와finish_reason을 알린다.- streaming 응답도 같은 정책을 따른다. reasoning-only 완료 시 최종 finish chunk와
[DONE]전에 fallback 또는 hidden-reasoning notice를contentdelta로 한 번 전송한다. - Chat Completions provider-pool pure
passthrough응답 body에는 이 normalized fallback/filtering 정책을 적용하지 않는다.
Provider별 think-control 정책:
아래 정책은 normalized adapter execution path 기준이다. Chat Completions provider-pool pure passthrough는 Node adapter의 normalized Execute/request-body builder를 거치지 않고 provider HTTP body를 tunnel로 전달하므로, dev-corp gemma4:26b 측정 범위는 위 표를 우선한다.
vLLM:think=false또는reasoning_effort=none-> 내부chat_template_kwargs.enable_thinking=falsethink=true또는 budget-only -> 내부chat_template_kwargs.enable_thinking=truethinking_token_budget-> 내부chat_template_kwargs.thinking_token_budgetreasoning_effort=low|medium|high->unsupported think control오류 반환
vLLM-MLX:think=true또는 budget-only -> 내부chat_template_kwargs.enable_thinking=truethinking_token_budget-> 내부chat_template_kwargs.thinking_token_budgetthink=false또는reasoning_effort=none->unsupported think control오류 반환. vLLM-MLX 런타임은 스트리밍 응답 전체를reasoning_content로 표기하고enable_thinking=false로도 reasoning 생성을 멈추지 않으므로, think disable을 조용한 성공(200 reasoning stream)으로 처리하지 않고 명시 오류를 반환한다.reasoning_effort=low|medium|high->unsupported think control오류 반환
Lemonade:think=false또는reasoning_effort=none-> 내부chat_template_kwargs.enable_thinking=false. 이 런타임은 top-levelthinkfield를 무시하므로 top-levelthink를 사용하지 않는다.think=true또는 budget-only -> 내부chat_template_kwargs.enable_thinking=truethinking_token_budget-> 내부chat_template_kwargs.thinking_token_budgetreasoning_effort=low|medium|high->unsupported think control오류 반환
- Unknown / 기타 provider: 요청 field를 그대로 전달하되, provider가 지원하지 않는 값은 backend 또는 adapter error가 될 수 있다.
Provider pool model catalog의 models[] entry가 generation policy를 제공하면 Edge는 요청을 내부 실행 또는 Chat Completions provider tunnel로 넘기기 전에 다음 값을 보정한다.
default_max_tokens: caller가 출력 token limit을 생략했을 때max_tokens또는max_output_tokens로 주입한다.min_max_tokens: caller가 너무 작은 출력 token limit을 보냈을 때 해당 값까지 올린다. caller 값이 더 크면 보존한다.default_thinking_token_budget: caller가thinking_token_budget을 생략했을 때 내부 실행 입력 또는 Chat Completions provider tunnel body에 주입한다. strict output가 함께 활성화된 provider-pool Chat Completions 요청에서는 Edge가think=true도 함께 주입해 vLLM/vLLM-MLX 계열 adapter가chat_template_kwargs.enable_thinking=true로 전달하도록 한다.
Conflict 정책:
reasoning_effort가 비어 있거나none|low|medium|high외 값이면 400 에러.thinking_token_budget가 음수이면 400 에러.think=false와reasoning_effort=low|medium|high가 함께 있으면 400 에러.think=false일 때thinking_token_budget를 설정하면 400 에러.reasoning_effort=none일 때thinking_token_budget를 설정하면 400 에러.
Strict output 모드:
- strict output가 활성화되면 non-provider normalized route에서
think=true가 명시되지 않은 요청은 내부 실행 입력에서think=false로 낮춘다. - strict output만으로 OpenAI-compatible provider model group route를
transformednormalized path로 전환하지 않는다. provider model group omitted mode는 계속 rawpassthrough다. - provider-pool
models[]entry의default_thinking_token_budget가 적용되는 모델은 catalog의 thinking policy가 우선한다. 이 경우 요청이think=false또는reasoning_effort=none을 명시하지 않았다면 strict output에서도think=true와thinking_token_budget을 내부 실행 입력 또는 Chat Completions provider tunnel body에 넣는다.
tools가 있는 Chat Completions 요청에서 provider route(openai_compat, vllm, ollama, provider pool)는 forced tool 선택 객체와 "none" 같은 명시적 tool_choice를 backend에 전달한다. 단, "auto"는 OpenAI-compatible 기본값과 같으므로 provider request에서는 생략한다. 일부 vLLM 계열 backend는 explicit/default "auto"를 --enable-auto-tool-choice/--tool-call-parser 없이 400으로 거부한다. 이 400이 발생하고 요청 tool이 정확히 1개이면 Node adapter는 해당 tool에 대한 forced tool_choice로 1회 재시도한다. forced tool도 --tool-call-parser 요구로 거부되거나 여러 tool이라 forced를 고를 수 없으면, Node adapter는 tools/tool_choice를 제거하고 text tool-call system instruction을 leading system message에 병합해 1회 재시도하며 완료 metadata에 openai_text_tool_fallback: "true"를 싣는다.
provider가 native OpenAI-compatible tool_calls를 반환하면 Node는 내부 RunEvent.metadata["openai_tool_calls"] JSON으로 보존하고, Edge는 이를 OpenAI-compatible message.tool_calls 또는 stream delta.tool_calls로 반환하며 finish_reason: "tool_calls"를 사용한다.
provider native tool_calls[].function.arguments는 OpenAI 계약에 맞는 JSON string으로 반환한다. 단, provider가 요청 tools[].function.parameters schema상 배열/객체여야 하는 값을 JSON 문자열로 이중 인코딩한 경우 Edge는 해당 arguments JSON만 schema 기준으로 복원해 다시 JSON string으로 직렬화한다.
요청에 tools[]가 있고 provider가 native tool_calls 없이 assistant content에 raw text tool-call 블록을 담아 응답하면, provider route(openai_compat, vllm, ollama, provider pool)와 CLI route(adapter: "cli") 모두에서 Edge는 그 블록을 요청 tool schema 기준으로 구조화하거나 차단한다. 이 정규화가 인식하는 텍스트 블록의 최소 형태는 <tool_call><function=<name>><parameter=<key>>JSON-or-text</parameter></function></tool_call> XML 형식과 {{function_name(key=Python/JSON-like-literal)}} mustache 형식이다.
후보 tool 이름이 요청 tools[]에 있고 arguments가 파싱되어 해당 tool의 function.parameters schema를 만족하면, Edge는 이를 OpenAI tool_calls로 정규화하고 raw 블록을 content에서 제거한 뒤 finish_reason: "tool_calls"로 반환한다. 요청 tools[]에 없는 tool 이름, unclosed/function 정의 누락 같은 malformed 블록, schema를 위반하는 arguments는 성공 content로 반환하지 않고 tool validation 실패로 처리한다. non-stream과 strict buffered stream 응답은 bounded tool-validation attempt 한도까지 run을 재시도하고, 그래도 실패하면 tool_validation_error로 응답한다. live SSE 스트림은 raw 블록을 content delta로 flush하지 않고 tool_validation_error 이벤트로 스트림을 종료한다.
요청에 tools[]가 없으면 assistant content의 tool-call 유사 텍스트는 파싱하거나 합성하지 않고 backend content 원문으로 그대로 둔다. 자연어 추론은 어떤 경우에도 tool_calls로 변환하지 않는다.
raw <tool_call>/{{...}} 블록과 <|mask_end|> 같은 알려진 chat-template sentinel은 성공 응답의 content나 SSE delta에 노출하지 않는다. sentinel은 content와 reasoning 양쪽에서, streaming chunk 경계에 걸쳐 분할되더라도 sanitize한다.
text tool-call을 구조화할 때 Edge는 route와 무관하게 요청의 tools[].function.parameters schema를 기준으로 arguments를 정규화한다. 예를 들어 tool schema가 commands: string[]만 허용하면 command 객체 입력도 shell string 배열로 접고, commands: {command,args}[]를 허용하면 shell 문법이 없는 명령을 structured argv로 만든다. schema에 없는 UI 설명용 description이나 실행 위치 힌트용 runInTerminal은 command 객체와 최상위 args에서 제거하되, cd, command -v, &&, pipe, redirect, quote 등 shell 해석이 필요한 명령은 schema가 허용할 때 commands: ["cd /work && git status"] 같은 shell string으로 유지한다. CLI route(adapter: "cli")는 native backend tool calling이 없어 이 text tool-call 구조화가 유일한 tool_calls 경로이며, backend auto tool-calling 요구 조건으로 요청이 실패하지 않도록 내부 실행 입력의 tool_choice를 "none"으로 낮춘다.
parallel_tool_calls, stream_options, store는 클라이언트 호환성을 위해 수신하지만 현재 Edge 실행 의미에는 반영하지 않는다.
금지:
metadata.source,metadata.cli,metadata.inference,metadata.nomadcodemetadata.iop_response_mode에passthrough,passthrough+sideband,transformed외 값을 넣는 방식options,chat_template_kwargs,format,keep_alive같은 provider/Ollama 전용 request fieldsession_id,timeout_sec같은 IOP 실행 제어 field
Legacy Completions
POST /v1/completions는 현재 IOP Edge OpenAI-compatible 표면에서 제공하지 않는다.
text completion 형태의 신규 호출은 /v1/responses를 사용하고, message 기반 호출은 /v1/chat/completions를 사용한다.
Routing
Edge 설정이 openai.model_routes[]를 제공하면 model은 먼저 route catalog에서 해석된다.
매칭 route가 없으면 기존 fallback 규칙에 따라 openai.target 또는 요청의 model을 내부 target으로 사용한다.
CLI agent를 OpenAI-compatible API로 노출할 때는 route catalog에서 해당 model을 명시적으로 adapter: "cli"와 target profile로 매핑하는 방식을 우선한다.
Top-level models[]가 있으면 IOP /v1/models와 provider-pool dispatch의 static catalog source of truth다. Seulgivibe provider는 runtime adapter type을 openai_compat로 정규화하되 provider family label로 seulgivibe_claude 또는 seulgivibe_openai를 보존할 수 있다. Tracked catalog 예시는 model/provider mapping만 담고 실제 endpoint credential이나 raw user token은 담지 않는다.