#30729 [Bug]: OpenAI & Azure moderation guardrails only scan the trailing user turn ā system/assistant content is never moderated
## Summary
Both API-backed moderation guardrails extract the text to scan via `get_user_prompt()` -> `get_last_user_message()` (`litellm_core_utils/prompt_templates/common_utils.py:1347`), which returns **only the last consecutive block of `role=="user"` messages** (it scans from the end and breaks at the first non-user message). So content in a **system** message, an **assistant** prefill, or any user message before a non-user turn is never submitted to the moderation API.
- **OpenAI moderation** (`guardrail_hooks/openai/moderations.py:224-225`) ā `apply_guardrail` prefers `inputs["structured_messages"]` and calls `get_user_prompt(...)`. Notably, the chat translation handler (`openai/chat/guardrail_translation/handler.py:102,117`) passes BOTH a full `texts` list (all message contents) AND `structured_messages`, but `apply_guardrail` **discards `texts`** whenever `structured_messages` is truthy ā so the full-conversation text it already computed is thrown away. - **Azure Content Safety** (`guardrail_hooks/azure/text_moderation.py:236`) ā `async_pre_call_hook` calls the same `get_user_prompt`, and additionally reads only `data.get("messages")` (so it inherits the `/v1/responses` iā¦