fix(server-utils): Record LangGraph span I/O for non-MessagesAnnotation state - #23315
Open
zkasuran wants to merge 2 commits into
Open
fix(server-utils): Record LangGraph span I/O for non-MessagesAnnotation state#23315zkasuran wants to merge 2 commits into
zkasuran wants to merge 2 commits into
Conversation
…on state instrumentCompiledGraphInvoke read the graph input and output through `args[0].messages` and `result.messages`. Those keys only exist for graphs built on MessagesAnnotation, so a graph with a custom state annotation had its `invoke_agent` span input and output silently left empty with no error. Keep the existing message path unchanged. When there is no `messages` array, fall back to serializing the whole input and output state onto `gen_ai.input.messages` and `gen_ai.response.text`, wrapped as a single role/content message so the attribute stays a valid chat array (the same shape LangChain LLM prompts already use). A null input still records nothing. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
zkasuran
requested review from
logaretm and
stephanie-anderson
and removed request for
a team
August 12, 2026 06:50
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit e194f28. Configure here.
nicohrubec
requested review from
nicohrubec
and removed request for
stephanie-anderson
August 12, 2026 08:06
An explicit empty `messages` array was gated by `length > 0`, so it fell through to the custom-state branch and got wrapped as a synthetic user message holding the whole input object. The output helper already routes on `Array.isArray`, so an empty array stays on the chat path there. Match that on the input read: key on `Array.isArray(state.messages)`, so an empty MessagesAnnotation input records an empty chat array while a null or resume input still records nothing. Co-Authored-By: Claude Opus 4.8 (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.

instrumentLangGraphrecorded span input and output only when the graph state usesMessagesAnnotation. The input read didargs[0].messages ?? []and the output helper returned early whenresult.messageswas not an array, so a graph on a custom state annotation produced an emptygen_ai.input.messagesand nogen_ai.response.text. No error, just an emptyinvoke_agentspan in the AI Agents view.This keeps the
MessagesAnnotationpath unchanged. When there is nomessagesarray, it serializes the whole input and output state and records it, wrapped as a single{ role, content }message so the attribute stays a valid chat array (the conventionextractLLMRequestAttributesalready uses in this package). A null input (the resume case) records nothing rather than a misleading empty array. Serialization uses core's circular-safestringifyso an unusual state object cannot throw inside the span callback.Fixes #19628
AI assistance (Claude, Anthropic) was used in developing this change. The design, review and verification were done by the author. Verified locally: the
@sentry/server-utilsvitest suite (335 to 339 passing), the new tests failing before and passing after the fix,oxlint --type-aware,oxfmt --check,tscon the changed files, plus a real Google Gemini LangGraph run showing the span input and output empty before and populated after.