Add SystemInstructionPart model and support in invocations - #612
Conversation
Pull request dashboard statusMerged · refreshed 2026-09-04 22:20 UTC Status above doesn't look right?
|
| @@ -1 +0,0 @@ | |||
| Divert `SystemMessage` inputs to `gen_ai.system_instructions` instead of emitting them as `role="system"` inside `gen_ai.input.messages`. | |||
There was a problem hiding this comment.
this change turns out to be wrong, instructions are only populated when they are provided separately from chat history
fixing it
There was a problem hiding this comment.
@lmolkova Sorry for the back and forth! I'll keep in mind to read the semconv more carefully before raising a PR next time
There was a problem hiding this comment.
no problem @sfc-gh-zeningchen! thanks a lot for the contributions!!
There was a problem hiding this comment.
🟡 Changes recommended
Generic-part handling, hook compatibility, and the unrelated LangChain regression must be resolved.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adds SystemInstructionPart typing across GenAI utilities and instrumentations.
Changes:
- Adds the system-instruction union and updates invocation/hook annotations.
- Updates provider extraction and examples.
- Alters LangChain system-message telemetry behavior.
File summaries
| File | Description |
|---|---|
util/opentelemetry-util-genai/tests/test_utils.py |
Tests the new alias. |
util/opentelemetry-util-genai/src/opentelemetry/util/genai/types.py |
Defines SystemInstructionPart. |
util/opentelemetry-util-genai/src/opentelemetry/util/genai/completion_hook.py |
Updates hook typing. |
util/opentelemetry-util-genai/src/opentelemetry/util/genai/_upload/completion_hook.py |
Updates upload-hook typing. |
util/opentelemetry-util-genai/src/opentelemetry/util/genai/_invocation.py |
Updates shared content typing. |
util/opentelemetry-util-genai/src/opentelemetry/util/genai/_inference_invocation.py |
Updates inference fields. |
util/opentelemetry-util-genai/src/opentelemetry/util/genai/_agent_invocation.py |
Updates agent fields. |
util/opentelemetry-util-genai/.changelog/612.added |
Adds release note. |
instrumentation/opentelemetry-instrumentation-google-genai/.../message.py |
Narrows system-part conversion. |
instrumentation/opentelemetry-instrumentation-genai-qwen-agent/examples/manual/custom_hook.py |
Updates example signature. |
instrumentation/opentelemetry-instrumentation-genai-portkey/examples/manual/custom_hook.py |
Updates example signature. |
instrumentation/opentelemetry-instrumentation-genai-openai/examples/manual/custom_hook.py |
Updates example signature. |
instrumentation/opentelemetry-instrumentation-genai-llama-index/.../_handler.py |
Updates system-prompt typing. |
instrumentation/opentelemetry-instrumentation-genai-llama-index/examples/manual/custom_hook.py |
Updates example signature. |
instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_llm_call.py |
Changes system-message expectations. |
instrumentation/opentelemetry-instrumentation-genai-langchain/tests/conformance/inference.py |
Removes system-instruction validation. |
instrumentation/opentelemetry-instrumentation-genai-langchain/tests/conformance/inference_streaming.py |
Removes system-instruction validation. |
instrumentation/opentelemetry-instrumentation-genai-langchain/tests/conformance/_shared.py |
Removes shared assertion helper. |
instrumentation/opentelemetry-instrumentation-genai-langchain/.../utils.py |
Removes system-message splitting. |
instrumentation/opentelemetry-instrumentation-genai-langchain/.../callback_handler.py |
Emits system messages as inputs. |
instrumentation/opentelemetry-instrumentation-genai-langchain/.changelog/511.fixed |
Removes prior fix note. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/tests/test_converse.py |
Tests text system instructions. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/.../extractors.py |
Adds system-part extraction. |
instrumentation/opentelemetry-instrumentation-genai-bedrock/examples/manual/custom_hook.py |
Updates example signature. |
instrumentation/opentelemetry-instrumentation-genai-anthropic/.../messages_extractors.py |
Narrows system extraction. |
Review details
- Files reviewed: 25/25 changed files
- Comments generated: 5
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
🟡 Changes recommended
It breaks the public GenericPart API and drops supported non-text Google system instructions.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (2)
util/opentelemetry-util-genai/src/opentelemetry/util/genai/types.py:40
GenericPartis public, so removingvalueimmediately breaks existingGenericPart(type=..., value=...)callers withTypeError. It is also not required by the pinned semconv schema:GenericParthasadditionalProperties: true, so provider-specific payload properties are explicitly permitted. Preserve and deprecate the legacy field while adding a representation that can serialize arbitrary top-level properties before removing it under the util compatibility policy.
"""Represents an arbitrary message part with any type and properties.
This allows for extensibility with custom message part types.
util/opentelemetry-util-genai/src/opentelemetry/util/genai/types.py:308
- The new public alias mirrors the system-instructions semconv model but does not cite that model, as required for util structured types. Add the pinned schema reference so future updates can verify its members against
SEMCONV_GENAI_REFrather thanmain.
SystemInstructionPart = Union[TextPart, GenericPart]
- Files reviewed: 22/22 changed files
- Comments generated: 2
- Review effort level: Balanced
bc2beb7 to
191c651
Compare
…system messages in input_messages
- Align GenericPart with semconv by removing the value field - Extract non-text Bedrock system content blocks as GenericPart - Check system is None in Anthropic message extractors - Retain list[MessagePart] in CompletionHook signature - Add tests for GenericPart serialization and system instruction span attributes
…ResponseInvocation
191c651 to
420b577
Compare
Added on main while this branch was in flight, so the rebase left the scenario in the old format and declared nowhere. Convert it to a standalone script and declare it in conformance.yaml; its cassette goes with the others. The langchain coverage file loses gen_ai.system_instructions: open-telemetry#612 removed the attribute from the callback handler, and nothing emits it now. Assisted-by: Claude Opus 5
Added on main while this branch was in flight, so the rebase left the scenario in the old format and declared nowhere. Convert it to a standalone script and declare it in conformance.yaml; its cassette goes with the others. The langchain coverage file drops gen_ai.system_instructions. That is intentional: open-telemetry#612 moved system messages into gen_ai.input.messages as a system-role message, so the scenario TODOs now point there. Assisted-by: Claude Opus 5
What does this change do?
Defines
SystemInstructionPart = Union[TextPart, GenericPart]inopentelemetry.util.genai.types, alignsGenericPartwith semantic conventions by removingvalue, updates invocation types, and reverts #511.Why?
GenericPartmodel with GenAI semantic conventions (gen-ai-system-instructions.json), which specify onlytypefor generic parts.opentelemetry-instrumentation-genai-langchain] DivertSystemMessagetogen_ai.system_instructions#511: per semantic conventions, system instructions are only populated when provided separately from chat history (rather than as an input message with a system role). In LangChain, system messages are part of chat history and belong ingen_ai.input.messages.