Skip to main content
Glama

bulk_delete_agents

Remove multiple agents from the Letta MCP Server using filters for names, tags, or specific IDs. Identify agents with list_agents first. This permanent deletion action helps manage agent collections.

Instructions

Deletes multiple agents based on filter criteria (name or tags) or a specific list of IDs. Use list_agents first to identify agents to delete. WARNING: This action is permanent.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
agent_idsNoOptional: A specific list of agent IDs to delete.
agent_name_filterNoOptional: Filter agents to delete by name (exact match or substring, depending on API).
agent_tag_filterNoOptional: Filter agents to delete by tag(s). Provide a single tag or comma-separated list.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
failedNo
deletedYes
resultsNo
total_agentsYes

Implementation Reference

  • Core handler function that executes the bulk_delete_agents tool: validates input, lists matching agents using filters or IDs, deletes each via DELETE /agents/{id}, reports success/error per agent with summary.
    export async function handleBulkDeleteAgents(server, args) {
        // Require at least one filter criteria to prevent accidental mass deletion
        if (!args?.agent_name_filter && !args?.agent_tag_filter && !args?.agent_ids) {
            server.createErrorResponse(
                'Missing required argument: Provide agent_ids, agent_name_filter, or agent_tag_filter.',
            );
        }
    
        const nameFilter = args.agent_name_filter;
        const tagFilter = args.agent_tag_filter;
        const specificAgentIds = args.agent_ids; // Allow deleting a specific list of IDs
    
        const results = [];
        let agentsToDelete = [];
    
        try {
            const headers = server.getApiHeaders();
    
            // Step 1: Identify agents to delete
            if (specificAgentIds && Array.isArray(specificAgentIds) && specificAgentIds.length > 0) {
                // If a list of IDs is provided, use that directly
                logger.info(`Received specific list of ${specificAgentIds.length} agents to delete.`);
                // We need agent objects (at least with 'id' and 'name') for consistent reporting
                // Fetch details for each ID or use list_agents with multiple ID filter if supported
                // For simplicity, we'll just use the IDs for deletion and report only IDs
                agentsToDelete = specificAgentIds.map((id) => ({ id: id, name: `ID: ${id}` })); // Create placeholder objects
            } else {
                // Otherwise, list agents based on filters
                logger.info(`Listing agents with filter: name='${nameFilter}', tags='${tagFilter}'...`);
                const listParams = {};
                if (nameFilter) listParams.name = nameFilter;
                if (tagFilter) listParams.tags = tagFilter; // Adjust if API uses different param name
    
                const listResponse = await server.api.get('/agents/', { headers, params: listParams });
                agentsToDelete = listResponse.data; // Assuming response.data is an array of AgentState objects
    
                if (!Array.isArray(agentsToDelete) || agentsToDelete.length === 0) {
                    return {
                        content: [
                            {
                                type: 'text',
                                text: JSON.stringify({
                                    message: 'No agents found matching the specified filter.',
                                    results: [],
                                }),
                            },
                        ],
                    };
                }
                logger.info(`Found ${agentsToDelete.length} agents to delete.`);
            }
    
            // Step 2: Iterate and delete each agent
            for (const agent of agentsToDelete) {
                const agentId = agent.id;
                const encodedAgentId = encodeURIComponent(agentId);
                try {
                    logger.info(`Deleting agent ${agentId} (${agent.name})...`);
                    // Use the specific endpoint from the OpenAPI spec
                    await server.api.delete(`/agents/${encodedAgentId}`, { headers });
                    results.push({ agent_id: agentId, name: agent.name, status: 'success' });
                    logger.info(`Successfully deleted agent ${agentId}.`);
                } catch (deleteError) {
                    let errorMessage = `Failed to delete agent ${agentId} (${agent.name}): ${deleteError.message}`;
                    if (deleteError.response) {
                        errorMessage += ` (Status: ${deleteError.response.status}, Data: ${JSON.stringify(deleteError.response.data)})`;
                    }
                    logger.error(errorMessage);
                    results.push({
                        agent_id: agentId,
                        name: agent.name,
                        status: 'error',
                        error: errorMessage,
                    });
                }
            }
    
            // Step 3: Return summary of results
            const successCount = results.filter((r) => r.status === 'success').length;
            const errorCount = results.filter((r) => r.status === 'error').length;
    
            return {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify({
                            summary: {
                                total_agents: agentsToDelete.length,
                                success_count: successCount,
                                error_count: errorCount,
                            },
                            results: results,
                        }),
                    },
                ],
            };
        } catch (error) {
            // Handle errors during the list_agents call or unexpected issues
            logger.error('Error:', error.response?.data || error.message);
            server.createErrorResponse(`Failed during bulk delete operation: ${error.message}`);
        }
    }
  • Tool definition including name, description, and inputSchema for validation of arguments: agent_ids, agent_name_filter, agent_tag_filter.
    export const bulkDeleteAgentsDefinition = {
        name: 'bulk_delete_agents',
        description:
            'Deletes multiple agents based on filter criteria (name or tags) or a specific list of IDs. Use list_agents first to identify agents to delete. WARNING: This action is permanent.',
        inputSchema: {
            type: 'object',
            properties: {
                agent_ids: {
                    type: 'array',
                    items: { type: 'string' },
                    description: 'Optional: A specific list of agent IDs to delete.',
                },
                agent_name_filter: {
                    type: 'string',
                    description:
                        'Optional: Filter agents to delete by name (exact match or substring, depending on API).',
                },
                agent_tag_filter: {
                    type: 'string',
                    description:
                        'Optional: Filter agents to delete by tag(s). Provide a single tag or comma-separated list.',
                },
                // Could add more filters like project_id if needed
            },
            // Custom validation in the handler ensures at least one argument is provided
            required: [],
        },
    };
  • Handler dispatch registration: switch case in CallToolRequestSchema handler that routes 'bulk_delete_agents' calls to handleBulkDeleteAgents.
    case 'bulk_delete_agents':
        return handleBulkDeleteAgents(server, request.params.arguments);
  • Tool definition registration: inclusion of bulkDeleteAgentsDefinition in the allTools array used for ListToolsRequestSchema response.
    bulkDeleteAgentsDefinition,
  • Output schema defining structured response format for bulk_delete_agents: summary counts and per-agent results.
    bulk_delete_agents: {
        type: 'object',
        properties: {
            total_agents: { type: 'integer' },
            deleted: { type: 'integer' },
            failed: { type: 'integer' },
            results: {
                type: 'array',
                items: {
                    type: 'object',
                    properties: {
                        agent_id: { type: 'string' },
                        agent_name: { type: 'string' },
                        success: { type: 'boolean' },
                        error: { type: 'string' },
                    },
                    required: ['agent_id', 'success'],
                },
            },
        },
        required: ['total_agents', 'deleted'],
    },
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only provide a title, so the description carries the full burden. It discloses critical behavioral traits: the action is 'permanent' (destructive nature) and includes a 'WARNING' about irreversibility. However, it doesn't mention authentication needs, rate limits, or error handling, which could be useful additions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core action, followed by usage guidance and a critical warning. Every sentence earns its place: the first defines purpose, the second provides prerequisites, and the third highlights risks—all without redundancy or fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (destructive bulk operation) and the presence of an output schema (which handles return values), the description is complete enough. It covers purpose, usage, and risks, addressing key contextual needs without over-explaining parameters or outputs.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all three parameters thoroughly. The description adds minimal value beyond the schema by mentioning 'filter criteria (name or tags) or a specific list of IDs,' which is already implied in the schema. This meets the baseline for high schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific action ('Deletes multiple agents') and distinguishes it from sibling tools like 'delete_agent' (singular) and 'list_agents' (read-only). It specifies the resource ('agents') and the scope ('multiple'), making the purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly provides usage guidance: 'Use list_agents first to identify agents to delete.' This tells the agent when to use this tool (after identification) and references a specific alternative tool for preparation, which is optimal for sibling differentiation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/oculairmedia/Letta-MCP-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server