Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
4f25a56
feat(openai): Set system instruction attribute
alexander-alderman-webb Jan 21, 2026
921a82f
Merge branch 'webb/openai-separate-input-handling' into webb/openai-a…
alexander-alderman-webb Jan 21, 2026
9f5d801
.
alexander-alderman-webb Jan 21, 2026
d66ffe1
use specific openai types
alexander-alderman-webb Jan 21, 2026
ac3ce00
wip
alexander-alderman-webb Jan 22, 2026
ef9fe6f
.
alexander-alderman-webb Jan 22, 2026
ce84a29
.
alexander-alderman-webb Jan 22, 2026
dee9930
remove test
alexander-alderman-webb Jan 22, 2026
cb00ab3
.
alexander-alderman-webb Jan 22, 2026
26b932b
.
alexander-alderman-webb Jan 22, 2026
04dc92c
.
alexander-alderman-webb Jan 22, 2026
c7263ea
edge case
alexander-alderman-webb Jan 22, 2026
d947899
full responses api tests
alexander-alderman-webb Jan 22, 2026
8cbeac1
remove sentry_sdk/ai/_openai_completions_api.py
alexander-alderman-webb Jan 22, 2026
bcebcc8
fix test
alexander-alderman-webb Jan 22, 2026
87dd8fe
Merge branch 'webb/openai-separate-input-handling' into webb/openai-a…
alexander-alderman-webb Jan 23, 2026
3f5ad11
more defensive checks in case input is not iterable
alexander-alderman-webb Jan 23, 2026
a8840d5
more early returns
alexander-alderman-webb Jan 26, 2026
382e933
revert unrelated tests
alexander-alderman-webb Jan 26, 2026
179d59e
revert unrelated change
alexander-alderman-webb Jan 26, 2026
12cb219
address comment
alexander-alderman-webb Jan 26, 2026
a6152fe
remove unused type ignore
alexander-alderman-webb Jan 26, 2026
5085fd8
split off responses API changes
alexander-alderman-webb Jan 26, 2026
187965b
feat(openai): Set system instruction attribute for Responses API
alexander-alderman-webb Jan 26, 2026
7fc64f0
remove unused functions
alexander-alderman-webb Jan 26, 2026
5d3ca4f
Merge branch 'webb/openai-ai-prompt-message' into webb/openai-respons…
alexander-alderman-webb Jan 26, 2026
dbfc709
merge
alexander-alderman-webb Jan 26, 2026
5ced480
merge
alexander-alderman-webb Jan 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 89 additions & 8 deletions sentry_sdk/integrations/openai.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,24 @@ def _get_system_instructions_completions(
]


def _is_system_instruction_responses(message: "ResponseInputItemParam") -> bool:
if not isinstance(message, dict) or not message.get("role") == "system":
return False

return "type" not in message or message["type"] == "message"


def _get_system_instructions_responses(
messages: "Union[str, ResponseInputParam]",
) -> "list[ResponseInputItemParam]":
if not isinstance(messages, list):
return []

return [
message for message in messages if _is_system_instruction_responses(message)
]


def _transform_system_instructions(
system_instructions: "list[ChatCompletionSystemMessageParam]",
) -> "list[TextPart]":
Expand Down Expand Up @@ -289,17 +307,80 @@ def _set_responses_api_input_data(
kwargs: "dict[str, Any]",
integration: "OpenAIIntegration",
) -> None:
messages: "Optional[Union[ResponseInputParam, list[str]]]" = _get_input_messages(
kwargs
)
explicit_instructions: "Union[Optional[str], Omit]" = kwargs.get("instructions")
messages: "Optional[Union[str, ResponseInputParam]]" = kwargs.get("input")

if not should_send_default_pii() or not integration.include_prompts:
set_data_normalized(span, SPANDATA.GEN_AI_OPERATION_NAME, "responses")
_commmon_set_input_data(span, kwargs)
return

if (
messages is not None
and len(messages) > 0
and should_send_default_pii()
and integration.include_prompts
messages is None
and explicit_instructions is not None
and _is_given(explicit_instructions)
):
normalized_messages = normalize_message_roles(messages) # type: ignore
set_data_normalized(
span,
SPANDATA.GEN_AI_SYSTEM_INSTRUCTIONS,
[
{
"type": "text",
"content": explicit_instructions,
}
],
unpack=False,
)

set_data_normalized(span, SPANDATA.GEN_AI_OPERATION_NAME, "responses")
_commmon_set_input_data(span, kwargs)
return

if messages is None:
set_data_normalized(span, SPANDATA.GEN_AI_OPERATION_NAME, "responses")
_commmon_set_input_data(span, kwargs)
return

instructions_text_parts: "list[TextPart]" = []
if explicit_instructions is not None and _is_given(explicit_instructions):
instructions_text_parts.append(
{
"type": "text",
"content": explicit_instructions,
}
)

system_instructions = _get_system_instructions_responses(messages)
# Deliberate use of function accepting completions API type because
# of shared structure FOR THIS PURPOSE ONLY.
instructions_text_parts += _transform_system_instructions(system_instructions)

if len(instructions_text_parts) > 0:
set_data_normalized(
span,
SPANDATA.GEN_AI_SYSTEM_INSTRUCTIONS,
instructions_text_parts,
unpack=False,
)

if isinstance(messages, str):
normalized_messages = normalize_message_roles([messages]) # type: ignore
scope = sentry_sdk.get_current_scope()
messages_data = truncate_and_annotate_messages(normalized_messages, span, scope)
if messages_data is not None:
set_data_normalized(
span, SPANDATA.GEN_AI_REQUEST_MESSAGES, messages_data, unpack=False
)

set_data_normalized(span, SPANDATA.GEN_AI_OPERATION_NAME, "responses")
_commmon_set_input_data(span, kwargs)
return

non_system_messages = [
message for message in messages if not _is_system_instruction_responses(message)
]
if len(non_system_messages) > 0:
normalized_messages = normalize_message_roles(non_system_messages)
scope = sentry_sdk.get_current_scope()
messages_data = truncate_and_annotate_messages(normalized_messages, span, scope)
if messages_data is not None:
Expand Down
Loading
Loading