-
Notifications
You must be signed in to change notification settings - Fork 808
fix(openai-agents): support json inputs #3354
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughSerializes non-string prompt message content to JSON strings in on_span_end for both object messages (with .content) and dict messages, across LLM_PROMPTS, gen_ai.prompt.*, and legacy fallback paths. Adds a unit test and a VCR cassette to validate dict content serialization. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Runner
participant Hook as on_span_end Hook
participant Span
Runner->>Hook: on_span_end(span, input_data)
Note over Hook: iterate over input_data.messages
alt message is object with .content
Hook->>Hook: content = message.content\nif not str -> json.dumps(content)
else message is dict
Hook->>Hook: content = message['content']\nif dict -> json.dumps(content)
else
Hook->>Hook: use content as-is
end
Hook->>Span: setAttribute(LLM_PROMPTS / gen_ai.prompt.{i}.content, serialized_content)
Span-->>Runner: span finished with stringified prompt attributes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 💡 Knowledge Base configuration:
You can enable these sources in your CodeRabbit configuration. 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
✨ Finishing Touches
🧪 Generate unit tests
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
23db276
to
4ef8bd7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caution
Changes requested ❌
Reviewed 4ef8bd7 in 1 minute and 40 seconds. Click for details.
- Reviewed
243
lines of code in3
files - Skipped
0
files when reviewing. - Skipped posting
0
draft comments. View those below. - Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
Workflow ID: wflow_7xAGeunaRdcztHp2
You can customize by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.
...elemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/_hooks.py
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/_hooks.py (1)
320-331
: Normalize tool call arguments to string as well.
output.arguments
may be dict/array; set_attribute requires primitives/str. Serialize consistently to avoid type rejection.- arguments = getattr(output, 'arguments', '{}') + arguments = _to_attr_str(getattr(output, 'arguments', {}))
♻️ Duplicate comments (1)
packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/_hooks.py (1)
239-242
: Serialize all non-string content (lists, tuples, etc.), not just dicts; dedupe with a helper.Inputs frequently contain lists (e.g., multimodal content arrays). Serializing only dicts leaves lists (or other types) as invalid attribute values. Replace with a generic converter and reuse it in both new and legacy paths to avoid drift.
Apply this diff in each location:
- content = message.content - if isinstance(content, dict): - content = json.dumps(content) + content = _to_attr_str(message.content)- content = message['content'] - if isinstance(content, dict): - content = json.dumps(content) + content = _to_attr_str(message['content'])And in the legacy block:
- content = message.content - if isinstance(content, dict): - content = json.dumps(content) + content = _to_attr_str(message.content)- content = message['content'] - if isinstance(content, dict): - content = json.dumps(content) + content = _to_attr_str(message['content'])Add this helper (top-level or as a @staticmethod on the class):
def _to_attr_str(value: Any) -> str: if isinstance(value, str): return value try: # Stable, compact JSON for any non-string (lists, dicts, numbers, booleans, None) return json.dumps(value, ensure_ascii=False, separators=(",", ":"), allow_nan=False) except (TypeError, ValueError): # Last resort: stringify without raising return str(value)Also applies to: 246-249, 374-377, 381-384
🧹 Nitpick comments (3)
packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/_hooks.py (1)
251-279
: Optional: cap very large attribute payloads.Long prompts/JSON can exceed exporter limits and be dropped. Consider truncating serialized strings to a configurable max length (e.g., 16–64KB) with an “…truncated” marker.
packages/opentelemetry-instrumentation-openai-agents/tests/test_openai_agents.py (2)
82-88
: Use contextlib.suppress and handle JSON arrays too.Covers
[]
-prefixed JSON and removes try/except noise.- # If it looks like JSON, verify it can be parsed - if attr_value.startswith('{') and attr_value.endswith('}'): - try: - json.loads(attr_value) - except json.JSONDecodeError: - # If it fails to parse, that's still fine - just not JSON - pass + # If it looks like JSON, verify it can be parsed + from contextlib import suppress + s = attr_value.strip() + if s and s[0] in "{[" and s[-1] in "}]": + with suppress(json.JSONDecodeError): + json.loads(s)
67-75
: Optional: tighten attribute filter.
"prompt" in attr_name
may match unrelated keys; prefer explicit prefixes for stability.- prompt_content_check = ( - ("prompt" in attr_name and "content" in attr_name) or - ("gen_ai.prompt" in attr_name and "content" in attr_name) - ) + prompt_content_check = ( + (attr_name.startswith(f"{SpanAttributes.LLM_PROMPTS}.") and ".content" in attr_name) + or (attr_name.startswith("gen_ai.prompt.") and ".content" in attr_name) + )
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (3)
packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/_hooks.py
(2 hunks)packages/opentelemetry-instrumentation-openai-agents/tests/cassettes/test_openai_agents/test_dict_content_serialization.yaml
(1 hunks)packages/opentelemetry-instrumentation-openai-agents/tests/test_openai_agents.py
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/cassettes/**/*.{yaml,yml,json}
📄 CodeRabbit inference engine (CLAUDE.md)
Never commit secrets or PII in VCR cassettes; scrub sensitive data
Files:
packages/opentelemetry-instrumentation-openai-agents/tests/cassettes/test_openai_agents/test_dict_content_serialization.yaml
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.py
: Store API keys only in environment variables/secure vaults; never hardcode secrets in code
Use Flake8 for code linting and adhere to its rules
Files:
packages/opentelemetry-instrumentation-openai-agents/tests/test_openai_agents.py
packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/_hooks.py
🧬 Code graph analysis (2)
packages/opentelemetry-instrumentation-openai-agents/tests/test_openai_agents.py (2)
packages/opentelemetry-instrumentation-openai-agents/tests/conftest.py (1)
exporter
(27-37)packages/traceloop-sdk/traceloop/sdk/utils/in_memory_span_exporter.py (1)
get_finished_spans
(40-43)
packages/opentelemetry-instrumentation-openai-agents/opentelemetry/instrumentation/openai_agents/_hooks.py (1)
packages/opentelemetry-semantic-conventions-ai/opentelemetry/semconv_ai/__init__.py (1)
SpanAttributes
(64-261)
🪛 Ruff (0.12.2)
packages/opentelemetry-instrumentation-openai-agents/tests/test_openai_agents.py
84-88: Use contextlib.suppress(json.JSONDecodeError)
instead of try
-except
-pass
(SIM105)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Test Packages (3.12)
- GitHub Check: Lint
- GitHub Check: Build Packages (3.11)
...tation-openai-agents/tests/cassettes/test_openai_agents/test_dict_content_serialization.yaml
Show resolved
Hide resolved
…etry/instrumentation/openai_agents/_hooks.py Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
feat(instrumentation): ...
orfix(instrumentation): ...
.Important
Adds JSON serialization for dictionary content in OpenAI agent spans and tests this functionality.
_hooks.py
,on_span_end()
now serializes dictionary content inmessage.content
to JSON strings before setting attributes.ResponseSpanData
andGenerationSpanData
types.test_dict_content_serialization()
intest_openai_agents.py
to verify dictionary content is serialized to JSON strings.test_dict_content_serialization.yaml
for testing serialized content.This description was created by
for 4ef8bd7. You can customize this summary. It will automatically update as commits are pushed.
Summary by CodeRabbit
Bug Fixes
Tests