Skip to main content
warpllm speaks the OpenAI chat-completions shape. Your request crosses to the provider verbatim — nothing is renamed on the way in, and nothing is renamed on the way back.

The request

Only model and messages are required.

Fields warpllm models

string
required
A provider/model routing string. See Model routing.
array
required
Conversation turns. Each message carries role and content, plus tool_calls and tool_call_id where the turn is part of a tool-calling exchange. content is a string or an array of content parts (text, image, audio, file, refusal).
number
Sampling temperature.
integer
Ceiling on tokens generated for the completion.
number
Nucleus sampling cutoff.
string | string[]
Sequences that end generation.
boolean
true returns chunks instead of one reply. See Streaming.
object
{ "include_usage": true } asks for a final usage chunk.
array
Tool definitions the model may call. See Tool calling.
string | object
Whether and which tool the model must call.
object
{ "type": "json_object" } or a JSON Schema. See Structured outputs.
string
Reasoning budget hint for models that accept one.

Fields warpllm does not model

A field absent from that list is forwarded to the provider untouched rather than rejected. This is deliberate: a provider parameter warpllm has not learned yet is still usable today.
In Python the request parameter is a Mapping, so any key type-checks. In TypeScript chatCompletions is generic in the request type, which is what lets { ...request, seed: 7 } compile without a cast. In Rust the struct carries a flattened unknown_fields map that round-trips anything it does not name.
Rust nests the request fields that are optional and nullable, the same way responses do: temperature, max_tokens, top_p, stop, stream_options, reasoning_effort, and a message’s content are all Option<Option<_>>. The outer layer is “send the key at all”, the inner one “send it as an explicit null”.For an ordinary prompt, skip both states with the constructor:
temperature, max_tokens, and top_p gained the nested shape in 0.5.0. On 0.4.0 and earlier they are plain Option<_> — write Some(0.2) there. Python and TypeScript are unaffected either way.

The response

A non-streamed call returns one whole completion.
model in the response is warpllm’s routing string, not the upstream name. A reply to openrouter/anthropic/claude-sonnet-4 says exactly that, so a log line identifies the route you asked for.

Response fields

string
required
string
required
integer
required
string
required
The provider/model string that was routed.
array
required
Each carries index, finish_reason, message, and optional logprobs. The message carries content, refusal, role, and optional annotations, audio, function_call, and tool_calls.
object
prompt_tokens, completion_tokens, total_tokens, plus prompt_tokens_details (cached_tokens, cache_write_tokens, audio_tokens) and completion_tokens_details (reasoning_tokens, accepted_prediction_tokens, rejected_prediction_tokens, audio_tokens) where the provider reports them.
string
string
object
Provider moderation results, where the provider returns them.

Why responses come back as plain data

The bindings hand you the JSON shape rather than a wrapper object. Rust has already parsed and validated the response; rebuilding it into Python or JavaScript objects would redo that work to return the same fields under the same names. So Python reads completion["choices"][0]["message"]["content"] while Node and Rust read completion.choices[0].message.content.
Absent is not null. Since 0.3.0, response fields that are both optional and nullable distinguish a key the provider omitted from one it sent as null. In Python that is a missing key versus a None value; in TypeScript undefined versus null; in Rust Option<Option<T>>. Code written against 0.2.x that treated the two as one thing needs a look.

Next

Streaming

The chunk shape and how a stream ends.

Errors

What comes back instead when a request fails.