Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

fix(react-langgraph): preserve streamed bedrock tool args#5080

Open
Kinfe123 wants to merge 4 commits into
mainassistant-ui/assistant-ui:mainfrom
fix/langgraph-bedrock-tool-argsassistant-ui/assistant-ui:fix/langgraph-bedrock-tool-argsCopy head branch name to clipboard
Open

fix(react-langgraph): preserve streamed bedrock tool args#5080
Kinfe123 wants to merge 4 commits into
mainassistant-ui/assistant-ui:mainfrom
fix/langgraph-bedrock-tool-argsassistant-ui/assistant-ui:fix/langgraph-bedrock-tool-argsCopy head branch name to clipboard

Conversation

@Kinfe123

@Kinfe123 Kinfe123 commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Summary

  • treat an argless matching tool_call_chunk as an empty streaming prefix
  • preserve the existing stringify fallback for completed or reloaded messages without chunks
  • add a regression test covering the Bedrock first-frame shape and following partial args

Why

Bedrock can start a tool call with a chunk that has an ID and name but no argument text. The converter previously turned the parsed empty object into "{}". Later argument prefixes such as {"url": are not extensions of "{}", so the invocation tracker rejected them and the frontend tool executed with empty arguments.

Testing

  • reproduced on current main: the regression test received argsText: "{}" instead of ""
  • @assistant-ui/react-langgraph: 182 tests passed
  • @assistant-ui/react-langgraph build passed
  • repository lint and format checks passed (existing unrelated warnings only)

Closes #5074

Review in cubic

@Kinfe123
Kinfe123 requested a review from a team July 20, 2026 19:54
@changeset-bot

changeset-bot Bot commented Jul 20, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: a3e8ff8

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@assistant-ui/react-langgraph Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@rupic-app rupic-app Bot added stage/needs-review No reviews yet; waiting for a maintainer pkg/react-langgraph Changes a package under packages/ R0 Act now: stale, blocked, or high impact type/bugfix Bug fix labels Jul 20, 2026
@claude

claude Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Claude finished @Kinfe123's task in 2m 17s —— View job


Review — PR #5080 (through a3e8ff8)

Changes since last review

One commit, a3e8ff8, which applies the previously suggested refactor verbatim: streamedArgsText is resolved before the predicate, and isStreamingArglessChunk now explicitly requires streamed text to be absent, so the flag's truth value matches its name in every state rather than relying on its position in the ?? chain.

Previously identified issues — all resolved

Issue Status
Completed args hidden when an argless chunk is retained (greptile) ✅ Fixed in 98fce8a, covered by the "serializes completed tool args when an argless chunk remains" test
Anonymous ternary hides the Bedrock rule ✅ Named isStreamingArglessChunk in 3a5247b
Flag truth value coupled to ??-chain position ✅ Decoupled in a3e8ff8

Correctness

The fix targets the right root cause. The tracker enforces a prefix-monotonic contract on argsText (packages/core/src/runtimes/tool-invocations/ToolInvocationTracker.ts:638content.argsText.startsWith(entry.argsText)), so a first snapshot of "{}" permanently rejects every later prefix like '{"url":'. Emitting "" for the argless first frame is the uniquely safe value: every string starts with "".

I also confirmed the fix only affects the path that was actually broken. The messages-tuple accumulator (appendLangChainChunk.ts:10) already synthesizes partial_json: "" for an argless first chunk, so that path never hit the stringify fallback; the bug lived in the messages/partial path where the server sends full snapshots with tool_calls + tool_call_chunks and no partial_json — exactly what the new tests model.

One benign behavioral edge worth knowing about (not blocking)

A completed zero-argument tool call that still retains an argless chunk now converts to argsText: "" where it previously produced "{}". This state is inherently ambiguous ("streaming, args not started" vs "completed, no args"), and the streaming interpretation is the safe one:

  • args is still chunk.args ({}), so tool execution is unaffected.
  • "" is a prefix of "{}", so if the server drops tool_call_chunks at messages/complete, the converter self-corrects to "{}" and the tracker accepts it.

No action needed; noting it so it doesn't surprise anyone later.

Tests & repo requirements

  • Both regression tests are well-targeted: the Bedrock first-frame → partial-args sequence (prefix monotonicity) and the retained-argless-chunk-with-completed-args case (the earlier greptile regression). Fixtures match the real messages/partial wire shape.
  • Changeset present (@assistant-ui/react-langgraph, patch) ✅
  • No public API surface change, so no api-reference regen needed ✅
  • CI: all runs green (the one cancelled Changeset Semver Check was superseded by a successful re-run). I couldn't execute the test suite locally in this sandbox (command approval), so I'm relying on the green PR #5080 CI run.

Good practices

  • Regression tests model the exact provider wire shape from the issue, both directions of the ambiguity.
  • Review feedback applied as focused, single-purpose commits.

Simplify

The simplify agent surfaced one candidate: the streamedArgsText === undefined clause is technically redundant at the ternary's only use site (the ternary is reached only when chunk.partial_json ?? streamedArgsText is nullish), so predicate and ternary could collapse back into the ?? chain. I'm deliberately not requesting this — it would reverse the decoupling applied in a3e8ff8, whose point was that the flag's truth value shouldn't depend on chain position. The current form is the right trade. No other reuse, efficiency, or simplification issues found.

Verdict: LGTM. The fix is minimal, root-caused, tested from both directions, and all prior review threads are resolved.

@greptile-apps

greptile-apps Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Reviews (1): Last reviewed commit: "fix(react-langgraph): preserve streamed ..." | Re-trigger Greptile

Comment thread packages/react-langgraph/src/convertLangChainMessages.ts Outdated
@rupic-app rupic-app Bot added stage/awaiting-reviewer Has reviews but not approved; reviewer follow-up needed and removed stage/needs-review No reviews yet; waiting for a maintainer labels Jul 20, 2026
Comment thread packages/react-langgraph/src/convertLangChainMessages.ts Outdated
Comment thread packages/react-langgraph/src/convertLangChainMessages.ts Outdated
Comment thread packages/react-langgraph/src/convertLangChainMessages.ts
@rupic-app rupic-app Bot added stage/awaiting-author Changes requested or CI failing; ball is with the author R2 Ball is in the author's court; not actionable today stage/awaiting-reviewer Has reviews but not approved; reviewer follow-up needed R0 Act now: stale, blocked, or high impact and removed stage/awaiting-reviewer Has reviews but not approved; reviewer follow-up needed R0 Act now: stale, blocked, or high impact stage/awaiting-author Changes requested or CI failing; ball is with the author R2 Ball is in the author's court; not actionable today labels Jul 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pkg/react-langgraph Changes a package under packages/ R0 Act now: stale, blocked, or high impact stage/awaiting-reviewer Has reviews but not approved; reviewer follow-up needed type/bugfix Bug fix

Projects

None yet

1 participant

Morty Proxy This is a proxified and sanitized view of the page, visit original site.