Atlas Inference

Tool calling

The tools and tool_choice request shape your OpenAI client already emits.

Tool calling uses the OpenAI request and response shape unchanged. If your code already calls tools against another OpenAI-compatible provider, it works here after the base URL, key, and model change.

Every model in the catalog supports tool calling. Check capabilities.tool_calling on GET /v1/models rather than assuming it.

Making a call

The assistant message comes back with tool_calls, and finish_reason is tool_calls:

{
  "index": 0,
  "message": {
    "role": "assistant",
    "content": null,
    "tool_calls": [
      {
        "id": "call_abc123",
        "type": "function",
        "function": { "name": "get_weather", "arguments": "{\"city\":\"Lagos\"}" }
      }
    ]
  },
  "finish_reason": "tool_calls"
}

arguments is a JSON string, not an object — that is the OpenAI shape, and Atlas does not change it. Parse it defensively: a model can emit arguments that are not valid JSON, and that is a model outcome rather than an API error.

Returning a result

Append the assistant message verbatim, then one tool message per call, keyed by tool_call_id:

messages.append(completion.choices[0].message)
messages.append(
    {
        "role": "tool",
        "tool_call_id": call.id,
        "content": '{"temp_c": 31, "conditions": "humid"}',
    }
)

follow_up = client.chat.completions.create(
    model="atlas-mid-1", messages=messages, tools=tools
)

tool_choice

ValueMeaning
"auto"The model decides.
"none"Tool definitions stay in context; no call is made.
"required"The model must call some tool.
{"type": "function", "function": {"name": "..."}}The model must call that tool.

tool_choice: "none" with tools attached is not treated as a tool-calling request. It is the shape a client sends when it wants the definitions in context but no call, so it is served even by a model without tool-calling support — refusing it would refuse a request the model can answer exactly as asked.

Streaming tool calls

Tool calls stream as fragments in delta.tool_calls, each carrying an index. Accumulate by index — the name arrives in one or more fragments and the arguments string is built up across many:

{"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"call_abc123","type":"function","function":{"name":"get_weather","arguments":""}}]}}]}
{"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"ci"}}]}}]}
{"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"ty\":\"Lagos\"}"}}]}}]}

The OpenAI SDKs' accumulation helpers handle this for you. If you assemble the stream yourself, do not attempt to parse arguments until finish_reason arrives.

Refusals

Combining with structured output

Tool parameter schemas and response_format schemas are not validated the same way. A tool's parameters document is passed through to the backend as you send it. Only response_format: {"type": "json_schema"} is checked against the published JSON Schema subset.

On this page