Skip to main content
Chat Completions API exposes reasoning through chat-compatible fields on assistant messages and streaming deltas. Use this page if you need reasoning controls but your integration still depends on OpenAI chat request and response shapes.

Request Controls

Use reasoning_effort on supported models.
from openai import OpenAI

client = OpenAI(
    base_url="https://api.naga.ac/v1",
    api_key="YOUR_API_KEY",
)

completion = client.chat.completions.create(
    model="gpt-5",
    messages=[
        {
            "role": "user",
            "content": "Explain the likely root cause of a slow PostgreSQL query and suggest the first two checks.",
        }
    ],
    reasoning_effort="medium",
)

print(completion.choices[0].message.content)
Supported normalized values are:
  • none
  • minimal
  • low
  • medium
  • high
  • xhigh
Start with the lowest setting that gives acceptable quality.

Response Shape

Depending on the model behind this compatibility layer, reasoning can appear in assistant messages as reasoning_details or reasoning_content.
{
  "role": "assistant",
  "content": "Start by checking the query plan and index usage.",
  "reasoning_details": [
    {
      "type": "reasoning.summary",
      "summary": "Need to compare common causes before answering."
    },
    {
      "type": "reasoning.encrypted",
      "data": "enc_123"
    }
  ]
}

Streaming Behavior

When streaming is enabled, reasoning can arrive in choices[0].delta as:
  • reasoning_details entries such as reasoning.summary, reasoning.text, or reasoning.encrypted
  • reasoning_content on providers that use the older single-field shape
Not every reasoning-capable model exposes visible reasoning on this surface.

Preserve Reasoning Blocks

This gateway is stateless. If a model pauses for tool use and returns reasoning_details, send those details back unchanged in the assistant message when you continue the conversation with the later role: tool result.
{
  "model": "gpt-4.1",
  "messages": [
    {
      "role": "user",
      "content": "What is the weather in Prague and should I bring a coat?"
    },
    {
      "role": "assistant",
      "content": null,
      "reasoning_details": [
        {
          "type": "reasoning.summary",
          "summary": "Need live weather data before answering."
        },
        {
          "type": "reasoning.encrypted",
          "data": "enc_123"
        }
      ],
      "tool_calls": [
        {
          "id": "call_1",
          "type": "function",
          "function": {
            "name": "lookup_weather",
            "arguments": "{\"city\":\"Prague\"}"
          }
        }
      ]
    },
    {
      "role": "tool",
      "tool_call_id": "call_1",
      "content": "{\"temperature_c\":7,\"raining\":true}"
    }
  ],
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "lookup_weather",
        "description": "Look up current weather for a city.",
        "parameters": {
          "type": "object",
          "properties": {
            "city": { "type": "string" }
          },
          "required": ["city"]
        }
      }
    }
  ]
}
Treat reasoning_details as model output. Do not edit, reorder, or partially replay them if you want the model to continue from the same reasoning state.

Caveats

  • not every reasoning-capable model exposes visible reasoning on this surface
  • some providers emit reasoning_details, while others still use reasoning_content
  • if a turn has no visible reasoning payload, there is nothing to replay

Common mistakes

  • assuming reasoning_details exists on every supported model
  • editing replayed reasoning payloads before a follow-up tool turn
  • raising reasoning effort without measuring the cost and latency tradeoff