A model reply can read as complete and still be cut off, be waiting on a tool, or have been filtered. The visible text cannot tell your application which of these happened. Read the provider’s completion field on every response, store the raw value, and branch on that value rather than on how the text looks. OpenAI Chat Completions calls the field finish_reason; Anthropic Messages calls it stop_reason. The names and values differ, so each provider needs its own mapping.
Why the visible text is not evidence
A truncated answer often stops mid-sentence, but not always. A token cap can land at the end of a paragraph. A response that asks for a tool to run may contain little or no user-facing text. A filtered or refused response can be a short, ordinary-looking sentence. Heuristics based on punctuation, length, or a closing phrase will misclassify some replies in both directions. The reliable signal is the completion field the API returns with the response.
As an Amazon Associate I earn from qualifying purchases.
The field and its values, by provider
The two main chat-style APIs use different field names and different value sets. Do not write one shared enum and assume both providers fill it the same way.
OpenAI Chat Completions: finish_reason
The OpenAI Chat Completions reference documents these values:
#1 Best Overall
- stop: the model reached a natural stopping point, or a configured stop sequence was produced.
- length: the maximum token count was reached before the model finished.
- tool_calls: the model made one or more tool calls.
- content_filter: content was omitted because of a filter.
- function_call: a deprecated value. It appears in the reference as deprecated, so new code should not depend on it as a primary branch.
Anthropic Messages: stop_reason
Anthropic states in its stop reasons documentation that every successful Messages API response includes a stop_reason field. The documented values are:
- end_turn: the model finished its turn naturally.
- max_tokens: the response hit the token limit you set.
- stop_sequence: generation ended at a configured stop sequence.
- tool_use: the model is asking your client to run one or more tools.
- pause_turn: a server-side tool turn was paused.
- refusal: the model declined the request.
- model_context_window_exceeded: the context window limit was reached.
Map each raw value to an internal outcome
The table below shows a suggested internal mapping. The outcome names are application-level labels, not vendor terms. Each row keeps the raw value so you can remap it later if the provider changes its documentation. Because the handling guidance differs between providers, the mapping is provider-aware.
Rank #2
- Used Book in Good Condition
| Provider and field | Raw value | Suggested internal outcome |
|---|---|---|
| OpenAI finish_reason | stop | complete |
| OpenAI finish_reason | length | continue_or_retry (treat as potentially incomplete) |
| OpenAI finish_reason | tool_calls | run_tool (pending application work, not final) |
| OpenAI finish_reason | content_filter | refusal_or_filter |
| OpenAI finish_reason | function_call (deprecated) | run_tool if your code still receives it; log it as deprecated |
| Anthropic stop_reason | end_turn | complete |
| Anthropic stop_reason | max_tokens | continue_or_retry (treat as potentially incomplete) |
| Anthropic stop_reason | stop_sequence | complete only if your stop sequence marks the end of the answer; otherwise review |
| Anthropic stop_reason | tool_use | run_tool (pending application work, not final) |
| Anthropic stop_reason | pause_turn | continue the paused turn |
| Anthropic stop_reason | refusal | refusal_or_filter |
| Anthropic stop_reason | model_context_window_exceeded | context_overflow (handle before retrying) |
A tool handoff is not a final answer
When the model asks for a tool, the response is an instruction to your code, not a result for the user. Both providers signal this with a distinct value: tool_calls on OpenAI Chat Completions and tool_use on Anthropic Messages. Your agent loop should execute the requested tools, return the results in the form the provider expects, and call the model again. Marking the interaction complete at this point will show the user an unfinished turn as if it were the answer.
Free tools Windows power users keep installed
One-click scans. No signup required.
Streaming: wait for the terminal state
Streaming responses pass through an intermediate state. The OpenAI streaming events reference says finish_reason can be null while the stream is still unfinished. A null value is not a stop reason. Record the classification only after the stream reaches its terminal event. If the connection drops before that event, store the stream as interrupted rather than guessing at a finish reason from the partial text.
Rank #3
Token limits and truncation
OpenAI’s length and Anthropic’s max_tokens both mean the output limit stopped generation. Treat the text as potentially incomplete. Your options include raising the output limit and retrying, or sending the partial output back to the model with an instruction to continue. The continuation approach needs testing against your own prompts, because the model may repeat text or change its formatting when it resumes. Whichever path you choose, do not show the truncated text as the final answer without a visible notice or a retry.
Refusals, filters, and context overflow
These endings need their own handling and should not be retried blindly. OpenAI’s content_filter means content was omitted. Anthropic’s refusal means the model declined. Anthropic’s model_context_window_exceeded means the input and output together reached the context limit. For context overflow, shorten or summarize the conversation before sending it again. For filters and refusals, show a neutral message and log the event, then follow your product’s policy for what to do next. The provider documentation describes these cases, and your branches should follow the handling guidance on the linked pages rather than your own assumptions.
Rank #4
OpenAI Responses API uses a different vocabulary
If you use OpenAI’s Responses API, do not carry Chat Completions field names over to it. The OpenAI Responses streaming events reference describes a separate model: incomplete details such as max_output_tokens, and an incomplete reason tied to steering that is followed by a successor response event. Read the status and incomplete details from the Responses event model and map them separately.
What to store with each response
For debugging and future remapping, record the following for every model call:
Best Value
- The provider name and API family (for example, Chat Completions, Messages, or Responses).
- The raw completion or stop value, exactly as returned.
- Whether a streamed response reached its terminal event.
- Any incomplete or error detail the response includes.
- The derived internal outcome, stored as a separate field.
The fields above are engineering practice inferred from the provider schemas. Neither provider’s documentation sets a universal logging schema, retention period, or privacy rule. Set retention and access rules according to your own data and policy requirements, especially where responses contain user content.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




