google / google/adk-web

Streaming thought chunks render as separate bubbles instead of consolidating

Open
#443 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
1k
Forks
267
Avg merge
1d 12h
Merged PRs (30d)
9

Description

## Description

When using streaming mode (SSE) with models that emit thinking/reasoning content (e.g., Claude with extended thinking via LiteLLM, or Gemini with `thinking_config`), each partial `ReasoningChunk` renders as a **separate "Thought" bubble** in the Dev UI instead of being consolidated into a single thought block.

**Non-streaming mode** correctly shows a single consolidated "Thought" bubble.

## Steps to Reproduce

1. Configure an ADK agent with a model that supports thinking/reasoning (e.g., `vertex_ai/claude-sonnet-4-6` via `LiteLlm` with `thinking={"type": "enabled", "budget_tokens": 10000}`)
2. Run `adk web` and open the Dev UI
3. Send a message to the agent
4. Observe the event timeline — each streaming thought chunk appears as a separate "Thought" bubble (e.g., #2 "The user said", #3 '"hola" (', #4 "hello).", etc.)

## Expected Behavior

Consecutive partial thought events should be consolidated into a single "Thought" bubble that progressively accumulates text, similar to how text response chunks are merged into a single response bubble.

## Actual Behavior

Each `ReasoningChunk` partial generates a separate "Thought" bubble in the timeline, resulting in dozens of fragmented thought events for a single reasoning block.

## Analysis

The consolidation logic in `chat.component.ts` (lines ~1237-1257) attempts to merge thought partials by searching for an existing event with `partial=true` and `thought=true`. However, `buildUiEventFromEvent` creates a new `UiEvent` with only the current chunk's content, and the replacement at line ~1285 (`newEvents[existingIndex] = uiEvent`) replaces rather than accumulates the text. This causes either:
- The consolidation search to fail (resulting in multiple bubbles), or
- The previous thought to be replaced instead of appended to

## Environment

- ADK Python: v1.32.0
- ADK Web: latest (cloned from main)
- Model: `vertex_ai/claude-sonnet-4-6` via `LiteLlm` with extended thinking enabled
- Also reproducible with native `LiteLlm` (not just custom `BaseLlm` subclasses)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.