From de9140b8eea6e7d47b4f391593bfa07b254c9d01 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 15 Apr 2026 13:17:00 -0400 Subject: [PATCH] fix(guardrails): append assistant turn to structured_messages in post_call --- .../chat/guardrail_translation/handler.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/litellm/llms/openai/chat/guardrail_translation/handler.py b/litellm/llms/openai/chat/guardrail_translation/handler.py index 2db19dea0b9..5bfbeea80f4 100644 --- a/litellm/llms/openai/chat/guardrail_translation/handler.py +++ b/litellm/llms/openai/chat/guardrail_translation/handler.py @@ -348,6 +348,28 @@ class OpenAIChatCompletionsHandler(BaseTranslation): if hasattr(response, "model") and response.model: inputs["model"] = response.model + # Build structured_messages: original request messages + assistant + # response turn(s) appended, so post-call guardrails see full context. + original_messages = cast( + List[AllMessageValues], + request_data.get("messages", []) if request_data else [], + ) + structured_messages: List[AllMessageValues] = list(original_messages) + for choice in response.choices: + msg = choice.message + if msg.tool_calls or msg.content is not None: + assistant_turn: dict = {"role": "assistant"} + if msg.content is not None: + assistant_turn["content"] = msg.content + if msg.tool_calls: + assistant_turn["tool_calls"] = [ + tc.model_dump() if hasattr(tc, "model_dump") else tc + for tc in msg.tool_calls + ] + structured_messages.append(cast(AllMessageValues, assistant_turn)) + if structured_messages: + inputs["structured_messages"] = structured_messages + guardrailed_inputs = await guardrail_to_apply.apply_guardrail( inputs=inputs, request_data=request_data,