Repository navigation
Unintended user message injection breaks tool calling with LiteLLM + OpenAI/Azure #4249
Description
Activity
- addedmodels[Component] This issue is related to model support[Component] This issue is related to model support
on Jan 23, 2026 I have the same issue. Is there a workaround for this issue?
I have the same issue. Is there a workaround for this issue?
Actually solved by freezing the library version to
google-adk==1.22.1. A workaround is feasible, but requires a ton of overriding as the issue is nested into the adk codebase.class OpenAILiteLlm(LiteLlm): """LiteLlm with fix for OpenAI API compatibility. ADK's _append_fallback_user_content_if_missing adds an extra user message after tool responses, which breaks OpenAI's API format. This class prevents that by ensuring function_response parts have payload (inline_data) so the fallback check passes. """ async def generate_content_async( self, llm_request: LlmRequest, stream: bool = False ) -> AsyncGenerator[LlmResponse, None]: # Add inline_data to function_response parts so _part_has_payload returns # True and _append_fallback_user_content_if_missing doesn't add fallback for content in llm_request.contents or []: if content.role != "user": continue for part in content.parts or []: if part.function_response and not part.inline_data: part.inline_data = types.Blob(data=b" ", mime_type="text/plain") async for response in super().generate_content_async(llm_request, stream): yield response
I ended up with this fix, tricking ADK to think this is a message with user payload so it won't auto append the user message again.
Reacted by GitMarco27, Simone Eandi and mmr94I ended up with this fix, tricking ADK to think this is a message with user payload so it won't auto append the user message again.
A bit dirty, but does the job!
+1 Bump.
I hit this issue and moved back one version - only to hit another issue with compaction.
Reacted by GitMarco27Same Issue as well, triggering Azure JailBreak detection during tool calling.
Reacted by GitMarco27I am also facing the same issue!
Reacted by GitMarco27I was able to debug and reproduce this issue.
Normally, when a tool returns a response, the function_response should be sent back to the model so the model can generate the final user-facing reply.However, in lite_llm.py, ADK only checks for payload in Part(text) (and a few other fields) and does not treat Part(function_response) as valid payload. Because of this, the payload check returns false even though a valid tool response exists.
As a result, the following fallback logic is triggered, which appends the default text:
"Handle the requests as specified in the System Instruction."
This injected text is interpreted by Azure OpenAI as prompt injection / jailbreak content, which causes the request to fail with a content policy violation.
I was able to recreate the entire scenario locally. As a workaround, treating function_response as valid payload fixes the issue:def _part_has_payload(part: types.Part) -> bool: """Checks whether a Part contains usable payload for the model.""" if part.text: return True if part.function_response: # added return True if part.inline_data and part.inline_data.data: return True if part.file_data and (part.file_data.file_uri or part.file_data.data): return True return FalseWith this change, the fallback text is not injected and the model proceeds correctly after the tool response.
Reacted by GitMarco27@GitMarco27 @dineshkrishna9999 @seandi @CactionCCY @bhakta0007 @sandangel
https://github.com/google/adk-python/blob/main/src/google/adk/models/lite_llm.py#L503
This statement is the culprit: Handle the requests as specified in the System Instruction.
Instead use: Handle the incoming request according to the provided requirements.

- added a commit that references this issue
on Jan 29, 2026 Handle the incoming request according to the provided requirements.
I think that this instruction might still be interpreted as a jailbreak or an injection. Overall, it doesn't solve the actual issue, the introduction of unintended and unexpected context into the LLM request.
Handle the incoming request according to the provided requirements.
I think that this instruction might still be interpreted as a jailbreak or an injection. Overall, it doesn't solve the actual issue, the introduction of unintended and unexpected context into the LLM request.
@GitMarco27 It worked fine, check the second pull request mentioned above, attached screenshots.
Reacted by KrishnaReacted by Luca RanalliIt worked fine, check the second pull request mentioned above, attached screenshots.
I see, but looks like a workaround. It might break again as soon as Openai / Azure Openai updates its filters' models and policies.
It worked fine, check the second pull request mentioned above, attached screenshots.
I see, but looks like a workaround. It might break again as soon as Openai / Azure Openai updates its filters' models and policies.
Maybe.
- added a commit that references this issue
on Jan 30, 2026 - added a commit that references this issue
on Aug 11, 2026
Describe the bug
When using LiteLLM with OpenAI / AzureOpenAI models, after tool calls, an user message
"Handle the requests as specified in the System Instruction."is injected into the conversation history. This message triggers OpenAI's prompt injection safety guards and causes the request to fail.openai.BadRequestError: Error code: 400 - {'error': {'message': "The response was filtered due to the prompt triggering Azure OpenAI's content management policy. Please modify your prompt and retry. To learn more about our content filtering policies please read our documentation: https://go.microsoft.com/fwlink/?linkid=2198766", 'type': None, 'param': 'prompt', 'code': 'content_filter', 'status': 400, 'innererror': {'code': 'ResponsibleAIPolicyViolation', 'content_filter_result': {'hate': {'filtered': False, 'severity': 'safe'}, 'jailbreak': {'filtered': True, 'detected': True}, 'self_harm': {'filtered': False, 'severity': 'safe'}, 'sexual': {'filtered': False, 'severity': 'safe'}, 'violence': {'filtered': False, 'severity': 'safe'}}}}}Root Cause Analysis
The bug originates from an interaction between two functions in
lite_llm.py:_part_has_payload()does not considerfunction_responseas a valid payload for the model:_append_fallback_user_content_if_missing()iterates throughllm_request.contentslooking for auserContent with payload. Tool responses (function_response) are represented asContentwithrole='user'. Since_part_has_payload()returnsFalseforfunction_responseparts, the function incorrectly appends a fallback text part._content_to_message_param()then processes this Content. The newly added text part becomes anon_tool_part, which triggers the branch:This creates an extra user message with the fallback text
"Handle the requests as specified in the System Instruction.", which OpenAI's safety systems flag as potential prompt injection.Previous Behavior
In previous versions,
_content_to_message_paramhandled this by returning early whentool_messagesexisted, so the new user part was never really provided to the model invocation:This prevented the fallback text from being converted into a follow-up user message.
To Reproduce
google-adk>1.22.1"Handle the requests as specified in the System Instruction."Minimal reproduction code
Error / Stacktrace
Expected behavior
Contentobjects containing onlyfunction_responseparts should NOT have the fallback text appended. The_part_has_payload()function should returnTruefor parts that havefunction_response, recognizing that tool responses are valid payload.Proposed fix
function_responsecheck in_part_has_payload()in order to avoid appending this fallback for function responses:_append_fallback_user_content_if_missing: avoid adding a fallback user message at all as this is unexpected, dangerous and really similar to a silent failure.Desktop
Model Information
Additional context
The bug specifically affects the flow:
_append_fallback_user_content_if_missingincorrectly modifies this Content -> Extra user message is createdThis issue may not manifest with Gemini models accessed directly (without LiteLLM) because they may handle the message format differently.
This bug forbids the use of any tool calls in conjunction with LiteLLM and OpenAI models and so does not allow me to use the latest releases of Google ADK