Skip to main content

Transparent by default

Sideren doesn’t run tools and doesn’t rewrite them. Every tool you define (any number, any names and schemas, function and custom tools), your tool_choice, parallel_tool_calls and strict settings, the model’s tool calls and your tool results are carried exactly as sent — on Chat Completions, Responses and Messages. Tool calls the model emits are forwarded as-is and streamed immediately — including a call to a tool name you didn’t define, or arguments that don’t match your schema. That is the same behaviour you get from the model vendors’ own APIs, and it is what agent harnesses expect: they report the bad call back to the model and let it correct itself. A call cut off by max_tokens keeps its length / max_tokens stop reason and is never marked complete. Only models that declare capabilities.tools serve requests that carry tools — a handful of small open-weight models don’t. Check the catalog before you build a tool loop on one model.

1 · Define tools

2 · The model calls

When the model decides to use a tool, the response carries a call instead of (or alongside) text:
Chat Completions — finish_reason: tool_calls
Messages — stop_reason: tool_use
Parse the arguments, validate them against your schema, run the tool, and send the result back. Models may emit several calls in one turn (parallel tool use); execute them all and return one result per call id.

3 · Return results

Append the result to the conversation and call the endpoint again — the model continues with the tool output in context. Repeat until it answers in text.

Steering with tool_choice

  • auto (default) — the model decides whether to call.
  • required / { "type": "any" } — must call some tool (Chat Completions / Messages respectively).
  • Named — force one specific tool: { "type": "function", "function": { "name": "get_weather" } } or { "type": "tool", "name": "get_weather" }.
  • none — text only, tools stay visible but uncallable.
A forced or strict request only goes to a placement that actually enforces it. If none can, you get a 422 before anything is sent to a model rather than a silently weaker request.
Tool calls stream too: argument deltas arrive incrementally on both dialects (Streaming). For extracting structured data without any real tool, prefer Structured output.