Skip to content

provider-openai: recovered incomplete streaming response can leave unpaired function_call items, permanently breaking the session #353

Description

@danshapiro

Summary

provider-openai has a recovery path that salvages non-completed streaming responses:

[PROVIDER] OpenAI recovered a non-completed streaming response (status=incomplete...): returning the partial response instead of failing.

(The warning references amplifier-support#339; that repo is not publicly resolvable, so this issue is filed here.)

When the salvaged partial response contains a function_call item, the salvage can leave that call unpaired (no function_call_output) in persisted conversation history. Because the Responses API requires every function_call item in replayed input to have a matching function_call_output, every subsequent request in the session fails — the session is permanently wedged and no retry can ever succeed.

Observed behavior

  • Model: gpt-5.6-sol, with enable_response_chaining: auto.

  • A chained continuation response (llm:response event with continuation_count: 1, output_tokens: 2050, cost_usd: null, 2026-08-01) ended non-completed and was salvaged by the recovery path.

  • The salvaged partial contained:

    1. A function call with truncated/empty arguments {}, which failed tool schema validation ("Command is required").
    2. A function_call item (call_NpD59KEhgybRvh2IyJ4AEWKF) that never received a function_call_output.
  • Every subsequent request in that session failed with:

    InvalidRequestError: "No tool output found for function call call_NpD59KEhgybRvh2IyJ4AEWKF"

    14 occurrences in the session log, including retries 7 hours later. Because the dangling function_call is persisted in history, retries can never succeed.

Note: the caps were NOT the cause

The request budget was max_output_tokens=128000 with a 900k context, and the turn was at ~110k input / 2k output. So the non-completed status was likely content_filter or a stream drop — but the warning text only guesses "max_output_tokens".

Proposed fix

When salvaging a non-completed response (especially mid-continuation):

  1. Drop function_call items whose arguments are truncated/unparseable.
  2. Guarantee pairing: every retained function_call must get an output — synthesize an error function_call_output (e.g. "call truncated by provider") for any salvaged call that tooling didn't execute.
  3. Log incomplete_details.reason explicitly in the salvage warning instead of guessing at the cause.

Affected code

amplifier-module-provider-openai — the streaming recovery/salvage path and response chaining.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions