Use these patterns to keep tool-calling deterministic and debuggable.
Pattern 1: Chat Completions loop
- Send user message + tool definitions.
- If
finish_reason is tool_calls, execute each tool call.
- Send tool outputs back as
role: "tool" messages.
- Read final assistant answer.
Request (continuation)
{
"model": "openai/gpt-5-nano",
"messages": [
{ "role": "user", "content": "What is the weather in Seattle?" },
{
"role": "assistant",
"content": null,
"tool_calls": [
{
"id": "call_123",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\":\"Seattle\"}"
}
}
]
},
{
"role": "tool",
"tool_call_id": "call_123",
"content": "72F and sunny"
}
],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"parameters": {
"type": "object",
"properties": { "city": { "type": "string" } },
"required": ["city"]
}
}
}
]
}
Pattern 2: Responses loop
For /v1/responses, model tool calls appear as output items of type function_call.
Then send a follow-up request with function_call_output input items.
Request (follow-up)
{
"model": "openai/gpt-5-nano",
"input": [
{
"type": "message",
"role": "user",
"content": [{ "type": "input_text", "text": "What's the weather in Seattle?" }]
},
{
"type": "function_call",
"call_id": "call_123",
"name": "get_weather",
"arguments": "{\"city\":\"Seattle\"}"
},
{
"type": "function_call_output",
"call_id": "call_123",
"output": "72F and sunny"
}
]
}
Endpoint selection
- Prefer
/v1/chat/completions if you already use OpenAI-style message loops.
- Prefer
/v1/responses if your app is standardized on the Responses API.
- Use
/v1/messages if your app is Anthropic-native.
Last modified on February 18, 2026