Skip to content

feat(core): wire AgentSession invocations into agent-tool - #26948

Merged
adamfweidman merged 9 commits into
mainfrom
agent-session/agent-tool
May 19, 2026
Merged

feat(core): wire AgentSession invocations into agent-tool#26948
adamfweidman merged 9 commits into
mainfrom
agent-session/agent-tool

Conversation

@adamfweidman

@adamfweidman adamfweidman commented May 12, 2026

Copy link
Copy Markdown
Collaborator

Summary

Wires AgentSession invocations into AgentTool behind the adk.agentSessionSubagentEnabled feature flag.

Details

  • Updated packages/core/src/agents/agent-tool.ts to check context.config.isAgentSessionEnabled().
  • If the flag is enabled, it uses RemoteSessionInvocation and LocalSessionInvocation for subagent calls.
  • This branch is stacked on top of experimental-flag.

Related Issues

Relates to #22700

How to Validate

Verified that the codebase builds successfully. Unit tests for agent-tool should be run to confirm behavior.

Pre-Merge Checklist

  • Updated relevant documentation and README (if needed)
  • Added/updated tests (if needed)
  • Noted breaking changes (if any)
  • Validated on required platforms/methods:
    • MacOS
      • npm run
      • npx
      • Docker
      • Podman
      • Seatbelt

@adamfweidman
adamfweidman requested a review from a team as a code owner May 12, 2026 21:13
@gemini-code-assist

Copy link
Copy Markdown
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 enables AgentSession support within the AgentTool framework, allowing for more robust subagent interactions behind a feature flag. It also includes critical improvements to session state management for remote agents and adds validation logic to the AgentRegistry to prevent and surface duplicate agent name conflicts.

Highlights

  • Feature Flag Integration: Integrated AgentSession invocations into AgentTool, gated by the adk.agentSessionSubagentEnabled feature flag.
  • Session State Isolation: Updated RemoteSessionInvocation to use a composite key (name::url) for session state, ensuring agents with identical names but different endpoints maintain independent state.
  • Registry Validation: Enhanced AgentRegistry to emit warnings and feedback events when duplicate agent names are registered, improving configuration debugging.
  • Event Threading: Updated AgentTool and DelegateInvocation to correctly thread onAgentEvent callbacks to session invocations.
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 the 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 counterproductive. 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.

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.

@adamfweidman
adamfweidman force-pushed the agent-session/agent-tool branch from 6833fa1 to 926a4e3 Compare May 12, 2026 21:21

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

Copy link
Copy Markdown
Contributor

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 implements session-based subagent invocations, gated by a feature flag, and adds a warning mechanism for duplicate agent names in the registry. It also updates remote session state management to use a composite key of name and URL. Review feedback highlights security concerns and potential memory leaks regarding the use of a static map for session state, suggesting a refactor to session-scoped storage or an LRU cache. Additionally, a redundant method definition in the configuration class was identified for removal.

I am having trouble creating individual review comments. Click here to see my feedback.

packages/core/src/agents/remote-session-invocation.ts (62-65)

security-high high

The sessionKey method generates a key for the static sessionState Map using only the agent name and URL, but it omits the sessionId. Because sessionState is a static member, it is shared across all instances of RemoteSessionInvocation within the same process. In multi-tenant environments (e.g., if this core library is used in a server-side application), this will cause different user sessions to share the same A2A conversation state (contextId and taskId) if they invoke the same remote agent. This leads to session collision or hijacking, where one user could inadvertently continue or access another user's conversation.

To remediate this, the sessionId should be incorporated into the session key to ensure that conversation state is isolated per session. This will require passing the AgentLoopContext to the sessionKey method.

References
  1. Avoid module-level global variables for state to prevent race conditions in concurrent environments. Instead, use instance-scoped properties, such as within a session class, for state that is primarily used within that scope.

packages/core/src/agents/remote-session-invocation.ts (53-56)

high

The use of a static Map for sessionState violates the general rule against module-level global variables for state. This implementation poses a memory leak risk in long-running processes as the map grows indefinitely with every unique agent/URL combination. More critically, it introduces a security vulnerability in multi-session or concurrent environments (such as a server) where A2A conversation state (contextId, taskId) could leak between different users or sessions sharing the same process.

Please refactor this to use session-scoped state (e.g., stored within the Config or a session-scoped service) or, at minimum, use a standard LRUCache with a reasonable size limit to mitigate memory issues.

References
  1. Avoid module-level global variables for state like caches to prevent race conditions and memory issues in concurrent environments. Instead, use session-scoped or instance-scoped state and leverage standard cache implementations like LRUCache.
  2. For caching, use the existing LruCache dependency instead of clearing the entire cache or implementing a custom LRU policy.

packages/core/src/config/config.ts (2584-2586)

high

The method isAgentSessionEnabled is redundantly defined here. It is already present in the class at line 2560. Please remove this duplicate definition to maintain code clarity and avoid confusion.

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

Copy link
Copy Markdown
Contributor

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 session-based agent invocations gated by a feature flag and adds duplicate agent name detection to the registry. It also updates remote session state management to use composite keys for improved isolation. Feedback identifies a critical security risk where the use of static maps for session state could lead to data leakage between concurrent sessions. Furthermore, the reviewer pointed out redundant and duplicate methods in the configuration class that should be consolidated.

I am having trouble creating individual review comments. Click here to see my feedback.

packages/core/src/agents/remote-session-invocation.ts (121-122)

security-high high

The RemoteSessionInvocation class uses a static Map named sessionState to persist A2A (Agent-to-Agent) conversation state. Because the map is static, it is shared across all instances within the same process, leading to state leakage between sessions in concurrent environments. Move the sessionState map to a session-scoped object, such as the Config instance or the AgentLoopContext.

References
  1. Avoid module-level global variables for state like caches to prevent race conditions and memory issues in concurrent environments. Instead, use session-scoped or instance-scoped state and leverage standard cache implementations like LRUCache.

packages/core/src/agents/remote-session-invocation.ts (228-231)

security-high high

This line persists the A2A conversation state into a static sessionState map. Using a static map for session-specific state leads to cross-session data leakage in long-lived processes. The state should be stored in a session-scoped container to ensure isolation.

References
  1. Avoid module-level global variables for state like caches to prevent race conditions and memory issues in concurrent environments. Instead, use session-scoped or instance-scoped state and leverage standard cache implementations like LRUCache.

packages/core/src/config/config.ts (2584-2587)

high

This method is a duplicate of the one already defined at line 2560. Please consolidate this logic to avoid duplication and improve maintainability, as per the project's architectural guidelines.

References
  1. When adding new functionality, such as filtering, consolidate it with existing similar logic to avoid duplication and improve maintainability.

packages/core/src/config/config.ts (3783-3786)

high

This method is redundant as it performs the exact same logic as isAgentSessionEnabled(). Instead of maintaining redundant logic or backward compatibility for configuration settings, remove the extra getter entirely to avoid confusion.

References
  1. Instead of maintaining backward compatibility for deprecated or unshipped configuration settings, remove them and their associated logic entirely to avoid confusion.

packages/core/src/agents/remote-session-invocation.ts (53-56)

security-high high

The use of a static map for storing session state violates the rule against module-level global variables for state. This approach can lead to race conditions and data leakage in concurrent environments. This state should be moved to a session-scoped store, such as a property on the Config instance.

References
  1. Avoid module-level global variables for state like caches to prevent race conditions and memory issues in concurrent environments. Instead, use session-scoped or instance-scoped state and leverage standard cache implementations like LRUCache.

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

Copy link
Copy Markdown
Contributor

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 session-based subagent invocations and enhances the agent registry to handle duplicate agent names with warnings. Key changes include updating AgentTool to support event threading, implementing composite keys (name and URL) for remote session state isolation, and adding feature flag checks for session-enabled invocations. Review feedback identifies a critical TypeScript compilation error due to a duplicate method definition in the Config class, a security concern regarding session leakage from static state in RemoteSessionInvocation, and a logic improvement to prevent false-positive warnings in the AgentRegistry when an agent is disabled via overrides.

I am having trouble creating individual review comments. Click here to see my feedback.

packages/core/src/config/config.ts (2584-2587)

critical

The method isAgentSessionEnabled is being added here, but it is already defined earlier in the class (around line 2563 in the current branch state). This duplication will cause a TypeScript compilation error ("Duplicate identifier 'isAgentSessionEnabled'").

packages/core/src/agents/remote-session-invocation.ts (53-56)

security-high high

The sessionState Map is declared as static, which means it is shared across all instances of RemoteSessionInvocation within the same process. This Map stores A2A conversation state (such as contextId and taskId) for remote agents. In environments where the same process handles multiple user sessions or different conversations (e.g., a long-running interactive shell or a server-side deployment of the core library), this can lead to session leakage. One session could potentially retrieve or overwrite the conversation state of another session if they use a remote agent with the same name and URL. Consider moving this state to a session-scoped object like AgentLoopContext or Config.

References
  1. Avoid module-level global variables for state like caches to prevent race conditions and memory issues in concurrent environments. Instead, use session-scoped or instance-scoped state.

packages/core/src/agents/registry.ts (340-351)

high

The warning for duplicate agent names is emitted before checking if the new agent definition is actually enabled. If the later definition is disabled (via settings overrides), it will not actually override the existing one in this.agents (as registerLocalAgent/registerRemoteAgent will return early), making this warning a false positive. The check should verify enablement before emitting the feedback.

    const existing = this.agents.get(definition.name);
    const overrides = this.config.getAgentsSettings().overrides?.[definition.name];
    if (existing && existing !== definition && this.isAgentEnabled(definition, overrides)) {
      coreEvents.emitFeedback(
        'warning',
        'Duplicate agent name \'' + definition.name + '\' detected. ' +
          'The later definition will override the earlier one. ' +
          'Rename one of the agents to avoid this conflict.',
      );
      debugLogger.warn(
        '[AgentRegistry] Overriding agent \'' + definition.name + '\' — duplicate name from a different definition.',
      );
    }

@adamfweidman
adamfweidman force-pushed the agent-session/agent-tool branch from 926a4e3 to 0dcda82 Compare May 12, 2026 21:29
@adamfweidman
adamfweidman force-pushed the agent-session/agent-tool branch from 0dcda82 to 755885f Compare May 12, 2026 21:32
@gemini-cli gemini-cli Bot added the status/need-issue Pull requests that need to have an associated issue. label May 12, 2026
@adamfweidman
adamfweidman force-pushed the agent-session/agent-tool branch 3 times, most recently from 712c435 to 4ad0926 Compare May 12, 2026 22:05
@adamfweidman
adamfweidman force-pushed the agent-session/agent-tool branch from be3b6f6 to c0981bd Compare May 13, 2026 18:33
Base automatically changed from experimental-flag to main May 17, 2026 17:47
@adamfweidman
adamfweidman force-pushed the agent-session/agent-tool branch from c0981bd to f89ebfb Compare May 18, 2026 14:02
@adamfweidman
adamfweidman changed the base branch from main to agent-session/remote-invocation May 18, 2026 14:02
@github-actions

Copy link
Copy Markdown

🛑 Action Required: Evaluation Approval

Steering changes have been detected in this PR. To prevent regressions, a maintainer must approve the evaluation run before this PR can be merged.

Maintainers:

  1. Go to the Workflow Run Summary.
  2. Click the yellow 'Review deployments' button.
  3. Select the 'eval-gate' environment and click 'Approve'.

Once approved, the evaluation results will be posted here automatically.

@github-actions

github-actions Bot commented May 18, 2026

Copy link
Copy Markdown

Size Change: +37.5 kB (+0.11%)

Total Size: 33.9 MB

Filename Size Change
./bundle/chunk-6X2YHQ47.js 0 B -49.2 kB (removed) 🏆
./bundle/chunk-B5NOV2LR.js 0 B -16.5 MB (removed) 🏆
./bundle/chunk-HPLASX37.js 0 B -19.5 kB (removed) 🏆
./bundle/chunk-J7GG7VRZ.js 0 B -2.78 MB (removed) 🏆
./bundle/chunk-J7QY2W3F.js 0 B -12.5 kB (removed) 🏆
./bundle/chunk-RNE7OO7E.js 0 B -659 kB (removed) 🏆
./bundle/chunk-SJATWTYV.js 0 B -3.77 kB (removed) 🏆
./bundle/chunk-YTFCZZ43.js 0 B -3.43 kB (removed) 🏆
./bundle/core-J7DPX7VY.js 0 B -49.2 kB (removed) 🏆
./bundle/devtoolsService-3GBNNQ5S.js 0 B -28 kB (removed) 🏆
./bundle/gemini-RTAGXC3T.js 0 B -585 kB (removed) 🏆
./bundle/interactiveCli-XH5SR2OR.js 0 B -1.3 MB (removed) 🏆
./bundle/liteRtServerManager-VBY4XRRI.js 0 B -2.08 kB (removed) 🏆
./bundle/oauth2-provider-ZD3NUCYT.js 0 B -9.12 kB (removed) 🏆
./bundle/chunk-7Z6FLNGL.js 659 kB +659 kB (new file) 🆕
./bundle/chunk-BIRSWE6N.js 19.5 kB +19.5 kB (new file) 🆕
./bundle/chunk-D7UNEA2Y.js 12.5 kB +12.5 kB (new file) 🆕
./bundle/chunk-IGYGNGNU.js 2.78 MB +2.78 MB (new file) 🆕
./bundle/chunk-LBJG5TJ3.js 49.2 kB +49.2 kB (new file) 🆕
./bundle/chunk-PHIQEQ46.js 3.77 kB +3.77 kB (new file) 🆕
./bundle/chunk-QJWFA2X4.js 3.43 kB +3.43 kB (new file) 🆕
./bundle/chunk-WRNUIVBB.js 16.6 MB +16.6 MB (new file) 🆕
./bundle/core-FF2VNGVN.js 49.2 kB +49.2 kB (new file) 🆕
./bundle/devtoolsService-KE35PUQW.js 28 kB +28 kB (new file) 🆕
./bundle/gemini-BZK7HLPB.js 585 kB +585 kB (new file) 🆕
./bundle/interactiveCli-PTFMPBXM.js 1.3 MB +1.3 MB (new file) 🆕
./bundle/liteRtServerManager-WZKTTHGR.js 2.08 kB +2.08 kB (new file) 🆕
./bundle/oauth2-provider-WRGLFVDL.js 9.12 kB +9.12 kB (new file) 🆕
ℹ️ View Unchanged
Filename Size Change
./bundle/bundled/third_party/index.js 8 MB 0 B
./bundle/chunk-34MYV7JD.js 2.45 kB 0 B
./bundle/chunk-5AUYMPVF.js 858 B 0 B
./bundle/chunk-5PS3AYFU.js 1.18 kB 0 B
./bundle/chunk-664ZODQF.js 124 kB 0 B
./bundle/chunk-CTHYVDCX.js 39.8 kB 0 B
./bundle/chunk-DAHVX5MI.js 206 kB 0 B
./bundle/chunk-IUUIT4SU.js 56.5 kB 0 B
./bundle/cleanup-SGQML4IY.js 0 B -902 B (removed) 🏆
./bundle/devtools-36NN55EP.js 696 kB 0 B
./bundle/dist-JYLQM7LS.js 373 B 0 B
./bundle/events-XB7DADIJ.js 418 B 0 B
./bundle/examples/hooks/scripts/on-start.js 188 B 0 B
./bundle/examples/mcp-server/example.js 1.43 kB 0 B
./bundle/gemini.js 5.07 kB 0 B
./bundle/getMachineId-bsd-TXG52NKR.js 1.55 kB 0 B
./bundle/getMachineId-darwin-7OE4DDZ6.js 1.55 kB 0 B
./bundle/getMachineId-linux-SHIFKOOX.js 1.34 kB 0 B
./bundle/getMachineId-unsupported-5U5DOEYY.js 1.06 kB 0 B
./bundle/getMachineId-win-6KLLGOI4.js 1.72 kB 0 B
./bundle/multipart-parser-KPBZEGQU.js 11.7 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/client/main.js 222 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/_client-assets.js 229 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/index.js 13.4 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
./bundle/src-QVCVGIUX.js 47 kB 0 B
./bundle/start-TXOVET7R.js 0 B -622 B (removed) 🏆
./bundle/tree-sitter-7U6MW5PS.js 274 kB 0 B
./bundle/tree-sitter-bash-34ZGLXVX.js 1.84 MB 0 B
./bundle/cleanup-HPD6PF6J.js 902 B +902 B (new file) 🆕
./bundle/start-FH7RITLG.js 622 B +622 B (new file) 🆕

compressed-size-action

@adamfweidman
adamfweidman force-pushed the agent-session/remote-invocation branch from 927dc8d to 80e1c75 Compare May 18, 2026 14:19
@adamfweidman
adamfweidman force-pushed the agent-session/agent-tool branch from 23c943a to 491e1e4 Compare May 18, 2026 14:19
@adamfweidman
adamfweidman force-pushed the agent-session/agent-tool branch from 491e1e4 to ab441fa Compare May 18, 2026 15:14
@adamfweidman
adamfweidman force-pushed the agent-session/remote-invocation branch from 78ccdb8 to 9901f6f Compare May 18, 2026 18:46
@adamfweidman
adamfweidman force-pushed the agent-session/agent-tool branch from ab441fa to 609ee82 Compare May 18, 2026 18:47
@adamfweidman
adamfweidman force-pushed the agent-session/remote-invocation branch from 9901f6f to abe9fd8 Compare May 18, 2026 19:05
@adamfweidman
adamfweidman force-pushed the agent-session/agent-tool branch from 609ee82 to 23ab766 Compare May 18, 2026 19:07
@adamfweidman
adamfweidman force-pushed the agent-session/remote-invocation branch from abe9fd8 to 0beb5ea Compare May 18, 2026 19:15
@adamfweidman
adamfweidman force-pushed the agent-session/agent-tool branch from 23ab766 to 6ca7b26 Compare May 18, 2026 19:18
@adamfweidman
adamfweidman force-pushed the agent-session/remote-invocation branch from 0beb5ea to 14f14f5 Compare May 18, 2026 20:26
@adamfweidman
adamfweidman force-pushed the agent-session/agent-tool branch from 6ca7b26 to a983202 Compare May 18, 2026 20:31
Base automatically changed from agent-session/remote-invocation to main May 19, 2026 14:37
adamfweidman and others added 9 commits May 19, 2026 11:47
…ure flag

Add agentSessionSubagentEnabled setting under experimental.adk that
routes subagent invocations through LocalSessionInvocation and
RemoteSessionInvocation instead of legacy executors. When disabled
(default), all behavior is unchanged.

- Add agentSessionSubagentEnabled to ADKSettings, Config, and settings schema
- Thread onAgentEvent callback through AgentTool → DelegateInvocation
- Route local/remote agents to session invocations when flag is enabled
- Browser agent always uses BrowserAgentInvocation regardless of flag
- Copy local protocol files needed for the session invocation path
@adamfweidman
adamfweidman force-pushed the agent-session/agent-tool branch from 6a29749 to 2308d4c Compare May 19, 2026 16:14

@jacob314 jacob314 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

lgtm

@adamfweidman
adamfweidman added this pull request to the merge queue May 19, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks May 19, 2026
@adamfweidman
adamfweidman added this pull request to the merge queue May 19, 2026
Merged via the queue into main with commit c4758ba May 19, 2026
29 checks passed
@adamfweidman
adamfweidman deleted the agent-session/agent-tool branch May 19, 2026 17:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/m A medium sized PR status/need-issue Pull requests that need to have an associated issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants