diff --git a/src/tools/descriptions/Task.md b/src/tools/descriptions/Task.md index 02ca1e7..a9727ff 100644 --- a/src/tools/descriptions/Task.md +++ b/src/tools/descriptions/Task.md @@ -6,12 +6,22 @@ The Task tool launches specialized agents (subprocesses) that autonomously handl ## Usage -When using the Task tool, you must specify: +The Task tool supports two commands: + +### Run (default) +Launch a subagent to perform a task. Parameters: - **subagent_type**: Which specialized agent to use (see Available Agents section) - **prompt**: Detailed, self-contained instructions for the agent (agents cannot ask questions mid-execution) - **description**: Short 3-5 word summary for tracking - **model** (optional): Override the model for this agent +### Refresh +Re-scan the `.letta/agents/` directories to discover new or updated custom subagents: +```typescript +Task({ command: "refresh" }) +``` +Use this after creating or modifying custom subagent definitions. + ## When to use this tool: - **Codebase exploration**: Use when you need to search for files, understand code structure, or find specific patterns diff --git a/src/tools/impl/Task.ts b/src/tools/impl/Task.ts index 967c077..66b5ecc 100644 --- a/src/tools/impl/Task.ts +++ b/src/tools/impl/Task.ts @@ -5,7 +5,11 @@ * Supports both built-in subagent types and custom subagents defined in .letta/agents/. */ -import { getAllSubagentConfigs } from "../../agent/subagents"; +import { + clearSubagentConfigCache, + discoverSubagents, + getAllSubagentConfigs, +} from "../../agent/subagents"; import { spawnSubagent } from "../../agent/subagents/manager"; import { completeSubagent, @@ -15,9 +19,10 @@ import { import { validateRequiredParams } from "./validation"; interface TaskArgs { - subagent_type: string; - prompt: string; - description: string; + command?: "run" | "refresh"; + subagent_type?: string; + prompt?: string; + description?: string; model?: string; toolCallId?: string; // Injected by executeTool for linking subagent to parent tool call signal?: AbortSignal; // Injected by executeTool for interruption handling @@ -27,15 +32,45 @@ interface TaskArgs { * Task tool - Launch a specialized subagent to handle complex tasks */ export async function task(args: TaskArgs): Promise { - // Validate required parameters + const { command = "run", model, toolCallId, signal } = args; + + // Handle refresh command - re-discover subagents from .letta/agents/ directories + if (command === "refresh") { + // Clear the cache to force re-discovery + clearSubagentConfigCache(); + + // Discover subagents from global and project directories + const { subagents, errors } = await discoverSubagents(); + + // Get all configs (builtins + discovered) to report accurate count + const allConfigs = await getAllSubagentConfigs(); + const totalCount = Object.keys(allConfigs).length; + const customCount = subagents.length; + + // Log any errors + if (errors.length > 0) { + for (const error of errors) { + console.warn( + `Subagent discovery error: ${error.path}: ${error.message}`, + ); + } + } + + const errorSuffix = errors.length > 0 ? `, ${errors.length} error(s)` : ""; + return `Refreshed subagents list: found ${totalCount} total (${customCount} custom)${errorSuffix}`; + } + + // For run command, validate required parameters validateRequiredParams( args, ["subagent_type", "prompt", "description"], "Task", ); - const { subagent_type, prompt, description, model, toolCallId, signal } = - args; + // Extract validated params (guaranteed to exist after validateRequiredParams) + const subagent_type = args.subagent_type as string; + const prompt = args.prompt as string; + const description = args.description as string; // Get all available subagent configs (built-in + custom) const allConfigs = await getAllSubagentConfigs(); diff --git a/src/tools/schemas/Task.json b/src/tools/schemas/Task.json index 4ef705b..738ab62 100644 --- a/src/tools/schemas/Task.json +++ b/src/tools/schemas/Task.json @@ -1,24 +1,28 @@ { "type": "object", "properties": { + "command": { + "type": "string", + "enum": ["run", "refresh"], + "description": "The operation to perform: \"run\" to spawn a subagent (default), \"refresh\" to re-scan the .letta/agents/ directories and update the available subagents list" + }, "subagent_type": { "type": "string", - "description": "The type of specialized agent to use. Available agents are discovered from .letta/agents/ directory." + "description": "The type of specialized agent to use. Available agents are discovered from .letta/agents/ directory. Required for \"run\" command." }, "prompt": { "type": "string", - "description": "The task for the agent to perform" + "description": "The task for the agent to perform. Required for \"run\" command." }, "description": { "type": "string", - "description": "A short (3-5 word) description of the task" + "description": "A short (3-5 word) description of the task. Required for \"run\" command." }, "model": { "type": "string", "description": "Optional model to use for this agent. If not specified, uses the recommended model for the subagent type." } }, - "required": ["subagent_type", "prompt", "description"], "additionalProperties": false, "$schema": "http://json-schema.org/draft-07/schema#" }