fix(logging): log anthropic system prompts sent as content blocks

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Devin AI 2026-08-10 14:13:53 +00:00
parent f6b9518ddb
commit 8bdd61bdea
2 changed files with 53 additions and 18 deletions

View file

@ -4542,25 +4542,27 @@ class StandardLoggingPayloadSetup:
def append_system_prompt_messages(kwargs: dict | None = None, messages: Any | None = None):
"""
Append system prompt messages to the messages
"""
if kwargs is not None:
if kwargs.get("system") is not None and isinstance(kwargs.get("system"), str):
if messages is None:
return [{"role": "system", "content": kwargs.get("system")}]
elif isinstance(messages, list):
if len(messages) == 0:
return [{"role": "system", "content": kwargs.get("system")}]
# check for duplicates
if messages[0].get("role") == "system" and messages[0].get("content") == kwargs.get("system"):
return messages
messages = [{"role": "system", "content": kwargs.get("system")}] + messages
elif isinstance(messages, str):
messages = [
{"role": "system", "content": kwargs.get("system")},
{"role": "user", "content": messages},
]
return messages
Anthropic's /v1/messages accepts ``system`` as a string or as a list of
content blocks; both shapes are logged.
"""
if kwargs is None:
return messages
system: Final = kwargs.get("system")
if not system or not isinstance(system, (str, list)):
return messages
system_message: Final = {"role": "system", "content": system}
if messages is None:
return [system_message]
if isinstance(messages, list):
if len(messages) == 0:
return [system_message]
first: Final = messages[0]
if isinstance(first, dict) and first.get("role") == "system" and first.get("content") == system:
return messages
return [system_message, *messages]
if isinstance(messages, str):
return [system_message, {"role": "user", "content": messages}]
return messages
@staticmethod

View file

@ -2240,6 +2240,39 @@ def test_append_system_prompt_messages():
assert result == messages
def test_append_system_prompt_messages_content_blocks():
"""
Anthropic /v1/messages accepts `system` as a list of content blocks; that shape must be logged
too, not silently dropped.
"""
from litellm.litellm_core_utils.litellm_logging import StandardLoggingPayloadSetup
system_blocks = [
{
"type": "text",
"text": "You are a helpful assistant",
"cache_control": {"type": "ephemeral"},
}
]
messages = [{"role": "user", "content": "Hello"}]
result = StandardLoggingPayloadSetup.append_system_prompt_messages(
kwargs={"system": system_blocks}, messages=messages
)
assert result == [{"role": "system", "content": system_blocks}, *messages]
# already-prepended system blocks are not duplicated
result = StandardLoggingPayloadSetup.append_system_prompt_messages(
kwargs={"system": system_blocks}, messages=result
)
assert len(result) == 2
# empty system is not logged as an empty system turn
assert (
StandardLoggingPayloadSetup.append_system_prompt_messages(kwargs={"system": []}, messages=messages) == messages
)
@pytest.mark.asyncio
async def test_async_success_handler_sets_standard_logging_object_for_pass_through_endpoints():
"""