Skip to content

fix: append trailing user turn in native Gemini provider - #6973

Open
hvlcrs wants to merge 4 commits into
crewAIInc:mainfrom
hvlcrs:fix/gemini-trailing-model-turn
Open

fix: append trailing user turn in native Gemini provider#6973
hvlcrs wants to merge 4 commits into
crewAIInc:mainfrom
hvlcrs:fix/gemini-trailing-model-turn

Conversation

@hvlcrs

@hvlcrs hvlcrs commented Aug 12, 2026

Copy link
Copy Markdown

Summary

Fixes #6984.

Gemini's generateContent API rejects a request whose history ends on a model turn (400 'Requests ending with a model turn are not supported.'). CrewAI's own agent loop (handle_max_iterations_exceeded, task guardrail/guardrail_max_retries retries) can produce exactly that history. This covers both places a Gemini call can be dispatched from:

  • Native provider: GeminiCompletion._format_messages_for_gemini maps assistant messages to Gemini's model role (in both the plain-text and tool-call branches) but never checked whether the resulting contents list ends on model. Now appends a trailing user types.Content when it does.
  • LiteLLM fallback: reached when google-genai isn't installed, or the model name isn't recognized as native (custom deployments, new previews, fine-tunes). LLM._format_messages_for_provider already guards this exact case for Mistral and Ollama, but had no Gemini branch — and litellm's own Vertex/Gemini transformation doesn't guard it either (checked litellm/llms/vertex_ai/gemini/transformation.py). Added a Gemini branch mirroring the existing Mistral one.

Test plan

  • uv run --package crewai pytest lib/crewai/tests/llms/google/test_google.py -v — 46 passed, 1 skipped, 1 pre-existing unrelated failure (test_gemini_raises_error_when_model_not_supported, fails identically on main without this change; requires the litellm extra which isn't installed for that test module).
  • uv run --package crewai pytest lib/crewai/tests/test_llm.py — 66 passed, 3 skipped, no failures.
  • Added test_gemini_message_formatting_appends_user_turn_after_trailing_model_turn and test_gemini_message_formatting_leaves_user_terminated_history_unchanged in tests/llms/google/test_google.py (native provider).
  • Added test_gemini_litellm_appends_user_message_when_last_is_assistant and test_gemini_litellm_does_not_modify_when_last_is_user in tests/test_llm.py (LiteLLM fallback), mirroring the existing Ollama tests.

GeminiCompletion._format_messages_for_gemini maps assistant messages
to Gemini's 'model' role but never guards against the resulting
contents list ending on a model turn. CrewAI's own agent loop (max
iterations, guardrail retries) can produce exactly that history, and
Gemini's generateContent API rejects it with 400 'Requests ending
with a model turn are not supported'.

Mirrors the existing Mistral/Ollama guard in
LLM._format_messages_for_provider, which never applies to Gemini
since gemini/google model strings resolve to this native provider
instead of the LiteLLM fallback path.

Fixes crewAIInc#6972
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 40888763-4645-42e8-a868-cb2df6f11d1b

📥 Commits

Reviewing files that changed from the base of the PR and between 5765912 and 3a4a52a.

📒 Files selected for processing (2)
  • lib/crewai/src/crewai/llms/providers/gemini/completion.py
  • lib/crewai/tests/llms/google/test_google.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/crewai/src/crewai/llms/providers/gemini/completion.py

📝 Walkthrough

Walkthrough

Gemini formatters now append a synthetic user continuation message after assistant or model-ending history. The native formatter raises a ValueError for unresolved function calls. Tests cover native Gemini and LiteLLM formatting.

Changes

Gemini message formatting

Layer / File(s) Summary
Add trailing user continuation and function-call validation
lib/crewai/src/crewai/llms/providers/gemini/completion.py, lib/crewai/src/crewai/llm.py
The formatters append a user message containing “Please continue.” after assistant or model-ending history. The native Gemini formatter raises a ValueError when the final model turn contains an unresolved function call.
Validate Gemini history termination
lib/crewai/tests/llms/google/test_google.py, lib/crewai/tests/test_llm.py
Tests verify continuation messages, unchanged user-terminated histories, input preservation, and unresolved function call errors.

Suggested reviewers: lorenzejay

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes satisfy issue #6972 by handling trailing model turns in native Gemini and LiteLLM paths with regression tests.
Out of Scope Changes check ✅ Passed All code and test changes support Gemini trailing-turn handling or safe unresolved function-call behavior.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title clearly identifies the primary change: appending a trailing user turn for the native Gemini provider.
Description check ✅ Passed The description directly explains the Gemini formatting fix, both provider paths, the error case, and the regression tests.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/crewai/src/crewai/llms/providers/gemini/completion.py`:
- Around line 675-684: Update the model-ending handling around the contents
construction to inspect the final model Content’s parts before appending the
synthetic “Please continue.” turn. If it contains an unresolved function_call,
route it through the existing function-response handling or raise a targeted
error instead; only append the continuation prompt for model turns without
pending calls. Add a regression test covering an assistant tool_calls message
with no subsequent tool response.

In `@lib/crewai/tests/llms/google/test_google.py`:
- Around line 517-519: Strengthen the assertions around
_format_messages_for_gemini by verifying the complete formatted message
sequence, including each expected role and exact text such as "Please continue."
Confirm that the original test_messages retain their original roles and "Hello"
content after formatting, covering both relevant assertion blocks without
relying only on implementation details.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f7698c15-9527-4436-8012-722c9b983ebe

📥 Commits

Reviewing files that changed from the base of the PR and between 28d868c and a74770e.

📒 Files selected for processing (2)
  • lib/crewai/src/crewai/llms/providers/gemini/completion.py
  • lib/crewai/tests/llms/google/test_google.py

Comment thread lib/crewai/src/crewai/llms/providers/gemini/completion.py
Comment thread lib/crewai/tests/llms/google/test_google.py Outdated
hvlcrs and others added 3 commits August 12, 2026 17:57
LLM._format_messages_for_provider already guards Mistral/Ollama
against a trailing assistant turn, but Gemini models routed through
the LiteLLM fallback (no google-genai installed, or a model name not
recognized as native) had no equivalent guard. litellm's own
Vertex/Gemini transformation doesn't handle this either, so the
request reaches Gemini's generateContent API unguarded and 400s.

Complements the native-provider fix in GeminiCompletion, covering
both dispatch paths.
Address CodeRabbit review on crewAIInc#6973: appending a plain 'Please
continue.' user turn after a trailing model turn that contains an
unresolved function_call violates Gemini's function-calling protocol
-- it requires a matching functionResponse, not free text. Raise a
targeted error instead so the caller notices rather than silently
sending a malformed follow-up.

Also strengthens the native-provider formatting tests to assert exact
role sequence and text content (not just the last role), per review,
and adds a regression test for the unresolved-function-call case.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Gemini native provider never appends trailing user turn -> 400 'Requests ending with a model turn are not supported'

1 participant