Skip to content

Commit dd2fd58

Browse files
committed
GenAI: redact output message text when include_sensitive_data is False in normalized output schema
1 parent 91ee492 commit dd2fd58

File tree

1 file changed

+74
-8
lines changed
  • instrumentation-genai/opentelemetry-instrumentation-openai-agents/src/opentelemetry/instrumentation/openai_agents

1 file changed

+74
-8
lines changed

instrumentation-genai/opentelemetry-instrumentation-openai-agents/src/opentelemetry/instrumentation/openai_agents/genai_semantic_processor.py

Lines changed: 74 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -594,19 +594,44 @@ def _normalize_output_messages_to_role_parts(
594594
# Collect text content
595595
output_text = getattr(response, "output_text", None)
596596
if isinstance(output_text, str) and output_text:
597-
parts.append({"type": "text", "content": output_text})
597+
parts.append(
598+
{
599+
"type": "text",
600+
"content": (
601+
"readacted"
602+
if not self.include_sensitive_data
603+
else output_text
604+
),
605+
}
606+
)
598607
else:
599608
output = getattr(response, "output", None)
600609
if isinstance(output, Sequence):
601610
for item in output:
602611
# ResponseOutputMessage may have a string representation
603612
txt = getattr(item, "content", None)
604613
if isinstance(txt, str) and txt:
605-
parts.append({"type": "text", "content": txt})
614+
parts.append(
615+
{
616+
"type": "text",
617+
"content": (
618+
"readacted"
619+
if not self.include_sensitive_data
620+
else txt
621+
),
622+
}
623+
)
606624
else:
607625
# Fallback: stringified
608626
parts.append(
609-
{"type": "text", "content": str(item)}
627+
{
628+
"type": "text",
629+
"content": (
630+
"readacted"
631+
if not self.include_sensitive_data
632+
else str(item)
633+
),
634+
}
610635
)
611636
# Capture finish_reason from parts when present
612637
fr = getattr(item, "finish_reason", None)
@@ -622,25 +647,66 @@ def _normalize_output_messages_to_role_parts(
622647
if item.get("type") == "text":
623648
txt = item.get("content") or item.get("text")
624649
if isinstance(txt, str) and txt:
625-
parts.append({"type": "text", "content": txt})
650+
parts.append(
651+
{
652+
"type": "text",
653+
"content": (
654+
"readacted"
655+
if not self.include_sensitive_data
656+
else txt
657+
),
658+
}
659+
)
626660
elif "content" in item and isinstance(
627661
item["content"], str
628662
):
629663
parts.append(
630-
{"type": "text", "content": item["content"]}
664+
{
665+
"type": "text",
666+
"content": (
667+
"readacted"
668+
if not self.include_sensitive_data
669+
else item["content"]
670+
),
671+
}
631672
)
632673
else:
633674
parts.append(
634-
{"type": "text", "content": str(item)}
675+
{
676+
"type": "text",
677+
"content": (
678+
"readacted"
679+
if not self.include_sensitive_data
680+
else str(item)
681+
),
682+
}
635683
)
636684
if not finish_reason and isinstance(
637685
item.get("finish_reason"), str
638686
):
639687
finish_reason = item.get("finish_reason")
640688
elif isinstance(item, str):
641-
parts.append({"type": "text", "content": item})
689+
parts.append(
690+
{
691+
"type": "text",
692+
"content": (
693+
"readacted"
694+
if not self.include_sensitive_data
695+
else item
696+
),
697+
}
698+
)
642699
else:
643-
parts.append({"type": "text", "content": str(item)})
700+
parts.append(
701+
{
702+
"type": "text",
703+
"content": (
704+
"readacted"
705+
if not self.include_sensitive_data
706+
else str(item)
707+
),
708+
}
709+
)
644710

645711
# Build assistant message
646712
msg: dict[str, Any] = {"role": "assistant", "parts": parts}

0 commit comments

Comments
 (0)