Skip to main content
Use these patterns to keep tool-calling deterministic and debuggable.

Pattern 1: Chat Completions loop

  1. Send user message + tool definitions.
  2. If finish_reason is tool_calls, execute each tool call.
  3. Send tool outputs back as role: "tool" messages.
  4. 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