Skip to content

fix(server-utils): Record LangGraph span I/O for non-MessagesAnnotation state - #23315

Open
zkasuran wants to merge 2 commits into
getsentry:developfrom
zkasuran:fix/langgraph-span-io-non-messages-state
Open

fix(server-utils): Record LangGraph span I/O for non-MessagesAnnotation state#23315
zkasuran wants to merge 2 commits into
getsentry:developfrom
zkasuran:fix/langgraph-span-io-non-messages-state

Conversation

@zkasuran

@zkasuran zkasuran commented Aug 12, 2026

Copy link
Copy Markdown

instrumentLangGraph recorded span input and output only when the graph state uses MessagesAnnotation. The input read did args[0].messages ?? [] and the output helper returned early when result.messages was not an array, so a graph on a custom state annotation produced an empty gen_ai.input.messages and no gen_ai.response.text. No error, just an empty invoke_agent span in the AI Agents view.

This keeps the MessagesAnnotation path unchanged. When there is no messages array, 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 convention extractLLMRequestAttributes already uses in this package). A null input (the resume case) records nothing rather than a misleading empty array. Serialization uses core's circular-safe stringify so 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-utils vitest suite (335 to 339 passing), the new tests failing before and passing after the fix, oxlint --type-aware, oxfmt --check, tsc on the changed files, plus a real Google Gemini LangGraph run showing the span input and output empty before and populated after.

…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
zkasuran requested a review from a team as a code owner August 12, 2026 06:50
@zkasuran
zkasuran requested review from logaretm and stephanie-anderson and removed request for a team August 12, 2026 06:50

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ 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.

Comment thread packages/server-utils/src/ai/langgraph/index.ts
@nicohrubec
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

instrumentLangGraph input/output recording only works with MessagesAnnotation

1 participant