Skip to content

Empty model reply is sent back to the provider, so the retry always fails on Vertex AI and Mistral #1936

Description

@azanux

Problem

Sometimes a model replies with nothing: no text, no tool call.

RetryWithFeedbackPolicy then adds a message asking the model to try again, and sends the conversation a second time. But the empty reply is still in the conversation, so it is sent too.

Vertex AI and Mistral reject any request containing an empty assistant message. They answer 400, so the retry never reaches the model and can never work.

Where

In DefaultToolLoop.execute, the reply is added to the conversation before the code checks if it is empty:

state.conversationHistory.add(transformedResponse)   // empty reply added here
...
is EmptyResponseAction.FeedbackToModel -> {
    state.conversationHistory.add(UserMessage(action.message))
    continue                                          // empty reply still there
}

Tested against the real APIs

Provider Result
Gemini (Vertex AI) 400 . must include at least one parts field
Mistral 400 - Assistant message must have either content or tool_calls, but not none
Gemini (API key), OpenAI, Anthropic accepted

Gemini only fails through Vertex AI, not through the API key endpoint.

The 400 is retried with backoff. Measured on Mistral: 32s to fail with max-attempts=3. The default is 10 attempts, so about 20 minutes.

Reproduce

Make the first model reply empty, let the second call reach the real API, with RetryWithFeedbackPolicy(maxRetries = 1).

Note for mocks: AssistantMessage(" ") reproduces it on Vertex AI but not on Mistral, which accepts the space. The reply must have no text and no tool calls to fail on both.

Possible fix

Remove the empty reply before sending the retry:

state.conversationHistory.removeAt(state.conversationHistory.lastIndex)
state.conversationHistory.add(UserMessage(action.message))

Only on the retry path. When the loop stops on an empty reply instead of retrying, that reply is the answer and the caller should still get it.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions