fix: use stream(values) for reliable agent streaming - #50
Merged
Conversation
…ithout text The streaming event loop used two sequential for-await loops: one on stream.messages (to collect text) and one on stream (for tool events). When the LLM generated an AIMessage with tool calls but no text content, stream.messages yielded a ChatModelStream backed by a ReplayBuffer that blocked indefinitely waiting for text-delta events that never arrived. This prevented tool events from ever being processed, causing the agent to silently hang with no response. Replace the two-loop approach with a single loop over the raw stream that processes both text events (from ChatModelStream chunk events) and tool events in one pass. This ensures nothing blocks and all events are processed correctly. Add test cases covering the blocking scenario and the new event-chunk text extraction approach.
…hoing input - Iterate stream events directly (not stream.messages) to avoid ChatModelStream.text ReplayBuffer blocking bug - Extract text from content-block-delta protocol events - Fall back to agent.invoke() when no streaming text captured - Throw 'No response from agent' when nothing captured instead of silently echoing user input - Update all streaming tests to new event format
Tool always returns 'hello_world!' and requires zero permissions so it's always available to the LLM. Helps diagnose if the problem is: - Tool registration/availability - Streaming text capture (ReplayBuffer blocking) - Tool execution/sandbox layer
LangGraph v3 streamEvents normalizes internal event names before the
protocol event stream reaches consumers. The previous code checked for
internal names ('on_tool_start', 'on_tool_end', etc.) which never
matched the protocol names ('tool-started', 'tool-finished', etc.).
This caused tool_end events to never fire in production, so tool results
never appeared in the TUI chat. Fixed by checking for both protocol and
legacy names. Also updated test mocks to use protocol event names.
…l_end events Logs every event method and event key flowing through the stream so we can see exactly what events arrive and in what order. Look for [stream] lines in the server output.
…text to /tmp/madz_cb.log
…ogging The agent.invoke() fallback was restarting the entire agent run, causing infinite tool call loops. Now the streaming loop properly returns the captured text from content-block-delta events, or throws a clear error if no text was produced. Also cleaned up debug logging files (mazd_stream.log, mazd_emit.log, mazd_cb.log) from react.js and hello.js.
Logs every event the TUI callback receives (type, text, toolName, data, error). This will show if tool_end/tool_error callbacks are actually firing and what data they contain.
…ts reach the loop
Replace streamEvents(v3) approach which did not produce tool events for ReAct agents. Now uses agent.stream(streamMode: 'values') to yield state snapshots containing messages array. Extract tool calls from AIMessage content, extract text from message payload. This provides a single-execution streaming path with no blocking issues from ReplayBuffer or mismatched tool/text pairs from dual stream runs.
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.
Description
Replace streamEvents(v3) with stream(streamMode: "values") for reliable ReAct agent streaming. The v3 protocol does not emit method: "tools" events for ReAct agents, and dual-stream approaches start two independent executions that produce mismatched results.
Type of Change
Testing
Coverage
Checklist
npm run lintpasses