Skip to content

feat(events): add turnId to SSE events for per-LLM-turn grouping - #5307

Closed
ilyesJammouci wants to merge 5 commits into
google:mainfrom
ilyesJammouci:feat/turn-id-streaming-events-4793
Closed

ilyesJammouci wants to merge 5 commits into
google:mainfrom
ilyesJammouci:feat/turn-id-streaming-events-4793

Conversation

@ilyesJammouci

Copy link
Copy Markdown

Closes: #4793

Problem

With runner.run_async() + StreamingMode.SSE, one invocation can contain multiple LLM calls (for example: text → tool call → text).
invocation_id is shared by all events, and id changes on each yield, so clients cannot reliably group partial chunks and final output from the same LLM call.turn.

Solution

This PR adds an additive turn_id field to Event (serialized as turnId) and propagates it through streaming flow:

  1. Generate one turn_id per LLM call step.
  2. Keep the same turn_id for partial chunks and final model event of that call.
  3. Propagate that turn_id to tool-derived follow-up events.
  4. Start a new turn_id when a new LLM call begins.

The first two images come from the same LLM call, so they share the same turnId.
image
image
This image comes from a different LLM call, so it has a different turnId.
image

Testing

  1. Run local unit tests: pytest test_base_llm_flow.py test_base_llm_flow_partial_handling.py test_progressive_sse_streaming.py test_functions_simple.py test_functions_parallel.py -q

  2. Locally validate SSE behavior via Web UI:

  • Start the app with adk web src/google/adk/agent.
  • Open an agent that triggers a multi-step flow (text → tool call → text) with streaming enabled.
  • Verify streamed payloads include turnId.
  • Confirm all partial and final events from the same LLM call share the same turnId, and that each new LLM call uses a different turnId.

@rohityan rohityan self-assigned this Apr 13, 2026
@rohityan rohityan added services [Component] This issue is related to runtime services, e.g. sessions, memory, artifacts, etc labels Apr 13, 2026
@rohityan

Copy link
Copy Markdown
Collaborator

Hi @ilyesJammouci , Thank you for your contribution! We appreciate you taking the time to submit this pull request. Please fix formatting errors by running autoformat.sh

@rohityan rohityan added request clarification [Status] The maintainer need clarification or more information from the author labels Apr 13, 2026
@ilyesJammouci

Copy link
Copy Markdown
Author

Hi @rohityan I fixed the formatting issues . Ready for review

@ilyesJammouci

Copy link
Copy Markdown
Author

Hi @rohityan, just a quick follow-up on this PR.
I’ve addressed the formatting issues and applied the requested changes. would appreciate it if you could take another look when you have time. Thanks!

@DeanChensj

Copy link
Copy Markdown
Collaborator

Hi @ilyesJammouci,

Thank you for putting this together and for tackling #4793! We really appreciate the detailed PR description, screenshots, and test coverage.
After discussing this internally with the team, we have decided not to add turn_id to the core Event model, and will be closing this PR. Here is our thinking:

  1. Core Schema & Persistence Scope: Event is the foundational data model across the entire ADK runtime. Adding a new field to Event impacts every SessionService implementation (DatabaseSessionService, VertexAiSessionService, GCS, etc.) and introduces serialization/storage migration overhead across all persistent backends.
  2. State & Distributed Consistency: In distributed deployments, branched workflows, and pause/resume scenarios across different workers and over time, generating and maintaining a globally consistent, reliable turn identifier on every event is fragile and difficult to guarantee.
  3. Layering: The underlying problem in Add a turn/response group identifier to streaming events #4793—grouping streaming SSE chunks within a single invocation for UI rendering—is primarily a transient presentation/streaming-layer concern. We believe this is better addressed via stream utility/helper functions that inspect event boundaries on the consumer side, rather than cementing a new persistent field into the core Event schema.
    Thank you again for your time and contribution here, and we welcome any ideas or PRs on client-side / stream helper utilities for chunk grouping!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

request clarification [Status] The maintainer need clarification or more information from the author services [Component] This issue is related to runtime services, e.g. sessions, memory, artifacts, etc

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a turn/response group identifier to streaming events

3 participants