Chat completions api
Reference for the OpenAI Chat Completions API (/v1/chat/completions) and legacy /v1/completions as the lingua-franca compatibility protocol — the official spec incl. deprecation timeline and Responses-only feature delta, how 7 local servers (vLLM, SGLang, llama.cpp, Ollama, mistral.rs, Llama Stack/OGX, Lemonade) actually implement it, gateways (LiteLLM, Bifrost), 10 cloud providers' CC-compat endpoints (Anthropic, Gemini, DeepSeek, xAI, Groq, OpenRouter, Azure...), the reasoning_content/reasoning field schism, finish_reason divergences, and client wire behavior (opencode, Vercel AI SDK). NOT for the Responses API (responses-api skill) or Anthropic Messages protocol (messages-api skill).From its SKILL.md
npx -y skills add air-gapped/skills --skill chat-completions-apiAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 5 stars5 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
8.9 KB, as published. Nobody here has run it
Chat Completions Compatibility Reference
Chat Completions is the lingua franca of LLM serving — and because everyone
has implemented and extended it longest, it carries the MOST undocumented
divergence of the three open protocols. OpenAI keeps it fully supported but
second-choice ("we recommend trying Responses") — and since 2026-07-29
OpenAI's own publications call it "our legacy Chat Completions API"
(ARC-AGI-3 post; still no deprecation or sunset date); xAI, Groq, and Azure
declare it legacy too. Legacy /v1/completions loses its last
first-party OpenAI models 2026-09-28 and survives as a local/third-party
surface.
Fleet property: stateless. Full history resent every turn, like
Messages; no server-side session state to break load-balanced fleets
(contrast responses-api's previous_response_id).
Last refreshed: 2026-07-19 (source-examined at commits of 2026-07-16..18;
provenance in references/sources.md).
Critical Gotchas
- The reasoning-field schism:
reasoning_content(SGLang, llama.cpp, mistral.rs, DeepSeek, xAI) vsreasoning(vLLM, Ollama, Together, Groq, OpenRouter) vs inline<think>— and vLLM silently RENAMES incomingreasoning_content→reasoning. Servers should emit both; clients should read both. Full table:references/backend-implementations.md. - Reasoning must be passed BACK in tool loops on DeepSeek v4 (with tool
calls) and OpenRouter (exact block sequence) — clients that strip
reasoning break agentic loops.
references/cloud-compat.md. - Silent-drop vs hard-400 split: Ollama silently drops
tool_choice(forced tool calls no-op!) andmax_completion_tokens(unbounded generation); Groq and xAI-reasoning hard-400 on specific params; LiteLLM raises UnsupportedParamsError as HTTP 500. Identify the target's failure mode before debugging. - finish_reason is not a closed enum:
abort(vLLM, SGLang),repetition,canceled/generated_image(mistral.rs); llama.cpp DEFAULTS tolength; named tool_choice returnsstopon vLLM/OpenAI buttool_callson SGLang/mistral.rs. Parse tolerantly, key loops ontool_calls. seedis a lottery: honored (vLLM, llama.cpp), silent no-op unless server flag (SGLang--enable-deterministic-inference), ignored (mistral.rs) — and OpenAI has formally deprecatedseedANDsystem_fingerprint.json_object≠ json mode everywhere: SGLang and mistral.rs implement it as schema{"type":"object"}— top-level arrays forbidden.json_schema.strictis ignored by ALL local servers (always fully enforced anyway).- Tool-call streaming split: whole-blob single delta (Ollama,
mistral.rs) vs incremental argument diffs (vLLM, SGLang, llama.cpp).
First delta must carry
id+function.nameor AI-SDK clients kill the stream; loose parsers finalize args the moment they parse as JSON. - Cached-token reporting is flag-gated: vLLM
--enable-prompt-tokens-details, SGLang--enable-cache-report; llama.cpp reports always; Ollama never. OpenAI CC now has explicit caching (prompt_cache_options+ per-block breakpoints,cache_write_tokensbilled 1.25×):references/spec.md. data: [DONE]is not universal — Llama Stack/OGX never sends it; AI SDK clients ignore it, official-SDK clients expect it. Send it; don't require it.
Quick Reference
When invoked with a topic argument (spec, backends, gateways, cloud,
clients), load that reference file first and answer from it. Without an
argument, pick by question shape: official params/deprecations/what-CC-gets
→ spec; which-local-server-does-what → backends; proxy/routing behavior →
gateways; hosted-provider compat → cloud; what-clients-send / parser
tolerance → clients.
- Spec:
references/spec.md— full request/response/chunk schema highlights, explicit prompt caching, stored completions, legacy /v1/completions + shutdown timeline, deprecation archaeology, Responses-only feature delta - Backends:
references/backend-implementations.md— divergence matrix- per-server sections for the 7 local servers
- Gateways:
references/gateways.md— LiteLLM param cascade and prefix routing, Bifrost, Superagent (CC outbound only), gateway-tax table - Cloud:
references/cloud-compat.md— 10 providers' CC-compat endpoints and the cross-provider gotcha matrix - Clients:
references/clients.md— opencode's three CC paths, AI SDK parser tolerance, server tolerance checklist - Sources:
references/sources.md— dated per-URL index with commits examined and the live-verification log
Translation between protocols is homed elsewhere: CC↔Messages mapping in the messages-api skill, CC↔Responses mapping in the responses-api skill.
Procedures
Pointing an OpenAI-SDK client at a local backend
- Base URL
http://host:port/v1(SDKs append/chat/completions); authBeareranything unless the server enforces keys. - Check the backend's row in the divergence matrix FIRST — especially
Ollama (
tool_choiceandmax_completion_tokenssilently dropped) and reasoning field naming. - For agent clients (opencode etc.): use the openai-COMPATIBLE provider
path, not the openai provider — the openai path model-id-sniffs
("o3-…" gets temperature stripped), drops reasoning fields, and its
factory default is the Responses API (
references/clients.md). - Reasoning models: confirm how thinking is toggled (
reasoning_effortmapping vschat_template_kwargs.enable_thinkingvs vendorthinkingfields) and which field the CoT comes back in. - Sanity curl:
Expectcurl -sS http://host:port/v1/chat/completions -H "Content-Type: application/json" \ -d '{"model":"<name>","max_tokens":32,"messages":[{"role":"user","content":"Say OK."}]}'object:"chat.completion", non-nullchoices[0].message.content,finish_reasonofstopORlength(llama.cpp defaults tolength). An error body here → check the server's error-envelope row in the matrix before parsing (mistral.rs sends{"message"}, not{"error":{...}}).
Serving CC through LiteLLM to a fleet
- Prefix decides fidelity:
openai/<model>= full surface passthrough;hosted_vllm/<model>= tool schemas silently edited (strict + additionalProperties stripped). Pick deliberately. - Set
drop_params: true(or per-modeladditional_drop_params) — otherwise unsupported params surface as HTTP 500 UnsupportedParamsError. - Statelessness makes any replica valid — no affinity needed.
Debugging a CC streaming issue
- Capture raw SSE:
curl -sN http://host:port/v1/chat/completions -H "Content-Type: application/json" \ -d '{"model":"<name>","max_tokens":64,"stream":true,"stream_options":{"include_usage":true},"messages":[{"role":"user","content":"hi"}]}' | head -40 - Expect data-only SSE: first chunk
delta.role, content/tool deltas keyed byindex, finish chunk, optionalchoices:[]usage chunk,[DONE]. - Check the backend's streaming row in the matrix for known deviations
(always-present null keys on SGLang, vendor
timingson llama.cpp, role-on-every-chunk + whole-blob tools on Ollama, raw non-JSON error lines on mistral.rs, missing [DONE] on OGX). - If tool calls vanish client-side: check whether the first delta carried
id+function.name, and whether the client requirestool_calls[].index(references/clients.md).
What ships with it: 7 files
62.6 KB alongside SKILL.md
references/
- backend-implementations.md19.2 KB
- clients.md9.6 KB
- cloud-compat.md8.8 KB
- gateways.md8.5 KB
- improvement-backlog.md2.2 KB
- sources.md5.0 KB
- spec.md9.2 KB
Gives 0 of the 12 instructions most containers cloud skills give
Counted across 607 of the 705 authors here whose files we hold, read 2026-09-06
- Run as non-root userin 34 of 607, across 27 files
- Use multi-stage buildsin 29 of 607
- Set resource requests and limitsin 24 of 607, across 20 files
- Configure liveness and readiness probesin 18 of 607, across 14 files
- Use named volumes for persistent datain 14 of 607, across 9 files
- Pin base image versionsin 14 of 607
- Set up environment variablesin 14 of 607, across 10 files
- Pin provider versionsin 14 of 607
- Apply least privilege RBAC permissionsin 10 of 607, across 7 files
- Create a dockerignore filein 10 of 607
- Use remote state with lockingin 9 of 607
- Pin base images by digestin 9 of 607, across 8 files
Said here and by no other author read
- Load that reference file first and answer from it
- Check the backend's row in the divergence matrix first
- Use the openai-compatible provider path for agent clients
- Confirm how thinking is toggled and which field the CoT comes back in
- Pick the model prefix deliberately
- Set drop_params to true
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once.