Chat Completions API tool use
POST /v1/chat/completions accepts OpenAI’s standard function-tool
shape. Definitions and tool_choice flow through verbatim — no
Kindo-specific wrapping.
Define a function tool
{ "model": "claude-sonnet-4-5-20250929", "messages": [ { "role": "user", "content": "What is the weather in San Francisco?" } ], "tools": [ { "type": "function", "function": { "name": "get_weather", "description": "Get the current weather for a city.", "parameters": { "type": "object", "properties": { "location": { "type": "string" } }, "required": ["location"] } } } ], "tool_choice": "auto"}Note the nested function object — that’s the Chat Completions tool
shape (different from the Responses API, where name /
description / parameters sit at the top level of the tool entry).
Round trip
Step 1 — initial request
Submit the request above.
Step 2 — assistant message with tool_calls
{ "id": "chatcmpl-abc123", "object": "chat.completion", "choices": [ { "index": 0, "message": { "role": "assistant", "content": null, "tool_calls": [ { "id": "call_abc", "type": "function", "function": { "name": "get_weather", "arguments": "{\"location\":\"San Francisco, CA\"}" } } ] }, "finish_reason": "tool_calls" } ]}finish_reason: "tool_calls" is the canonical signal that the model
wants you to execute a tool.
Step 3 — execute the tool client-side
Run get_weather("San Francisco, CA") in your application.
Step 4 — submit the result
Send a follow-up request with the assistant message preserved and a
new tool message carrying the result:
curl -X POST https://api.kindo.ai/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $KINDO_API_KEY" \ -d '{ "model": "claude-sonnet-4-5-20250929", "messages": [ { "role": "user", "content": "What is the weather in San Francisco?" }, { "role": "assistant", "content": null, "tool_calls": [ { "id": "call_abc", "type": "function", "function": { "name": "get_weather", "arguments": "{\"location\":\"San Francisco, CA\"}" } } ] }, { "role": "tool", "tool_call_id": "call_abc", "content": "{\"temperature\":68,\"unit\":\"fahrenheit\"}" } ], "tools": [ { "type": "function", "function": { "name": "get_weather", "description": "Get the current weather for a city.", "parameters": { "type": "object", "properties": { "location": { "type": "string" } }, "required": ["location"] } } } ] }'The tool_call_id must match the one from Step 2. Re-include
tools so the model still sees the schema.
Step 5 — final answer
{ "choices": [ { "index": 0, "message": { "role": "assistant", "content": "It's 68 °F in San Francisco." }, "finish_reason": "stop" } ]}tool_choice
| Value | Behavior |
|---|---|
"auto" (default) | The model decides whether to call a tool. |
"none" | The model must produce a message; never a tool call. |
"required" | The model must call at least one tool. |
{type: "function", function: {name: "..."}} | The model must call exactly that function. |
See also
- Request shape — full field reference.
- Streaming —
delta.tool_callsevents. - Errors — error envelopes for tool-call failures and provider passthrough.