Skip to content

feat: add Event.intermediate flag for multi-step agent streaming#273

Open
nuthalapativarun wants to merge 6 commits into
google:mainfrom
nuthalapativarun:feat/event-intermediate-flag
Open

feat: add Event.intermediate flag for multi-step agent streaming#273
nuthalapativarun wants to merge 6 commits into
google:mainfrom
nuthalapativarun:feat/event-intermediate-flag

Conversation

@nuthalapativarun
Copy link
Copy Markdown
Contributor

Please ensure you have read the contribution guide before creating a pull request.

Link to Issue or Description of Change

Problem:
During multi-step agent turns (e.g. model text → tool call → model text), streaming consumers cannot distinguish model text emitted before a tool call from the final response text. Both appear as identical events, forcing clients to buffer everything or show intermediate reasoning text to the user unintentionally.

Solution:
Add an optional intermediate?: boolean field to the Event interface. In LlmAgent.runAsyncImpl, events from steps that are followed by function calls are marked intermediate: true. Final response events remain unmarked (undefined).

for await (const event of runner.runAsync({ ... })) {
  if (event.intermediate) continue; // skip reasoning steps
  displayToUser(event);
}

This is a purely additive, non-breaking change. Existing consumers that do not check intermediate are unaffected. Aligned with adk-python behaviour.

Implementation details:

  • Event.intermediate?: boolean added to core/src/events/event.ts
  • LlmAgent.runAsyncImpl in core/src/agents/llm_agent.ts now collects all events per step, checks whether the step is final (isFinalResponse), and sets intermediate: true on non-final steps before yielding

Testing Plan

Unit Tests:

  • I have added or updated unit tests for my change.
  • All unit tests pass locally.

Summary of passed npm test results:

✓ |unit:core| core/test/agents/event_intermediate_test.ts (5 tests) 7ms

Test Files  1 passed (1)
     Tests  5 passed (5)

Full suite (on this branch): 1101 passed | 21 skipped

Manual End-to-End (E2E) Tests:
The intermediate field is optional and additive. All existing tests pass without modification.

Checklist

  • I have read the CONTRIBUTING.md document.
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • I have manually tested my changes end-to-end.
  • Any dependent changes have been merged and published in downstream modules.

Add an optional Event.intermediate boolean field that is set to true
on all events emitted during agent steps that produce function calls
(i.e. steps that are followed by tool execution and more LLM calls).

This allows streaming consumers to distinguish between model text
produced as part of a reasoning/tool-calling step versus the final
response text returned to the user.

Motivation: issue google#261. Aligned with adk-python behaviour.
@nuthalapativarun nuthalapativarun force-pushed the feat/event-intermediate-flag branch from e2618c5 to 0d35f5b Compare April 18, 2026 03:26
@nuthalapativarun
Copy link
Copy Markdown
Contributor Author

Hi team, gentle ping on this one — happy to address any feedback or make adjustments if needed. Thanks for reviewing!

@nuthalapativarun
Copy link
Copy Markdown
Contributor Author

Hi team, gentle ping on this one — happy to address any feedback or make adjustments if needed. Thanks for reviewing!

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.

1 participant