Skip to content

Conversation

@thesynapses
Copy link

fix: Preserve adk-* function call IDs for Claude/OpenAI compatibility

Summary

Fixes BadRequestError when using Claude via Vertex AI or OpenAI models with ADK session continuity. When previous sessions containing tool calls are loaded and replayed, the remove_client_function_call_id() function strips adk-* prefixed IDs, but Claude/OpenAI require these IDs to be present.

Resolves #4348

Problem

When ADK replays session history that contains tool calls:

  1. Gemini returns id=None for function calls (confirmed in official docs)
  2. ADK generates adk-* IDs via populate_client_function_call_id() to fill this gap
  3. Before sending to LLM, remove_client_function_call_id() strips all adk-* prefixed IDs
  4. Claude via Vertex AI requires tool_call_id on tool response messages → BadRequestError

Error message:

litellm.BadRequestError: litellm.BadRequestError: VertexAIException BadRequestError - 
{'error': {'message': "tool_call_id '...' not found in list of function calls in the chat history"}}

Solution

Make remove_client_function_call_id() a no-op by replacing the function body with pass:

def remove_client_function_call_id(content: Optional[types.Content]) -> None:
  """Preserves ADK-generated function call IDs for Claude/OpenAI compatibility."""
  # No-op: Keep adk-* IDs for Claude/OpenAI compatibility
  pass

Why This Works

  • Gemini compatibility preserved: Gemini ignores extra IDs in the request; it generates its own or uses None
  • Claude/OpenAI fixed: These models require tool_call_id to match tool responses to function calls
  • Session continuity works: Replayed history maintains valid IDs throughout the conversation
  • No semantic change: The adk-* prefix is just a namespace; keeping it doesn't affect model behavior

Impact

  • Fixes session continuity for Claude via Vertex AI
  • Fixes session continuity for OpenAI models
  • No breaking changes for Gemini users
  • Enables multi-turn tool-using conversations across all LiteLLM-supported models

Testing Plan

Unit Tests

Test case validates that adk-* function call IDs are preserved:

def test_remove_client_function_call_id_preserves_ids():
    """Test that adk-* function call IDs are preserved for Claude/OpenAI compatibility."""
    content = types.Content(
        parts=[
            types.Part(function_call=types.FunctionCall(
                id="adk-test-uuid-1234",
                name="test_tool",
                args={"arg1": "value1"}
            )),
            types.Part(function_response=types.FunctionResponse(
                id="adk-test-uuid-1234",
                name="test_tool",
                response={"result": "success"}
            ))
        ]
    )
    
    # Call the function
    remove_client_function_call_id(content)
    
    # IDs should be preserved (not stripped)
    assert content.parts[0].function_call.id == "adk-test-uuid-1234"
    assert content.parts[1].function_response.id == "adk-test-uuid-1234"

pytest results:

$ pytest ./tests/unittests -v -k "test_remove_client_function_call_id"
============================= test session starts ==============================
collected 1 item

tests/unittests/flows/llm_flows/test_functions.py::test_remove_client_function_call_id_preserves_ids PASSED

============================= 1 passed in 0.12s ================================

Manual E2E Tests

Setup:

  • ADK with Firestore session storage
  • Claude via Vertex AI model (claude-sonnet-4-5@20250929)
  • Agent with tool calls (Google Drive agent)

Test Flow:

  1. Send: @drive list 2 recent files
  2. Agent uses list_drive_files tool, response saved with adk-* IDs
  3. Send follow-up: show me the first one
  4. Session history with tool calls replayed to Claude

Before fix:

litellm.BadRequestError: VertexAIException BadRequestError - 
{'error': {'message': "tool_call_id '...' not found in list of function calls"}}

After fix:

✅ Session history replayed successfully
✅ Claude received tool_call_id and processed correctly
✅ Follow-up response generated with context from previous tool call

Screenshot/Log (after fix):

DEBUG | services.memory.memory_service - Found 1 previous ADK session(s) for agent: drive
DEBUG | services.spark.spark_generation_orchestrator - ♻️ Loaded ADK session: session_id=93eece1a-a5d9-4288-826e-cb35866a5000, events=4
INFO  | LiteLLM completion() model= claude-sonnet-4-5@20250929; provider = vertex_ai
DEBUG | services.spark.spark_generation_orchestrator - ✅ AGENT_EXEC_COMPLETE: chunks=15, duration=8.2s

Additional Context

  • Root cause: Session continuity feature loads previous sessions with tool calls
  • Before session continuity: Every request was a fresh session, no history to replay
  • The populate_client_function_call_id() function correctly generates IDs when missing
  • Only the remove_* function needs modification
  • Gemini's official docs show id=None in function call examples, confirming ADK must generate IDs

Previously, remove_client_function_call_id() stripped adk-* prefixed IDs
before sending to LLM. This breaks Claude via Vertex AI and OpenAI models
which require tool_call_id on tool response messages.

When using session continuity with tool calls in history:
1. Gemini returns id=None for function calls
2. ADK generates adk-* IDs via populate_client_function_call_id()
3. remove_client_function_call_id() stripped these IDs
4. Claude/OpenAI fail with BadRequestError: tool_call_id not found

The fix preserves these IDs since:
- Claude via Vertex AI requires tool_call_id
- OpenAI models require matching tool_call_id
- Gemini ignores extra IDs (generates its own or uses None)
- Session continuity requires IDs to persist across replayed history
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @thesynapses, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request resolves a critical compatibility issue affecting multi-turn conversations with Claude and OpenAI models when utilizing ADK's session continuity. By preventing the removal of ADK-generated function call IDs, the change ensures that these models can correctly process tool responses, thereby eliminating BadRequestError and enabling seamless, stateful interactions.

Highlights

  • Problem Addressed: Fixes BadRequestError when using Claude via Vertex AI or OpenAI models with ADK session continuity. The error occurred because adk-* prefixed function call IDs, generated by ADK for session replay, were being stripped before being sent to these LLMs, which require them for matching tool responses.
  • Solution Implemented: The remove_client_function_call_id() function has been modified to become a no-op, effectively preserving the adk-* prefixed function call IDs. This ensures that Claude and OpenAI models receive the necessary tool_call_id for proper session continuity.
  • Compatibility and Impact: This change maintains compatibility with Gemini models (which ignore extra IDs), fixes session continuity for Claude and OpenAI, and enables robust multi-turn tool-using conversations across all LiteLLM-supported models without introducing breaking changes.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request addresses a BadRequestError with Claude and OpenAI models by preserving adk-* prefixed function call IDs during session replay. The fix is implemented by making remove_client_function_call_id a no-op, which is a clean and effective solution. The change is well-documented in both the PR description and the code's docstring. My only suggestion is to update the placeholder in a code comment to reference the correct GitHub issue number.

@adk-bot adk-bot added the models [Component] Issues related to model support label Feb 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

models [Component] Issues related to model support

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BadRequestError: tool_call_id not found when using Claude/OpenAI with session history containing tool calls

2 participants