Stop reasons

Every response from the Mira API includes a finish_reason field that indicates why the model stopped generating. Properly handling this field is critical for robust applications.

finish_reason values

ValueDescriptionAction
stopModel naturally completed its responseResponse is complete, display it
lengthReached max_tokens limitResponse truncated — increase max_tokens or continue
tool_callsModel wants to call a toolExecute the call and pass the result back
content_filterContent blocked by safety filterInform the user, modify the request

stop — natural completion

This is the most common and desired result. The model completed its response in full. It is also returned when the model encounters one of the sequences specified in the stop parameter.

Example response with stop
{
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Paris is the capital of France."
      },
      "finish_reason": "stop"
    }
  ]
}

length — truncated by token limit

Returned when the model's response reached the max_tokens value. The response is truncated and may be incomplete. To address this, you can:

  • Increase max_tokensSet a higher max_tokens value in the next request.
  • Continue generationSend a new request, adding the truncated response as an assistant message, and ask to continue.
  • Break down the taskRequest the response in parts instead of one long output.

tool_calls — function call requested

When the model decides it needs to call one of the provided tools, it stops text generation and returns a structured function call. You must execute the call and pass the result back to the model.

Response with tool_calls
{
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": null,
        "tool_calls": [
          {
            "id": "call_abc123",
            "type": "function",
            "function": {
              "name": "get_weather",
              "arguments": "{\"city\": \"Moscow\"}"
            }
          }
        ]
      },
      "finish_reason": "tool_calls"
    }
  ]
}

content_filter — content blocked

Returned when the safety filter blocked part or all of the model's response. The content field may be empty or contain a partial response.

Do not attempt to bypass the content filter by rephrasing. If your use case requires working with sensitive content, contact support.

Handling finish_reason in code

Python

Python
import requests

response = requests.post(
    "https://api.vmira.ai/v1/chat/completions",
    headers={"Authorization": "Bearer sk-mira-YOUR_API_KEY"},
    json={
        "model": "mira",
        "max_tokens": 512,
        "messages": [{"role": "user", "content": "Write a long article"}],
    },
)

data = response.json()
choice = data["choices"][0]
finish_reason = choice["finish_reason"]

if finish_reason == "stop":
    # Response is complete
    print(choice["message"]["content"])

elif finish_reason == "length":
    # Response truncated — continue or increase max_tokens
    print("Warning: response truncated!")
    print(choice["message"]["content"])

elif finish_reason == "tool_calls":
    # Model wants to call a tool
    tool_calls = choice["message"]["tool_calls"]
    for tool_call in tool_calls:
        fn_name = tool_call["function"]["name"]
        fn_args = tool_call["function"]["arguments"]
        print(f"Tool call: {fn_name}({fn_args})")

elif finish_reason == "content_filter":
    # Content blocked
    print("Response blocked by safety filter.")

JavaScript

JavaScript
const response = await fetch("https://api.vmira.ai/v1/chat/completions", {
  method: "POST",
  headers: {
    "Authorization": "Bearer sk-mira-YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "mira",
    max_tokens: 512,
    messages: [{ role: "user", content: "Write a long article" }],
  }),
});

const data = await response.json();
const choice = data.choices[0];

switch (choice.finish_reason) {
  case "stop":
    console.log(choice.message.content);
    break;

  case "length":
    console.warn("Response truncated! Increase max_tokens.");
    console.log(choice.message.content);
    break;

  case "tool_calls":
    for (const call of choice.message.tool_calls) {
      console.log(`Tool: ${call.function.name}(${call.function.arguments})`);
    }
    break;

  case "content_filter":
    console.error("Content blocked by filter.");
    break;
}
Always check finish_reason before processing the response. Assuming the response is complete without checking is a common source of bugs.

Streaming and finish_reason

During streaming, finish_reason arrives in the last chunk. In all previous chunks it is null. Process the final chunk to determine the stop reason.

Next steps