Skip to content

[Bug] - response.completed always returns finish_reason='stop' even when response contains tool calls #19744

Closed

Description

@felixti

Bug Description

When using the Responses API (e.g., via Azure gpt-5.1-codex-mini through LiteLLM proxy), the response.completed streaming event always returns finish_reason='stop', even when the response contains function_call items in its output. This causes agents and clients that rely on finish_reason='tool_calls' to determine if tools need to be executed to incorrectly conclude the stream ended without any pending tool calls.

Environment

  • LiteLLM Version: Versions after 1.80.8-stable.1
  • Model: Azure gpt-5.1-codex-mini (any model using Responses API with tool calling)
  • Setup: LiteLLM proxy with custom provider (e.g., OpenCode)

Steps to Reproduce

  1. Configure LiteLLM proxy to route to an Azure OpenAI deployment using the Responses API
  2. Send a request with tools defined that triggers the model to make a function call
  3. Observe the streaming events

Expected Behavior

When the model decides to call a tool, the final response.completed event should return finish_reason='tool_calls' to signal the client that tools need to be executed.

Actual Behavior

The response.completed event always returns finish_reason='stop', regardless of whether the response contains function calls.

Server Log Example

23:12:38 - LiteLLM:DEBUG: transformation.py:238 - Raw OpenAI Chunk={
  'type': 'response.completed', 
  'sequence_number': 26, 
  'response': {
    'id': 'resp_...', 
    'status': 'completed', 
    'output': [
      {
        'type': 'function_call',
        'id': 'call_abc123',
        'name': 'read_file',
        'arguments': '{"path": "/tmp/test.py"}',
        'status': 'completed'
      }
    ],
    ...
  }
}

Despite the response containing a function_call in output, the transformation returns finish_reason='stop'.

Impact

This breaks tool/function calling workflows for agents like OpenCode when using newer LiteLLM versions (after 1.80.8). The agent:

  1. Receives the tool call events correctly
  2. Receives finish_reason='stop' from response.completed
  3. Concludes the stream ended normally without tools to execute
  4. Stops waiting for more input, leaving the tool call unexecuted

Users must repeatedly prompt the model to get it to respond, as the agent doesn't recognize it needs to execute the pending tool call.

Root Cause

In litellm/completion_extras/litellm_responses_transformation/transformation.py, the response.completed handler unconditionally returns finish_reason='stop':

elif event_type == "response.completed":
    return ModelResponseStream(
        choices=[
            StreamingChoices(
                index=0,
                delta=Delta(content=""),
                finish_reason="stop",  # BUG: Should check for function_call items
            )
        ]
    )

Suggested Fix

Inspect the response.output field in the response.completed event to determine the correct finish_reason:

  • Return 'tool_calls' when output contains function_call items
  • Return 'stop' otherwise

Activity

  1. changed the title [-]response.completed always returns finish_reason='stop' even when response contains tool calls[/-] [+][Bug] - response.completed always returns finish_reason='stop' even when response contains tool calls[/+] on Jan 29, 2026
  2. tkyggit commented on Feb 5, 2026

    @tkyggit

    It’s great.
    I look forward to the release where this code is merged.

    I was also having trouble because it wouldn't work at all when going from opencode through litellm. I encountered what seemed to be the same issue with Azure OpenAI and Ollama GPT-OSS.

  3. anuragxxd commented on Feb 12, 2026

    @anuragxxd

    I’m seeing the same problem. Looking forward to getting this merged.

  4. mWozDev commented on Feb 14, 2026

    @mWozDev

    @krrishdholakia can the associated PR be merged? this issue is also prevalent for multiple users I know as well that have been affected

  5. JosXa commented on Feb 17, 2026

    @JosXa

    We just installed v1.81.13 (which, from what I can tell, should include #19745) and there was zero improvement:

    Image

    @felixti is that the right release?

    Edit: Ah, apparently not. Eagerly waiting for the release here @krrishdholakia :)

  6. kavolorn commented on Sep 1, 2026

    @kavolorn

    Looks like issue still exists. I cannot use DeepSeek V4 (both Flash and Pro) with Ollama.

    I'm defining my Ollama model like that:

    - model_name: deepseek-v4-flash
        litellm_params:
          model: ollama_chat/deepseek-v4-flash:0731
          api_base: https://ollama.com
          api_key: os.environ/OLLAMA_API_KEY

    This response I get:

    {
        "id": "f62f763b-d2fc-4c1f-ab47-088d268a1ffd",
        "model": "deepseek-v4-flash:0731",
        "usage": {
            "total_tokens": 12963,
            "prompt_tokens": 12879,
            "completion_tokens": 84,
            "prompt_tokens_details": null,
            "completion_tokens_details": {
                "text_tokens": null,
                "audio_tokens": null,
                "image_tokens": null,
                "video_tokens": null,
                "reasoning_tokens": 42,
                "accepted_prediction_tokens": null,
                "rejected_prediction_tokens": null
            }
        },
        "object": "chat.completion",
        "choices": [
            {
                "index": 0,
                "message": {
                    "role": "assistant",
                    "content": null,
                    "tool_calls": [
                        {
                            "id": "6f890a8f-23b9-4aa4-929c-3d2b2fba5d7f",
                            "type": "function",
                            "function": {
                                "name": "terminal",
                                "arguments": "{\"command\": \"date\"}"
                            }
                        }
                    ],
                    "function_call": null,
                    "reasoning_content": "The user asks for the current datetime. I have system info: Today's Date: 2026-09-01. But I should give the actual current datetime. Let me check viaterminal."
                },
                "finish_reason": "stop"
            }
        ],
        "created": 1788230116,
        "system_fingerprint": null
    }
    

    Finish reason forces agent to stop turns.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions