Tool calling
Tool & function calling
Describe your functions, and a model that supports tools will ask you to run one. Oxyy translates the declaration into whatever each provider expects, so the same tools array works across OpenAI, Anthropic, Google, xAI and the rest.
| Parameter | Type | Required | Description |
|---|---|---|---|
| tools | array | Optional | Function declarations: {type: "function", function: {name, description, parameters}}, where parameters is a JSON Schema object. |
| tool_choice | string|object | Optional | How freely the model may call a tool. One of:noneautorequired{type:"function",function:{name}} Default auto |
| parallel_tool_calls | boolean | Optional | Allow more than one tool call per turn. Default true |
import json, os from openai import OpenAI client = OpenAI( api_key=os.environ["OXYY_API_KEY"], base_url="https://api.oxyy.ai/v1" ) tools = [{ "type": "function", "function": { "name": "get_weather", "description": "Current weather for a city.", "parameters": { "type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"], }, }, }] messages = [{"role": "user", "content": "Weather in Dhaka?"}] response = client.chat.completions.create( model="gpt-5.5", messages=messages, tools=tools, tool_choice="auto" ) call = response.choices[0].message.tool_calls[0] args = json.loads(call.function.arguments) # Run the tool yourself, then send the result back as a tool message. messages.append(response.choices[0].message) messages.append({ "role": "tool", "tool_call_id": call.id, "content": json.dumps({"temp_c": 31, "sky": "humid"}), }) final = client.chat.completions.create(model="gpt-5.5", messages=messages, tools=tools) print(final.choices[0].message.content)
import OpenAI from 'openai'; const client = new OpenAI({ apiKey: process.env.OXYY_API_KEY, baseURL: 'https://api.oxyy.ai/v1' }); const tools = [{ type: 'function', function: { name: 'get_weather', description: 'Current weather for a city.', parameters: { type: 'object', properties: { city: { type: 'string' } }, required: ['city'], }, }, }]; const messages = [{ role: 'user', content: 'Weather in Dhaka?' }]; const res = await client.chat.completions.create({ model: 'gpt-5.5', messages, tools, tool_choice: 'auto', }); const call = res.choices[0].message.tool_calls[0]; const args = JSON.parse(call.function.arguments); messages.push(res.choices[0].message, { role: 'tool', tool_call_id: call.id, content: JSON.stringify({ temp_c: 31, sky: 'humid' }), }); const final = await client.chat.completions.create({ model: 'gpt-5.5', messages, tools }); console.log(final.choices[0].message.content);
The tool-call turn
Response
{
"id": "chatcmpl-abc123",
"object": "chat.completion",
"created": 1700000000,
"model": "gpt-5.5",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": null,
"tool_calls": [
{
"id": "call_abc123",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\":\"Dhaka\"}"
}
}
],
"refusal": null
},
"logprobs": null,
"finish_reason": "tool_calls"
}
],
"usage": { "prompt_tokens": 61, "completion_tokens": 18, "total_tokens": 79, "cost": 0.00029 }
}The loop. Append the assistant message as it came back, then one
{role:"tool", tool_call_id, content}message per call, and send the whole conversation again. finish_reason is tool_callswhenever calls are present, even on providers that report stop. On reasoning models, send back any reasoning_details unmodified so the model's own thinking survives the round trip.Function tools only. Oxyy runs no hosted tools of its own — there is no web search, code interpreter or file search to enable. Declare a function and run it in your application. Anthropic's server tools are the exception: they are forwarded to the provider untouched over the Anthropic SDK.
