Skip to main content
Tool calling uses the OpenAI shape: you send tools, the model answers with tool_calls, you run them and send the results back as tool messages.
Whether a given model calls tools well is the provider’s business, not warpllm’s. warpllm forwards tools and tool_choice and returns whatever comes back. Check the provider’s own docs before assuming a model supports them.

The exchange

1

Send tool definitions with the request

2

The model answers with tool_calls

finish_reason is tool_calls, and message.content is null.
arguments is a JSON string, not an object. Parse it, and treat a parse failure as a normal outcome — models emit malformed JSON.
3

Append the assistant turn and one tool message per call

Each tool message carries the tool_call_id it answers.
4

Call again with the extended message list

The model now has the results and produces its final answer. Loop until finish_reason is no longer tool_calls.

A complete loop

Forcing a tool

tool_choice controls whether the model may, must, or must not call one.

Tool calls in a stream

Streamed tool calls arrive as fragments, and arguments is built up across chunks. Reassemble by index.
Do not parse arguments until the stream ends. A fragment is a slice of a JSON string, and a slice of valid JSON is rarely valid JSON.

Custom tool calls

Alongside type: "function", the response types model type: "custom" calls, which carry custom: { name, input } — a raw string rather than JSON arguments. Branch on type before reaching for function.

Next

Structured outputs

When you want a shaped answer rather than a function call.

Streaming

The chunk shape these fragments arrive in.