mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-13 07:30:52 -07:00
feat(core): add default execution limits for subagents (#18274)
This commit is contained in:
@@ -146,8 +146,8 @@ it yourself; just report it.
|
||||
| `tools` | array | No | List of tool names this agent can use. If omitted, it may have access to a default set. |
|
||||
| `model` | string | No | Specific model to use (e.g., `gemini-2.5-pro`). Defaults to `inherit` (uses the main session model). |
|
||||
| `temperature` | number | No | Model temperature (0.0 - 2.0). |
|
||||
| `max_turns` | number | No | Maximum number of conversation turns allowed for this agent before it must return. |
|
||||
| `timeout_mins` | number | No | Maximum execution time in minutes. |
|
||||
| `max_turns` | number | No | Maximum number of conversation turns allowed for this agent before it must return. Defaults to `15`. |
|
||||
| `timeout_mins` | number | No | Maximum execution time in minutes. Defaults to `5`. |
|
||||
|
||||
### Optimizing your sub-agent
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
} from './agentLoader.js';
|
||||
import { GEMINI_MODEL_ALIAS_PRO } from '../config/models.js';
|
||||
import type { LocalAgentDefinition } from './types.js';
|
||||
import { DEFAULT_MAX_TIME_MINUTES, DEFAULT_MAX_TURNS } from './types.js';
|
||||
|
||||
describe('loader', () => {
|
||||
let tempDir: string;
|
||||
@@ -237,7 +238,8 @@ Body`);
|
||||
},
|
||||
},
|
||||
runConfig: {
|
||||
maxTimeMinutes: 5,
|
||||
maxTimeMinutes: DEFAULT_MAX_TIME_MINUTES,
|
||||
maxTurns: DEFAULT_MAX_TURNS,
|
||||
},
|
||||
inputConfig: {
|
||||
inputSchema: {
|
||||
|
||||
@@ -10,7 +10,11 @@ import { type Dirent } from 'node:fs';
|
||||
import * as path from 'node:path';
|
||||
import * as crypto from 'node:crypto';
|
||||
import { z } from 'zod';
|
||||
import type { AgentDefinition } from './types.js';
|
||||
import {
|
||||
type AgentDefinition,
|
||||
DEFAULT_MAX_TURNS,
|
||||
DEFAULT_MAX_TIME_MINUTES,
|
||||
} from './types.js';
|
||||
import { isValidToolName } from '../tools/tool-names.js';
|
||||
import { FRONTMATTER_REGEX } from '../skills/skillLoader.js';
|
||||
import { getErrorMessage } from '../utils/errors.js';
|
||||
@@ -290,8 +294,8 @@ export function markdownToAgentDefinition(
|
||||
},
|
||||
},
|
||||
runConfig: {
|
||||
maxTurns: markdown.max_turns,
|
||||
maxTimeMinutes: markdown.timeout_mins || 5,
|
||||
maxTurns: markdown.max_turns ?? DEFAULT_MAX_TURNS,
|
||||
maxTimeMinutes: markdown.timeout_mins ?? DEFAULT_MAX_TIME_MINUTES,
|
||||
},
|
||||
toolConfig: markdown.tools
|
||||
? {
|
||||
|
||||
@@ -41,7 +41,12 @@ import type {
|
||||
OutputObject,
|
||||
SubagentActivityEvent,
|
||||
} from './types.js';
|
||||
import { AgentTerminateMode, DEFAULT_QUERY_STRING } from './types.js';
|
||||
import {
|
||||
AgentTerminateMode,
|
||||
DEFAULT_QUERY_STRING,
|
||||
DEFAULT_MAX_TURNS,
|
||||
DEFAULT_MAX_TIME_MINUTES,
|
||||
} from './types.js';
|
||||
import { templateString } from './utils.js';
|
||||
import { DEFAULT_GEMINI_MODEL, isAutoModel } from '../config/models.js';
|
||||
import type { RoutingContext } from '../routing/routingStrategy.js';
|
||||
@@ -406,7 +411,10 @@ export class LocalAgentExecutor<TOutput extends z.ZodTypeAny> {
|
||||
let terminateReason: AgentTerminateMode = AgentTerminateMode.ERROR;
|
||||
let finalResult: string | null = null;
|
||||
|
||||
const { maxTimeMinutes } = this.definition.runConfig;
|
||||
const maxTimeMinutes =
|
||||
this.definition.runConfig.maxTimeMinutes ?? DEFAULT_MAX_TIME_MINUTES;
|
||||
const maxTurns = this.definition.runConfig.maxTurns ?? DEFAULT_MAX_TURNS;
|
||||
|
||||
const timeoutController = new AbortController();
|
||||
const timeoutId = setTimeout(
|
||||
() => timeoutController.abort(new Error('Agent timed out.')),
|
||||
@@ -441,7 +449,7 @@ export class LocalAgentExecutor<TOutput extends z.ZodTypeAny> {
|
||||
|
||||
while (true) {
|
||||
// Check for termination conditions like max turns.
|
||||
const reason = this.checkTermination(startTime, turnCounter);
|
||||
const reason = this.checkTermination(turnCounter, maxTurns);
|
||||
if (reason) {
|
||||
terminateReason = reason;
|
||||
break;
|
||||
@@ -499,13 +507,13 @@ export class LocalAgentExecutor<TOutput extends z.ZodTypeAny> {
|
||||
} else {
|
||||
// Recovery Failed. Set the final error message based on the *original* reason.
|
||||
if (terminateReason === AgentTerminateMode.TIMEOUT) {
|
||||
finalResult = `Agent timed out after ${this.definition.runConfig.maxTimeMinutes} minutes.`;
|
||||
finalResult = `Agent timed out after ${maxTimeMinutes} minutes.`;
|
||||
this.emitActivity('ERROR', {
|
||||
error: finalResult,
|
||||
context: 'timeout',
|
||||
});
|
||||
} else if (terminateReason === AgentTerminateMode.MAX_TURNS) {
|
||||
finalResult = `Agent reached max turns limit (${this.definition.runConfig.maxTurns}).`;
|
||||
finalResult = `Agent reached max turns limit (${maxTurns}).`;
|
||||
this.emitActivity('ERROR', {
|
||||
error: finalResult,
|
||||
context: 'max_turns',
|
||||
@@ -569,7 +577,7 @@ export class LocalAgentExecutor<TOutput extends z.ZodTypeAny> {
|
||||
}
|
||||
|
||||
// Recovery failed or wasn't possible
|
||||
finalResult = `Agent timed out after ${this.definition.runConfig.maxTimeMinutes} minutes.`;
|
||||
finalResult = `Agent timed out after ${maxTimeMinutes} minutes.`;
|
||||
this.emitActivity('ERROR', {
|
||||
error: finalResult,
|
||||
context: 'timeout',
|
||||
@@ -1160,12 +1168,10 @@ Important Rules:
|
||||
* @returns The reason for termination, or `null` if execution can continue.
|
||||
*/
|
||||
private checkTermination(
|
||||
startTime: number,
|
||||
turnCounter: number,
|
||||
maxTurns: number,
|
||||
): AgentTerminateMode | null {
|
||||
const { runConfig } = this.definition;
|
||||
|
||||
if (runConfig.maxTurns && turnCounter >= runConfig.maxTurns) {
|
||||
if (turnCounter >= maxTurns) {
|
||||
return AgentTerminateMode.MAX_TURNS;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,16 @@ export interface OutputObject {
|
||||
*/
|
||||
export const DEFAULT_QUERY_STRING = 'Get Started!';
|
||||
|
||||
/**
|
||||
* The default maximum number of conversational turns for an agent.
|
||||
*/
|
||||
export const DEFAULT_MAX_TURNS = 15;
|
||||
|
||||
/**
|
||||
* The default maximum execution time for an agent in minutes.
|
||||
*/
|
||||
export const DEFAULT_MAX_TIME_MINUTES = 5;
|
||||
|
||||
/**
|
||||
* Represents the validated input parameters passed to an agent upon invocation.
|
||||
* Used primarily for templating the system prompt. (Replaces ContextState)
|
||||
@@ -183,8 +193,14 @@ export interface OutputConfig<T extends z.ZodTypeAny> {
|
||||
* Configures the execution environment and constraints for the agent.
|
||||
*/
|
||||
export interface RunConfig {
|
||||
/** The maximum execution time for the agent in minutes. */
|
||||
maxTimeMinutes: number;
|
||||
/** The maximum number of conversational turns. */
|
||||
/**
|
||||
* The maximum execution time for the agent in minutes.
|
||||
* If not specified, defaults to DEFAULT_MAX_TIME_MINUTES (5).
|
||||
*/
|
||||
maxTimeMinutes?: number;
|
||||
/**
|
||||
* The maximum number of conversational turns.
|
||||
* If not specified, defaults to DEFAULT_MAX_TURNS (15).
|
||||
*/
|
||||
maxTurns?: number;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user