Skip to content

feat(a2a): switch from callback-based to event-driven tool scheduler#21467

Merged
cocosheng-g merged 12 commits intomainfrom
pr-17128-takeover
Mar 10, 2026
Merged

feat(a2a): switch from callback-based to event-driven tool scheduler#21467
cocosheng-g merged 12 commits intomainfrom
pr-17128-takeover

Conversation

@cocosheng-g
Copy link
Contributor

@cocosheng-g cocosheng-g commented Mar 6, 2026

No description provided.

@gemini-cli
Copy link
Contributor

gemini-cli bot commented Mar 6, 2026

Hi @cocosheng-g, thank you so much for your contribution to Gemini CLI! We really appreciate the time and effort you've put into this.

We're making some updates to our contribution process to improve how we track and review changes. Please take a moment to review our recent discussion post: Improving Our Contribution Process & Introducing New Guidelines.

Key Update: Starting January 26, 2026, the Gemini CLI project will require all pull requests to be associated with an existing issue. Any pull requests not linked to an issue by that date will be automatically closed.

Thank you for your understanding and for being a part of our community!

@cocosheng-g cocosheng-g changed the title refactor(a2a-server): resolve merge conflicts and address PR 17128 feedback feat(a2a): switch from callback-based to event-driven tool scheduler Mar 6, 2026
@github-actions
Copy link

github-actions bot commented Mar 6, 2026

Size Change: +264 B (0%)

Total Size: 26.2 MB

ℹ️ View Unchanged
Filename Size Change
./bundle/gemini.js 25.7 MB +264 B (0%)
./bundle/node_modules/@google/gemini-cli-devtools/dist/client/main.js 221 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/_client-assets.js 227 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/index.js 11.5 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/types.js 132 B 0 B
./bundle/sandbox-macos-permissive-open.sb 890 B 0 B
./bundle/sandbox-macos-permissive-proxied.sb 1.31 kB 0 B
./bundle/sandbox-macos-restrictive-open.sb 3.36 kB 0 B
./bundle/sandbox-macos-restrictive-proxied.sb 3.56 kB 0 B
./bundle/sandbox-macos-strict-open.sb 4.82 kB 0 B
./bundle/sandbox-macos-strict-proxied.sb 5.02 kB 0 B

compressed-size-action

@cocosheng-g
Copy link
Contributor Author

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces an event-driven scheduler to the Task class, providing an alternative to the existing callback-based CoreToolScheduler. The Task constructor now conditionally initializes either the new Scheduler (if isEventDrivenSchedulerEnabled is true) or the legacy scheduler. Key changes include new methods (setupEventDrivenScheduler, handleEventDrivenToolCallsUpdate, handleEventDrivenToolCall, checkInputRequiredState) to subscribe to TOOL_CALLS_UPDATE messages from a MessageBus, process tool call statuses (including output, terminal states, and confirmation requests), stash correlation IDs, publish status updates to the A2A event bus, and manage auto-execution (YOLO mode). The tool confirmation flow (_handleToolConfirmationPart) has been updated to publish TOOL_CONFIRMATION_RESPONSE messages via the MessageBus when a correlation ID is present, while maintaining a fallback for legacy callback-based confirmations. A new enableEventDrivenScheduler configuration setting, defaulting to true, controls this feature, and a new test file (task-event-driven.test.ts) validates the new scheduler's functionality. A review comment points out an issue in the new tool confirmation logic, specifically that the confirmed property in the TOOL_CONFIRMATION_RESPONSE message is incorrectly set to true only for ProceedOnce outcomes, suggesting it should be true for all outcomes that lead to tool execution (i.e., not Cancel or ModifyWithEditor).

@gemini-cli gemini-cli bot added the area/agent Issues related to Core Agent, Tools, Memory, Sub-Agents, Hooks, Agent Quality label Mar 6, 2026
@cocosheng-g cocosheng-g force-pushed the pr-17128-takeover branch 2 times, most recently from b0632cc to abc05ff Compare March 9, 2026 18:45
@cocosheng-g
Copy link
Contributor Author

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces an event-driven scheduler for tool calls within the Task class, allowing for a more reactive and asynchronous handling of tool execution and confirmations. The changes include integrating a new Scheduler class, conditionally enabling it via a new configuration setting (isEventDrivenSchedulerEnabled), and refactoring tool call lifecycle management to use a MessageBus for status updates and confirmation responses. New methods were added to handle event-driven tool call updates, manage pending confirmations, and determine input-required states. The schedule method was updated to pre-register tools and use a fire-and-forget approach for the event-driven scheduler, while tool confirmation handling was enhanced to support both legacy callbacks and message bus-based responses, including auto-approval in 'YOLO' mode. Comprehensive unit tests for the new event-driven scheduler functionality were also added.

@cocosheng-g cocosheng-g marked this pull request as ready for review March 9, 2026 18:54
@cocosheng-g cocosheng-g requested a review from a team as a code owner March 9, 2026 18:54
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly refactors the tool scheduling mechanism within the a2a-server by transitioning from a callback-based system to a modern event-driven architecture. This change enhances the robustness and scalability of tool execution, particularly in handling asynchronous operations and user confirmations. It also addresses several critical race conditions and deadlocks, improving the overall stability and reliability of the agent's interaction with tools.

Highlights

  • Event-Driven Scheduler Migration: Migrated packages/a2a-server to utilize a modern, event-driven Scheduler by default, replacing the legacy callback-based CoreToolScheduler for improved architecture and scalability.
  • Enhanced Tool Confirmation and Status Updates: Implemented a MessageBus listener within the Task class to handle tool status updates, live output, and confirmations using correlationId, streamlining asynchronous communication.
  • Critical Deadlock and Race Condition Fixes: Resolved significant executor deadlock bugs by introducing synchronous pre-registration of pending tools and a toolsAlreadyConfirmed cache, preventing premature waitForPendingTools resolution and agent hangs.
  • Comprehensive Test Coverage: Added extensive test coverage for Confirmation User Journeys (CUJs) in the new event-driven scheduler, rigorously validating execution flows including auto-proceed, rejection, and modification.
  • Code Refactoring and Review Feedback: Refactored the Task class by extracting complex logic into distinct semantic methods (handleEventDrivenToolCall, checkInputRequiredState), removed redundant code, and improved TypeScript type handling based on code review feedback.
Changelog
  • packages/a2a-server/src/agent/task-event-driven.test.ts
    • Added new test file for the event-driven scheduler.
    • Included tests for scheduler instantiation, TOOL_CALLS_UPDATE subscription, tool confirmations (proceed, cancel, modify), YOLO mode auto-execution, output updates, and artifact creation.
  • packages/a2a-server/src/agent/task.ts
    • Updated Task class to use Scheduler | CoreToolScheduler type for scheduler.
    • Introduced pendingCorrelationIds map and toolsAlreadyConfirmed set for managing event-driven confirmations.
    • Modified Task constructor to conditionally initialize Scheduler or CoreToolScheduler based on isEventDrivenSchedulerEnabled config.
    • Enhanced cancelAll method to handle both Scheduler and CoreToolScheduler cancellation logic and clear pendingCorrelationIds.
    • Renamed createScheduler to createLegacyScheduler and added setupEventDrivenScheduler for the new event-driven flow.
    • Implemented handleEventDrivenToolCallsUpdate and handleEventDrivenToolCall methods to process TOOL_CALLS_UPDATE messages from the MessageBus, managing tool states, output, confirmations, and auto-execution.
    • Added checkInputRequiredState to manage the input-required task state based on pending tool calls and confirmations, resolving toolCompletionPromise prematurely to prevent deadlocks.
    • Modified schedule method to pre-register tool calls synchronously before dispatching to the scheduler, preventing race conditions with waitForPendingTools.
    • Updated _handleToolConfirmationPart to use toolsAlreadyConfirmed and publish TOOL_CONFIRMATION_RESPONSE messages via MessageBus for event-driven confirmations, while retaining fallback for legacy callbacks.
    • Ensured _resetToolCompletionPromise is called after handling confirmations to correctly await tool execution.
    • Removed pendingCorrelationIds when a tool confirmation is processed.
  • packages/a2a-server/src/config/config.ts
    • Added enableEventDrivenScheduler to the loaded configuration, defaulting to true if not specified in settings.
  • packages/a2a-server/src/config/settings.ts
    • Introduced an experimental setting enableEventDrivenScheduler to control the new event-driven scheduler.
  • packages/a2a-server/src/utils/testing_utils.ts
    • Updated the mock configuration utility to include a mock for isEventDrivenSchedulerEnabled.
Activity
  • Superseded feat(a2a): switch from callback-based to event-driven tool scheduler #17128, integrating its changes and further refining the event-driven scheduler implementation.
  • Resolved recent merge conflicts in task.ts, config.ts, and settings.ts to ensure compatibility with main.
  • Addressed code review feedback by extracting logic into distinct methods, removing redundant checks, renaming private methods, and rectifying TypeScript casting issues.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

abhipatel12 and others added 5 commits March 9, 2026 14:55
This change transitions packages/a2a-server to use the event-driven
Scheduler by default. It replaces the legacy direct callback mechanism
with a MessageBus listener in the Task class to handle tool status
updates, live output, and confirmations.

- Added experimental.enableEventDrivenScheduler setting (defaults to true).
- Refactored Task.ts to support both legacy and event-driven schedulers.
- Implemented bus-based tool confirmation responses using correlationId.
- Exported Scheduler from packages/core.
- Added unit tests for the event-driven flow in A2A.
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

The pull request introduces an event-driven scheduler to the Task class, allowing it to handle tool call updates and confirmations via a message bus, with a fallback to the legacy scheduler. This involves adding new methods for event handling, managing tool confirmation correlation IDs, and updating the task state based on tool execution and approval flows, including a "YOLO" mode for auto-execution. A critical issue was identified where the legacy scheduler's cancelAll method does not properly abort its AbortSignal, potentially leading to dangling processes.

…ension

* Preserved continuous currentAgentMessageId during each turn to prevent separate UI bubbles
* Added processedToolCallIds to prevent state manager from triggering multiple generation cycles
* Added test coverage for MCP Server user journey operations
This commit adds tests for ProceedAlwaysServer, ProceedAlwaysTool, and ProceedAlwaysAndSave, and fixes a missing outcome mapping in the A2A task implementation to support all PR 21467 event-driven flows.
@cocosheng-g
Copy link
Contributor Author

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request is a significant refactoring that migrates the A2A server to a modern, event-driven scheduler, effectively addressing critical issues like deadlocks and race conditions, thereby improving robustness and reliability. While the architectural change is sound and the implementation includes comprehensive test coverage, a critical security regression has been identified. The new asynchronous flow bypasses the mechanism intended to prevent sensitive GCP credentials from leaking into tool calls during tool confirmation. This vulnerability needs to be addressed to ensure environment variable protection. Additionally, a potential memory leak related to MessageBus subscriptions has been identified, requiring proper cleanup.

cocosheng-g and others added 3 commits March 9, 2026 18:20
This commit addresses PR 21467 code review: (1) Adds missing await on the message bus publish in _handleToolConfirmationPart to prevent GCP variables from prematurely restoring and leaking into external tools. (2) Adds dispose() to Task.ts and explicitly unregisters the message bus listener from cache when tasks reach terminal states in executor.ts, preventing unbounded memory leaks over the session.
This commit addresses edge cases for PR 21467:
* Fixes a bug in YOLO mode where auto-approved tool calls incorrectly triggered an `input-required` task state by adding the call ID to the confirmed tools set.
* Adds comprehensive test coverage for YOLO mode auto-approvals, parallel tool calls, executing background tools, and unknown tool ID confirmations.
* Ensures pendingCorrelationIds is safely deleted alongside pendingToolConfirmationDetails to prevent memory leaks in long-running tasks.
* Adds a regression test to verify that delayed or spurious confirmations are safely ignored once the ID is cleaned up.
Copy link
Contributor

@adamfweidman adamfweidman left a comment

Choose a reason for hiding this comment

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

LGTM

adamfweidman and others added 2 commits March 10, 2026 13:54
Address stalls and task abortion regressions in YOLO mode by implementing unconditional core policy approval and primary execution loop isolation. Add comprehensive unit test coverage for PolicyEngine and CoderAgentExecutor.
@cocosheng-g cocosheng-g enabled auto-merge March 10, 2026 19:28
@cocosheng-g cocosheng-g added this pull request to the merge queue Mar 10, 2026
Merged via the queue into main with commit 1b69637 Mar 10, 2026
28 checks passed
@cocosheng-g cocosheng-g deleted the pr-17128-takeover branch March 10, 2026 19:48
@adamfweidman
Copy link
Contributor

/patch preview

@github-actions
Copy link

🚀 [Step 1/4] Patch workflow(s) waiting for approval!

📋 Details:

  • Channels: preview
  • Commit: 1b6963703291c2503245933c9a34d36c296a31c1
  • Workflows Created: 1

⏳ Status: The patch creation workflow has been triggered and is waiting for deployment approval. Please visit the specific workflow links below and approve the runs.

🔗 Track Progress:

github-actions bot pushed a commit that referenced this pull request Mar 10, 2026
…21467)

Co-authored-by: Abhi <abhipatel@google.com>
Co-authored-by: Adam Weidman <adamfweidman@google.com>
# Conflicts:
#	packages/a2a-server/src/config/config.ts
@github-actions
Copy link

🚀 [Step 2/4] Patch PR Created!

📋 Patch Details:

📝 Next Steps:

  1. ⚠️ Resolve conflicts in the hotfix PR first: #21930
  2. Test your changes after resolving conflicts
  3. Once merged, the patch release will automatically trigger
  4. You'll receive updates here when the release completes

🔗 Track Progress:

@github-actions
Copy link

🚀 [Step 3/4] Patch Release Waiting for Approval!

📋 Release Details:

⏳ Status: The patch release has been triggered and is waiting for deployment approval. Please visit the specific workflow run link below and approve the deployment. You'll receive another update when it completes.

🔗 Track Progress:

@github-actions
Copy link

[Step 4/4] Patch Release Complete!

📦 Release Details:

🎉 Status: Your patch has been successfully released and published to npm!

📝 What's Available:

🔗 Links:

JaisalJain pushed a commit to JaisalJain/gemini-cli that referenced this pull request Mar 11, 2026
…oogle-gemini#21467)

Co-authored-by: Abhi <abhipatel@google.com>
Co-authored-by: Adam Weidman <adamfweidman@google.com>
kunal-10-cloud pushed a commit to kunal-10-cloud/gemini-cli that referenced this pull request Mar 12, 2026
…oogle-gemini#21467)

Co-authored-by: Abhi <abhipatel@google.com>
Co-authored-by: Adam Weidman <adamfweidman@google.com>
liamhelmer pushed a commit to badal-io/gemini-cli that referenced this pull request Mar 12, 2026
…oogle-gemini#21467)

Co-authored-by: Abhi <abhipatel@google.com>
Co-authored-by: Adam Weidman <adamfweidman@google.com>
yashodipmore pushed a commit to yashodipmore/geemi-cli that referenced this pull request Mar 21, 2026
…oogle-gemini#21467)

Co-authored-by: Abhi <abhipatel@google.com>
Co-authored-by: Adam Weidman <adamfweidman@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/agent Issues related to Core Agent, Tools, Memory, Sub-Agents, Hooks, Agent Quality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants