feat: 将 Agents/Teams 工具纳入 Tool Search 按需发现

将 TeamCreate、TeamDelete、SendMessage 从 CORE_TOOLS 移除,
使其成为 deferred 工具,通过 ToolSearch 按需发现以减少 context token。
swarm 模式下 SendMessage 保持 always loaded,TeamCreate/TeamDelete
在 swarm 未启用时调用返回启用提示。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
claude-code-best
2026-05-09 15:45:20 +08:00
parent 3ac866be98
commit af0d7dc851
7 changed files with 36 additions and 18 deletions

View File

@@ -553,7 +553,8 @@ async function handlePlanRejection(
export const SendMessageTool: Tool<InputSchema, SendMessageToolOutput> =
buildTool({
name: SEND_MESSAGE_TOOL_NAME,
searchHint: 'send messages to agent teammates (swarm protocol)',
searchHint:
'send message to teammate agent, broadcast, inter-agent communication, swarm messaging, agent coordination',
maxResultSizeChars: 100_000,
userFacingName() {
@@ -564,9 +565,10 @@ export const SendMessageTool: Tool<InputSchema, SendMessageToolOutput> =
return inputSchema()
},
shouldDefer: true,
alwaysLoad: isAgentSwarmsEnabled(),
isEnabled() {
return isAgentSwarmsEnabled()
return true
},
isReadOnly(input) {

View File

@@ -73,7 +73,8 @@ function generateUniqueTeamName(providedName: string): string {
export const TeamCreateTool: Tool<InputSchema, Output> = buildTool({
name: TEAM_CREATE_TOOL_NAME,
searchHint: 'create a multi-agent swarm team',
searchHint:
'create multi-agent swarm team, collaborate, parallel agents, task distribution, agent coordination, team management',
maxResultSizeChars: 100_000,
shouldDefer: true,
@@ -86,7 +87,7 @@ export const TeamCreateTool: Tool<InputSchema, Output> = buildTool({
},
isEnabled() {
return isAgentSwarmsEnabled()
return true
},
toAutoClassifierInput(input) {
@@ -126,6 +127,12 @@ export const TeamCreateTool: Tool<InputSchema, Output> = buildTool({
},
async call(input, context) {
if (!isAgentSwarmsEnabled()) {
throw new Error(
'Agent Teams 功能未启用。请确保未设置 CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS_DISABLED 环境变量。',
)
}
const { setAppState, getAppState } = context
const { team_name, description: _description, agent_type } = input

View File

@@ -50,7 +50,8 @@ export type Input = z.infer<InputSchema>
export const TeamDeleteTool: Tool<InputSchema, Output> = buildTool({
name: TEAM_DELETE_TOOL_NAME,
searchHint: 'disband a swarm team and clean up',
searchHint:
'disband delete swarm team cleanup, remove team, end team collaboration, cleanup team resources',
maxResultSizeChars: 100_000,
shouldDefer: true,
@@ -63,7 +64,7 @@ export const TeamDeleteTool: Tool<InputSchema, Output> = buildTool({
},
isEnabled() {
return isAgentSwarmsEnabled()
return true
},
async description() {
@@ -88,6 +89,12 @@ export const TeamDeleteTool: Tool<InputSchema, Output> = buildTool({
},
async call(input, context) {
if (!isAgentSwarmsEnabled()) {
throw new Error(
'Agent Teams 功能未启用。请确保未设置 CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS_DISABLED 环境变量。',
)
}
const { setAppState, getAppState } = context
const appState = getAppState()
const teamName = appState.teamContext?.teamName

View File

@@ -6,7 +6,7 @@ export { TOOL_SEARCH_TOOL_NAME } from './constants.js'
import { TOOL_SEARCH_TOOL_NAME } from './constants.js'
const PROMPT_HEAD = `Search for deferred tools by name or keyword. LOW PRIORITY — only use this tool when no core tool can accomplish the task. Core tools (Read, Edit, Write, Bash, Glob, Grep, Agent, WebFetch, WebSearch, Skill) are always available and should be used directly. This tool is only for discovering additional capabilities like MCP tools, cron scheduling, worktree management, etc.
const PROMPT_HEAD = `Search for deferred tools by name or keyword. LOW PRIORITY — only use this tool when no core tool can accomplish the task. Core tools (Read, Edit, Write, Bash, Glob, Grep, Agent, WebFetch, WebSearch, Skill) are always available and should be used directly. This tool is for discovering additional capabilities like MCP tools, cron scheduling, worktree management, agent teams (TeamCreate, TeamDelete, SendMessage), etc.
`

View File

@@ -52,8 +52,8 @@ function makeTool(overrides: Partial<MockTool> = {}): MockTool {
describe('CORE_TOOLS', () => {
test('contains expected number of tools', () => {
// 7 SHELL_TOOL_NAMES + 22 independent tool names
expect(CORE_TOOLS.size).toBeGreaterThanOrEqual(29)
// 7 SHELL_TOOL_NAMES + 19 independent tool names
expect(CORE_TOOLS.size).toBeGreaterThanOrEqual(26)
})
test('contains key core tool names', () => {
@@ -72,8 +72,6 @@ describe('CORE_TOOLS', () => {
'Sleep',
'LSP',
'Skill',
'TeamCreate',
'TeamDelete',
'TaskCreate',
'TaskGet',
'TaskUpdate',
@@ -124,6 +122,15 @@ describe('isDeferredTool', () => {
expect(isDeferredTool(tool as never)).toBe(true)
})
test('returns true for agent/team tools (TeamCreate, TeamDelete, SendMessage)', () => {
for (const name of ['TeamCreate', 'TeamDelete', 'SendMessage']) {
const tool = makeTool({ name })
expect(isDeferredTool(tool as never), `${name} should be deferred`).toBe(
true,
)
}
})
test('returns true for MCP tools', () => {
const tool = makeTool({ name: 'mcp__server__action', isMcp: true })
expect(isDeferredTool(tool as never)).toBe(true)

View File

@@ -135,10 +135,6 @@ export const CORE_TOOLS = new Set([
// Agent & interaction
AGENT_TOOL_NAME, // 'Agent'
ASK_USER_QUESTION_TOOL_NAME, // 'AskUserQuestion'
SEND_MESSAGE_TOOL_NAME, // 'SendMessage'
// Team (swarm)
TEAM_CREATE_TOOL_NAME, // 'TeamCreate'
TEAM_DELETE_TOOL_NAME, // 'TeamDelete'
// Task management
TASK_OUTPUT_TOOL_NAME, // 'TaskOutput'
TASK_STOP_TOOL_NAME, // 'TaskStop'

View File

@@ -247,9 +247,8 @@ export function getAllBaseTools(): Tools {
...(isWorktreeModeEnabled() ? [EnterWorktreeTool, ExitWorktreeTool] : []),
getSendMessageTool(),
...(ListPeersTool ? [ListPeersTool] : []),
...(isAgentSwarmsEnabled()
? [getTeamCreateTool(), getTeamDeleteTool()]
: []),
getTeamCreateTool(),
getTeamDeleteTool(),
...(VerifyPlanExecutionTool ? [VerifyPlanExecutionTool] : []),
...(process.env.USER_TYPE === 'ant' && REPLTool ? [REPLTool] : []),
...(WorkflowTool ? [WorkflowTool] : []),