Skip to content

Conversation

@rainbow-f1zz
Copy link

@rainbow-f1zz rainbow-f1zz commented Nov 25, 2025

Proposal

Fix #705

Introduce a new parameter streamAgentTools in StreamRunOptions. When set to true, the StreamRunResult object returned by Runner.run() contains all stream events from current agent, and all agents invoked via agent-as-tools, recursively.

For example, the following setup:

const agentB = new Agent(...);
const agentA = new Agent(
  ..., 
  tools=[agentB.asTool(...)]
);
const runner = new Runner(...);
const result = runner.run(
  agentA,
  'Solve task by using agentB as a tool',
  {
    stream: true,
    streamAgentTools: true,
  }
);

We can consume events by for await (const event of result) {...}, and events originate from both agent A and agent B.

Background

I was working on an app with a main agent using other tool agents as tools, for better responsibility separation. To provide live update to end users, I process stream events from the main agent. In current implementation, the events from main stream only consist of tool_called / tool_output in run item events, or corresponding raw events.

This behavior creates a challenge for live updates - end users can see that the main agent is invoking a tool, but it may look stuck if tool agent takes a while to run. Although there are workarounds like writing updates in agent hooks, they all require code changes to handle this case. What I needed was a straightforward toggle to enable stream events from all agents recursively, working with agent-as-tools, handoffs, etc.

I see similar PRs requesting for features in the Python library, so I feel that this is a pretty common use case.

Implementation details

I added a context-scope stream that all runners invoked with a single RunContext can use to send stream events. The first runner owns the stream, and other runner (initialized indirectly inside asTool()) copies events to the context-scope stream if necessary.

Changes

  1. added streamAgentTools in StreamRunOptions
  2. updated StreamRunResult to handle streamAgentTools; created context-scope stream; copied events to the context-scope stream; handled completion/abort/failure scenarios
  3. updated asTool execute method to check run context; if enabled, passed StreamRunOptions to runner and await for completion
  4. added a stream-agent-tools.ts example snippet
  5. unit tests

Unrelated fix

This PR also contains 2 commits to (1) remove redundant tool name replacement (non-alphanumeric -> underscore already handles space -> underscore), and (2) fix a typo (Schame -> Schema).

@changeset-bot
Copy link

changeset-bot bot commented Nov 25, 2025

⚠️ No Changeset found

Latest commit: 34d6cce

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 287 to 291
this.#contextScopeStreamOwner = true;
this.state._context._copyToContextScopeStream = true;
},
cancel: () => {},
});

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Propagate cancellation for context scope stream

When streamAgentTools is enabled, the async iterator returned from StreamedRunResult is the context-scope stream created here, but its cancel handler is a no-op and never marks the result as cancelled. If a caller stops consuming the stream (e.g., breaks out of for await), the context stream is cancelled but #cancelled stays false, so _addItem continues to enqueue into a cancelled controller and the run loop keeps executing nested agents instead of short-circuiting. This regresses the previous cancellation semantics (line 264) and can throw once the controller is closed or waste work for abandoned streams. The cancel handler should set the same cancellation flag/cleanup as the primary stream.

Useful? React with 👍 / 👎.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@seratch seratch added enhancement New feature or request package:agents-core labels Dec 2, 2025
@seratch seratch marked this pull request as draft December 2, 2025 02:54
@seratch
Copy link
Member

seratch commented Dec 2, 2025

Thanks for sending this patch. While the code changes are minimal, the behavioral & design changes are not minor. Also, the inconsistency between function tools and agent tools here could be a potential issue. I need to handle other priorities right now, so let me hold off actively working on this at this moment.

@seratch seratch changed the title Feat: added context scope stream to enable streaming event from nested agent-as-tool invocations Feat: #705 added context scope stream to enable streaming event from nested agent-as-tool invocations Dec 2, 2025
@rainbow-f1zz
Copy link
Author

Hey @seratch, thanks for the reply. Yeah I had the same concerns when I worked on the code, and it appeared more like a design choice rather than a simple code change.

With that being said, I'm still curious if this feature will be included in the SDK in the future. Is there progress on the Python SDK side?

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enable unified streaming of all agents in a run (agent-as-tools, handoffs) recursively with streamAgentTools param

3 participants