[nodejs]Update message format to align with OTel spec#256
Merged
Conversation
Remove the versioned wrapper `{ version, messages }` envelope from message
serialization. Messages now serialize as a plain JSON array per OTel gen-ai
semantic conventions. Output messages default finish_reason to "stop" when
created from plain strings via toOutputMessages/normalizeOutputMessages.
Port of microsoft/Agent365-dotnet#253.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the observability message serialization format to match OpenTelemetry gen-ai semantic conventions by removing the versioned { version, messages } envelope and emitting a plain JSON array of messages, while also defaulting finish_reason to "stop" for output messages created from plain strings and tightening wrapper detection.
Changes:
- Serialize
gen_ai.{input,output}.messagesas a plain JSON array instead of a versioned wrapper object. - Default
finish_reasonto"stop"for output messages produced from string / string[] inputs. - Update wrapper type guards, contracts, exporter truncation logic, and tests to reflect the new format.
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/observability/tracing/message-utils.test.ts | Updates unit tests for wrapper detection, normalization, and array-based serialization; adds finish_reason expectations. |
| tests/observability/integration/openai-agent-instrument.test.ts | Adjusts integration assertions to expect JSON arrays for input/output message attributes. |
| tests/observability/integration/langchain-agent-instrument.test.ts | Adjusts integration assertions to expect JSON arrays for input/output message attributes. |
| tests/observability/integration/helpers/span-validators.ts | Updates span validators to treat message attributes as arrays (not {version,messages}). |
| tests/observability/extension/openai/OpenAIMessageContract.test.ts | Updates OpenAI extension contract tests to index into the serialized array. |
| tests/observability/extension/openai/OpenAIAgentsTraceProcessor.test.ts | Updates processor tests to validate array serialization and indexing. |
| tests/observability/extension/langchain/LangChainObservabilityAttributes.test.ts | Updates LangChain extension attribute assertions to expect array JSON. |
| tests/observability/extension/langchain/LangChainMessageContract.test.ts | Updates LangChain message contract tests for array JSON format. |
| tests/observability/extension/hosting/scope-utils.test.ts | Updates hosting scope tests to expect array serialization for input messages. |
| tests/observability/extension/hosting/output-logging-middleware.test.ts | Updates middleware tests to expect array output messages plus default finish_reason. |
| tests/observability/extension/helpers/message-schema-validator.ts | Updates shared validator to validate “plain array of messages” payloads. |
| tests/observability/core/scopes.test.ts | Updates core scope tests to validate array-based attributes and finish_reason defaults. |
| tests/observability/core/scope-messages.test.ts | Updates scope message recording tests for array format and finish_reason defaults. |
| tests/observability/core/output-scope.test.ts | Updates OutputScope tests to validate array output messages and finish_reason defaults. |
| tests/observability/core/agent365-exporter.test.ts | Updates exporter truncation tests to validate array-based message attributes. |
| packages/agents-a365-observability/src/tracing/scopes/OutputScope.ts | Removes versioned wrapping and refines raw-dict detection for output message recording. |
| packages/agents-a365-observability/src/tracing/message-utils.ts | Implements array serialization, default finish_reason, and tighter wrapper guard. |
| packages/agents-a365-observability/src/tracing/exporter/utils.ts | Updates truncation logic to parse/flush message attributes as arrays and adjust overflow sentinel generation. |
| packages/agents-a365-observability/src/tracing/contracts.ts | Removes version from message wrapper contracts and introduces DEFAULT_FINISH_REASON. |
| packages/agents-a365-observability/src/index.ts | Updates public exports to expose DEFAULT_FINISH_REASON instead of the schema version constant. |
| packages/agents-a365-observability-extensions-openai/src/Utils.ts | Updates OpenAI extension helpers to build wrappers without version and default finish_reason for assistant. |
| packages/agents-a365-observability-extensions-langchain/src/Utils.ts | Updates LangChain extension to wrap messages without version before serializing. |
- Remove unused DEFAULT_FINISH_REASON import from test file - Remove finish_reason from serialization fallback and overflow sentinel (finish_reason is output-only per OTel spec, sentinels are used for both input and output attributes) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The "validate error.type on failing tool" test was flaky because it used waitForSpans with a generic count of 2, which could resolve before the tool span was emitted. Now polls specifically for the execute_tool span by name with a 15s timeout. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
nikhilNava
approved these changes
May 26, 2026
juliomenendez
approved these changes
May 26, 2026
4 tasks
fpfp100
added a commit
to microsoft/opentelemetry-distro-javascript
that referenced
this pull request
May 27, 2026
* Update message format to align with OTel spec
Remove the versioned `{ version, messages }` envelope from message
serialization. Messages now serialize as a plain JSON array per OTel gen-ai
semantic conventions. Output messages default finish_reason to "stop" when
created from plain strings via toOutputMessages/normalizeOutputMessages.
Tighten isWrappedMessages type guard with Array.isArray check.
Port of microsoft/Agent365-nodejs#256.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix lint: remove unused InputMessages import from scopes test
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Peng Fan <pefan@microsoft.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
{ version: "0.1.0", messages: [...] }envelope from message serialization — messages now serialize as a plain JSON array[...]per OTel gen-ai semantic conventionsfinish_reasonto"stop"on output messages created from plain strings viatoOutputMessages/normalizeOutputMessagesisWrappedMessagestype guard withArray.isArraycheck to prevent false positivesPort of microsoft/Agent365-dotnet#253.
Test plan
🤖 Generated with Claude Code