litellm - 💡(How to fix) Fix [Bug]: experimental_use_latest_role_message_only - parallel tool calls leave N-1 responses unchecked by Bedrock Guardrails [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
BerriAI/litellm#25228Fetched 2026-04-08 03:02:37
View on GitHub
Comments
0
Participants
1
Timeline
3
Reactions
0
Participants
Timeline (top)
labeled ×3

When experimental_use_latest_role_message_only is enabled and an LLM requests N tool calls in a single agentic loop iteration, all N results are appended to the conversation history before the next request is sent. LiteLLM then forwards only messages[-1] to Bedrock Guardrails, meaning the first N-1 tool responses are never evaluated. This is a silent security gap, since tool outputs are a known indirect prompt injection vector.

Error Message

In a multi-turn agentic loop, when the assistant requests N tool calls at once, the agent executes all of them and appends all N results to the conversation before sending the next request. The message array at that point looks like:

[..., assistant(+N tool_calls), tool_result_1, tool_result_2, ..., tool_result_N]

With experimental_use_latest_role_message_only, LiteLLM sends only tool_result_N (messages[-1]) to Bedrock Guardrails.
tool_result_1 through tool_result_{N-1} are silently skipped — never evaluated.

Root Cause

Tool outputs are a well-known indirect prompt injection vector. An attacker who controls a tool's response can craft a payload. Silently skipping N-1 out of every N tool results when the model uses parallel tool calls means Bedrock Guardrails defense is only partially applied, with no warning or indication to the operator.

Code Example

[..., assistant(+N tool_calls), tool_result_1, tool_result_2, ..., tool_result_N]

---

messages = [
  # first iteration of the loop
  [0] system
  [1] user:      "..."
  # second (and current) iteration of the loop
  [2] assistant: [tool_call_A, tool_call_B, tool_call_C]
  [3] tool:      result_A   ← NOT sent to Bedrock Guardrails
  [4] tool:      result_B   ← NOT sent to Bedrock Guardrails
  [5] tool:      result_C   ← sent to Bedrock Guardrails  (messages[-1])
]

---

guardrails:
  - guardrail_name: <guardrail_name>
    litellm_params:
      guardrail: "bedrock"
      mode: "pre_call"
      guardrailIdentifier: <guardrailIdentifier>
      guardrailVersion: "6"
      aws_region_name: "us-west-2"
      default_on: true
      experimental_use_latest_role_message_only: true
RAW_BUFFERClick to expand / collapse

Check for existing issues

  • I have searched the existing issues and checked that my issue is not a duplicate.

Summary

When experimental_use_latest_role_message_only is enabled and an LLM requests N tool calls in a single agentic loop iteration, all N results are appended to the conversation history before the next request is sent. LiteLLM then forwards only messages[-1] to Bedrock Guardrails, meaning the first N-1 tool responses are never evaluated. This is a silent security gap, since tool outputs are a known indirect prompt injection vector.

Observed behavior

In a multi-turn agentic loop, when the assistant requests N tool calls at once, the agent executes all of them and appends all N results to the conversation before sending the next request. The message array at that point looks like:

[..., assistant(+N tool_calls), tool_result_1, tool_result_2, ..., tool_result_N]

With experimental_use_latest_role_message_only, LiteLLM sends only tool_result_N (messages[-1]) to Bedrock Guardrails.
tool_result_1 through tool_result_{N-1} are silently skipped — never evaluated.

Concrete example: 3 parallel tool calls

messages = [
  # first iteration of the loop
  [0] system
  [1] user:      "..."
  # second (and current) iteration of the loop
  [2] assistant: [tool_call_A, tool_call_B, tool_call_C]
  [3] tool:      result_A   ← NOT sent to Bedrock Guardrails
  [4] tool:      result_B   ← NOT sent to Bedrock Guardrails
  [5] tool:      result_C   ← sent to Bedrock Guardrails ✅ (messages[-1])
]

Full coverage table

Message typeEvaluated by Bedrock Guardrails?
systemNever
userOnly on the first request (when it is messages[-1])
assistant intermediate turnsNever (always followed by tool results)
Tool result #1 … #(N-1) when N tools called in parallelNever
Tool result #N (last in batch)Yes — it is messages[-1]

Steps to reproduce

  1. Set up a LiteLLM proxy with Bedrock Guardrails enabled and experimental_use_latest_role_message_only: true.

  2. Define at least one tool that the model is likely to call multiple times in parallel (e.g. a search or lookup tool).

  3. Enable Litellm DEBUG level logging so you can inspect what is forwarded to the Bedrock Guardrail applyGuardrail endpoint.

  4. Send a user message that causes the model to issue 2 or more tool calls in a single assistant turn (parallel tool use).

  5. Observe the Bedrock Guardrail API calls made during that agentic loop iteration corresponds only to the latest tool response in the array

Expected: Each tool result is sent to Bedrock Guardrails individually (or all are batched in a single call).
Actual: Only messages[-1] — the last tool result in the batch — is forwarded. All preceding tool results in the same turn are skipped.

Expected behavior

All tool results from the current agentic loop iteration should be evaluated by Bedrock Guardrails. Ideally each tool result is forwarded individually (one guardrail API call per result), so that:

  • Every tool response is inspected exactly once
  • Guardrail payload size stays bounded (no accumulated history, no batch of N results at once), which mitigates false positive risk from large payloads

Why this matters

Tool outputs are a well-known indirect prompt injection vector. An attacker who controls a tool's response can craft a payload. Silently skipping N-1 out of every N tool results when the model uses parallel tool calls means Bedrock Guardrails defense is only partially applied, with no warning or indication to the operator.

Environment

  • LiteLLM version: 1.81.12
  • Bedrock region: us-west-2
  • Model: us.anthropic.claude-sonnet-4-6

config.yaml:

guardrails:
  - guardrail_name: <guardrail_name>
    litellm_params:
      guardrail: "bedrock"
      mode: "pre_call"
      guardrailIdentifier: <guardrailIdentifier>
      guardrailVersion: "6"
      aws_region_name: "us-west-2"
      default_on: true
      experimental_use_latest_role_message_only: true

What part of LiteLLM is this about?

Proxy

What LiteLLM version are you on ?

1.81.12

extent analysis

TL;DR

Disable experimental_use_latest_role_message_only to ensure all tool results are evaluated by Bedrock Guardrails.

Guidance

  • Review the config.yaml file and set experimental_use_latest_role_message_only to false to enable evaluation of all tool results.
  • Verify that each tool result is sent to Bedrock Guardrails individually by checking the LiteLLM DEBUG level logs.
  • Consider batching tool results in a single call to Bedrock Guardrails to mitigate false positive risk from large payloads.
  • Test the setup with multiple parallel tool calls to ensure all tool results are evaluated correctly.

Example

No code snippet is provided as the issue is related to configuration and not code.

Notes

Disabling experimental_use_latest_role_message_only may have performance implications, and the optimal solution may depend on the specific use case and requirements.

Recommendation

Apply workaround: Disable experimental_use_latest_role_message_only to ensure all tool results are evaluated by Bedrock Guardrails, as this setting is causing the silent security gap.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

All tool results from the current agentic loop iteration should be evaluated by Bedrock Guardrails. Ideally each tool result is forwarded individually (one guardrail API call per result), so that:

  • Every tool response is inspected exactly once
  • Guardrail payload size stays bounded (no accumulated history, no batch of N results at once), which mitigates false positive risk from large payloads

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING