Skip to content

Allow agents to call agents - #28738

Open
akash-manna-sky wants to merge 3 commits into
google-gemini:mainfrom
akash-manna-sky:issue-22092
Open

Allow agents to call agents#28738
akash-manna-sky wants to merge 3 commits into
google-gemini:mainfrom
akash-manna-sky:issue-22092

Conversation

@akash-manna-sky

Copy link
Copy Markdown

Summary

Allow agents to call agents

Fixes #22092

Details

Fixes #22092 by letting subagents delegate to other subagents — or recurse into themselves — via their tools: frontmatter. This was blocked twice over: the agent loader rejected agent names as Invalid tool name, and the executor stripped every Kind.Agent tool from subagent registries, so even a name that passed validation would have had no effect. isValidToolName() now takes an allowAgentNames option (checked after the MCP branch, so malformed names like mcp__tool stay rejected), and the executor resolves each tools: entry through the tool registry, then the agent registry, then warns instead of silently dropping it. Resolved agents get an invoke_agent tool whose agent_name is constrained to a JSON-schema enum of exactly those agents. A bare agent name grants that one agent, agent_* or invoke_agent grants all of them, and a self-reference enables recursion; * and an omitted tools: deliberately grant no agent access, so no existing definition changes behaviour — notably generalist-agent, whose list is built from getAllToolNames(). Recursion is bounded three ways: an agent at max depth is never handed the tool, AgentTool.createInvocation rejects nesting past MAX_AGENT_DEPTH = 3, and each level keeps its own max_turns/timeout_mins. Docs updated; 26 tests added across tool-names, agentLoader, agent-tool and local-executor, with the two pre-existing recursion tests still passing unmodified. Note that this introduces a deferred import cycle (local-executoragent-toollocal-invocation), which ESM resolves correctly and the tests exercise in both load orders — happy to switch to a dynamic import if preferred.

Related Issues

How to Validate

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
    • Windows
      • npm run
      • npx
      • Docker
    • Linux
      • npm run
      • npx
      • Docker

@github-actions github-actions Bot added the size/l A large sized PR label Aug 8, 2026
@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown

📊 PR Size: size/L

  • Lines changed: 735
  • Additions: +705
  • Deletions: -30
  • Files changed: 10

@akash-manna-sky
akash-manna-sky marked this pull request as ready for review August 8, 2026 12:32
@akash-manna-sky
akash-manna-sky requested review from a team as code owners August 8, 2026 12:32
@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 hierarchical agent delegation, allowing subagents to invoke other subagents. This functionality is opt-in, requiring explicit configuration in the agent's frontmatter. The implementation includes robust recursion protection, ensuring that agent nesting does not exceed a predefined depth, and maintains strict validation to prevent unauthorized tool or agent access.

Highlights

  • Agent Delegation: Subagents can now delegate tasks to other subagents or recurse into themselves by explicitly listing them in their tools frontmatter.
  • Recursion Control: Agent nesting is now strictly bounded to a maximum depth of 3 levels to prevent infinite loops and excessive resource usage.
  • Configuration Validation: The agent loader and tool registry have been updated to support agent names in tool configurations, with improved validation to ensure only registered agents can be invoked.
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.

@github-actions

github-actions Bot commented Aug 8, 2026

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.

@gemini-cli gemini-cli Bot added priority/p2 Important but can be addressed in a future release. area/agent Issues related to Core Agent, Tools, Memory, Sub-Agents, Hooks, Agent Quality help wanted We will accept PRs from all issues marked as "help wanted". Thanks for your support! labels Aug 8, 2026

@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 subagent delegation and bounded recursion (capped at 3 levels) to prevent infinite loops. It updates the configuration schema, tool validation, and executor logic to allow agents to explicitly opt-in to calling other agents. The code reviewer identified a critical security vulnerability in local-executor.ts where nested subagents could bypass tool isolation by inheriting the grandparent's unrestricted tool registry instead of the parent's restricted registry. To address this, the reviewer suggested passing the current agent's isolated registries and message bus to the nested context, along with a corresponding test update.

Comment on lines +312 to +323
const nestedContext: AgentLoopContext = {
config: context.config,
promptId: context.promptId,
parentSessionId: context.parentSessionId,
toolRegistry: context.toolRegistry,
promptRegistry: context.promptRegistry,
resourceRegistry: context.resourceRegistry,
messageBus: context.messageBus,
geminiClient: context.geminiClient,
sandboxManager: context.sandboxManager,
agentDepth: nestedDepth,
};

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.

security-critical critical

Using the grandparent's registries (context.toolRegistry, etc.) for the child agent's nestedContext creates a critical security vulnerability and tool isolation bypass. If a restricted subagent invokes another subagent, the child subagent will inherit the grandparent's unrestricted tool registry instead of the parent's restricted registry, allowing privilege escalation. The nestedContext must use the current agent's isolated registries (agentToolRegistry, agentPromptRegistry, agentResourceRegistry) and message bus (subagentMessageBus) to preserve tool isolation boundaries.

Suggested change
const nestedContext: AgentLoopContext = {
config: context.config,
promptId: context.promptId,
parentSessionId: context.parentSessionId,
toolRegistry: context.toolRegistry,
promptRegistry: context.promptRegistry,
resourceRegistry: context.resourceRegistry,
messageBus: context.messageBus,
geminiClient: context.geminiClient,
sandboxManager: context.sandboxManager,
agentDepth: nestedDepth,
};
const nestedContext: AgentLoopContext = {
config: context.config,
promptId: context.promptId,
parentSessionId: context.parentSessionId,
toolRegistry: agentToolRegistry,
promptRegistry: agentPromptRegistry,
resourceRegistry: agentResourceRegistry,
messageBus: subagentMessageBus,
geminiClient: context.geminiClient,
sandboxManager: context.sandboxManager,
agentDepth: nestedDepth,
};

Comment on lines +996 to +1016
it('should hand the nested agent tool an incremented depth', async () => {
stubAgentRegistry(['code-reviewer']);

const definition = createTestDefinition([
LS_TOOL_NAME,
'code-reviewer',
]);
const executor = await LocalAgentExecutor.create(
definition,
mockConfig,
onActivity,
);

const agentTool = executor['toolRegistry'].getTool(
AGENT_TOOL_NAME,
) as AgentTool;
const nestedContext = agentTool['context'];
expect(nestedContext.agentDepth).toBe(1);
expect(nestedContext.config).toBe(mockConfig);
expect(nestedContext.toolRegistry).toBe(parentToolRegistry);
});

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.

high

Update the test to assert that the nested context inherits the current agent's isolated tool registry (executor['toolRegistry']) instead of the grandparent's registry (parentToolRegistry), aligning with the security fix.

      it('should hand the nested agent tool an incremented depth', async () => {
        stubAgentRegistry(['code-reviewer']);

        const definition = createTestDefinition([
          LS_TOOL_NAME,
          'code-reviewer',
        ]);
        const executor = await LocalAgentExecutor.create(
          definition,
          mockConfig,
          onActivity,
        );

        const agentTool = executor['toolRegistry'].getTool(
          AGENT_TOOL_NAME,
        ) as AgentTool;
        const nestedContext = agentTool['context'];
        expect(nestedContext.agentDepth).toBe(1);
        expect(nestedContext.config).toBe(mockConfig);
        expect(nestedContext.toolRegistry).toBe(executor['toolRegistry']);
      });

@akash-manna-sky

Copy link
Copy Markdown
Author

Hi, @rnett Can you please review this pr? Thanks!

@akash-manna-sky

Copy link
Copy Markdown
Author

Hi @scidomino, can you please review the changes?

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 help wanted We will accept PRs from all issues marked as "help wanted". Thanks for your support! priority/p2 Important but can be addressed in a future release. size/l A large sized PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow agents to call agents

1 participant