Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/core/subagents.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 3 additions & 1 deletion packages/core/src/agents/agentLoader.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -237,7 +238,8 @@ Body`);
},
},
runConfig: {
maxTimeMinutes: 5,
maxTimeMinutes: DEFAULT_MAX_TIME_MINUTES,
maxTurns: DEFAULT_MAX_TURNS,
},
inputConfig: {
inputSchema: {
Expand Down
10 changes: 7 additions & 3 deletions packages/core/src/agents/agentLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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
? {
Expand Down
26 changes: 20 additions & 6 deletions packages/core/src/agents/local-executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -406,7 +411,8 @@ 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 timeoutController = new AbortController();
const timeoutId = setTimeout(
() => timeoutController.abort(new Error('Agent timed out.')),
Expand Down Expand Up @@ -499,13 +505,18 @@ 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.`;
const actualMaxTime =
this.definition.runConfig.maxTimeMinutes ??
DEFAULT_MAX_TIME_MINUTES;
finalResult = `Agent timed out after ${actualMaxTime} minutes.`;
Comment thread
abhipatel12 marked this conversation as resolved.
Outdated
this.emitActivity('ERROR', {
error: finalResult,
context: 'timeout',
});
} else if (terminateReason === AgentTerminateMode.MAX_TURNS) {
finalResult = `Agent reached max turns limit (${this.definition.runConfig.maxTurns}).`;
const actualMaxTurns =
this.definition.runConfig.maxTurns ?? DEFAULT_MAX_TURNS;
finalResult = `Agent reached max turns limit (${actualMaxTurns}).`;
this.emitActivity('ERROR', {
error: finalResult,
context: 'max_turns',
Expand Down Expand Up @@ -569,7 +580,9 @@ export class LocalAgentExecutor<TOutput extends z.ZodTypeAny> {
}

// Recovery failed or wasn't possible
finalResult = `Agent timed out after ${this.definition.runConfig.maxTimeMinutes} minutes.`;
const actualMaxTime =
this.definition.runConfig.maxTimeMinutes ?? DEFAULT_MAX_TIME_MINUTES;
finalResult = `Agent timed out after ${actualMaxTime} minutes.`;
Comment thread
abhipatel12 marked this conversation as resolved.
Outdated
this.emitActivity('ERROR', {
error: finalResult,
context: 'timeout',
Expand Down Expand Up @@ -1165,7 +1178,8 @@ Important Rules:
): AgentTerminateMode | null {
const { runConfig } = this.definition;

if (runConfig.maxTurns && turnCounter >= runConfig.maxTurns) {
const maxTurns = runConfig.maxTurns ?? DEFAULT_MAX_TURNS;
if (turnCounter >= maxTurns) {
return AgentTerminateMode.MAX_TURNS;
}

Expand Down
20 changes: 18 additions & 2 deletions packages/core/src/agents/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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. */
/**
* The maximum execution time for the agent in minutes.
* If not specified, defaults to DEFAULT_MAX_TIME_MINUTES (5).
*/
maxTimeMinutes: number;
Comment thread
abhipatel12 marked this conversation as resolved.
Outdated
/** The maximum number of conversational turns. */
/**
* The maximum number of conversational turns.
* If not specified, defaults to DEFAULT_MAX_TURNS (15).
*/
maxTurns?: number;
}
Loading