Skip to main content
Glama

bulk_attach_tool_to_agents

Attach a tool to multiple agents simultaneously by filtering them based on name or tags. Use this to efficiently manage tool assignments across your agent network in the Letta system.

Instructions

Attaches a specified tool to multiple agents based on filter criteria (name or tags). Use list_agents to find agents and list_mcp_tools_by_server or upload_tool to get tool IDs.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
tool_idYesThe ID of the tool to attach.
agent_name_filterNoOptional: Filter agents by name (exact match or substring, depending on API).
agent_tag_filterNoOptional: Filter agents by tag(s). Provide a single tag or comma-separated list.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultsNo
tool_idYes
total_agentsYes
failed_attachmentsNo
successful_attachmentsYes

Implementation Reference

  • Primary handler function implementing the bulk tool attachment logic: validates inputs, lists matching agents, attaches tool to each via API, handles errors per agent, returns summary with results.
    export async function handleBulkAttachToolToAgents(server, args) {
        if (!args?.tool_id) {
            server.createErrorResponse('Missing required argument: tool_id');
        }
        // Require at least one filter criteria
        if (!args?.agent_name_filter && !args?.agent_tag_filter) {
            server.createErrorResponse(
                'Missing required argument: Provide either agent_name_filter or agent_tag_filter.',
            );
        }
    
        const toolId = args.tool_id;
        const nameFilter = args.agent_name_filter;
        const tagFilter = args.agent_tag_filter; // Assuming API supports tag filtering for list_agents
    
        const results = [];
        let agentsToProcess = [];
    
        try {
            const headers = server.getApiHeaders();
    
            // Step 1: List agents based on filter criteria
            logger.info(
                `[bulk_attach_tool] Listing agents with filter: name='${nameFilter}', tags='${tagFilter}'...`,
            );
            const listParams = {};
            if (nameFilter) listParams.name = nameFilter; // Assuming API uses 'name' for filtering
            if (tagFilter) listParams.tags = tagFilter; // Assuming API uses 'tags' (might need adjustment based on actual API)
    
            const listResponse = await server.api.get('/agents/', { headers, params: listParams });
            agentsToProcess = listResponse.data; // Assuming response.data is an array of AgentState objects
    
            if (!Array.isArray(agentsToProcess) || agentsToProcess.length === 0) {
                return {
                    content: [
                        {
                            type: 'text',
                            text: JSON.stringify({
                                message: 'No agents found matching the specified filter.',
                                results: [],
                            }),
                        },
                    ],
                };
            }
            logger.info(`[bulk_attach_tool] Found ${agentsToProcess.length} agents to process.`);
    
            // Step 2: Iterate and attach tool to each agent
            const encodedToolId = encodeURIComponent(toolId);
            for (const agent of agentsToProcess) {
                const agentId = agent.id;
                const encodedAgentId = encodeURIComponent(agentId);
                try {
                    logger.info(`[bulk_attach_tool] Attaching tool ${toolId} to agent ${agentId}...`);
                    // Use the specific endpoint from the OpenAPI spec
                    await server.api.patch(
                        `/agents/${encodedAgentId}/tools/attach/${encodedToolId}`,
                        {},
                        { headers },
                    ); // PATCH often has empty body for attach/detach
                    results.push({ agent_id: agentId, name: agent.name, status: 'success' });
                    logger.info(
                        `[bulk_attach_tool] Successfully attached tool ${toolId} to agent ${agentId}.`,
                    );
                } catch (attachError) {
                    let errorMessage = `Failed to attach tool ${toolId} to agent ${agentId}: ${attachError.message}`;
                    if (attachError.response) {
                        errorMessage += ` (Status: ${attachError.response.status}, Data: ${JSON.stringify(attachError.response.data)})`;
                    }
                    logger.error(`[bulk_attach_tool] ${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: agentsToProcess.length,
                                success_count: successCount,
                                error_count: errorCount,
                            },
                            results: results,
                        }),
                    },
                ],
            };
        } catch (error) {
            // Handle errors during the list_agents call or unexpected issues
            logger.error('[bulk_attach_tool] Error:', error.response?.data || error.message);
            server.createErrorResponse(`Failed during bulk attach operation: ${error.message}`);
        }
    }
  • Input schema and tool definition for bulk_attach_tool_to_agents, defining parameters like tool_id, agent_name_filter, agent_tag_filter.
    export const bulkAttachToolDefinition = {
        name: 'bulk_attach_tool_to_agents',
        description:
            'Attaches a specified tool to multiple agents based on filter criteria (name or tags). Use list_agents to find agents and list_mcp_tools_by_server or upload_tool to get tool IDs.',
        inputSchema: {
            type: 'object',
            properties: {
                tool_id: {
                    type: 'string',
                    description: 'The ID of the tool to attach.',
                },
                agent_name_filter: {
                    type: 'string',
                    description:
                        'Optional: Filter agents by name (exact match or substring, depending on API).',
                },
                agent_tag_filter: {
                    // Assuming API accepts comma-separated string or array for tags
                    type: 'string', // or 'array' with items: { type: 'string' }
                    description:
                        'Optional: Filter agents by tag(s). Provide a single tag or comma-separated list.',
                },
                // Could add more filters like project_id if needed and supported by list_agents API
            },
            required: ['tool_id'],
            // Custom validation could ensure at least one filter is present, but basic schema doesn't enforce this easily.
            // The handler function checks for this.
        },
    };
  • Output schema defining the expected structured response: summary counts and per-agent results.
    bulk_attach_tool_to_agents: {
        type: 'object',
        properties: {
            tool_id: { type: 'string' },
            total_agents: { type: 'integer' },
            successful_attachments: { type: 'integer' },
            failed_attachments: { 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: ['tool_id', 'total_agents', 'successful_attachments'],
    },
  • Dispatch registration in the main tool call handler switch statement, routing calls to the handler function.
    case 'bulk_attach_tool_to_agents':
        return handleBulkAttachToolToAgents(server, request.params.arguments);
  • Import of the handler function and tool definition.
        handleBulkAttachToolToAgents,
        bulkAttachToolDefinition,
    } from './tools/bulk-attach-tool.js';
  • Inclusion of the tool definition in the allTools array for registration with the MCP server.
    bulkAttachToolDefinition,
Behavior3/5

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

Annotations only provide a title ('Bulk Attach Tool'), which doesn't cover behavioral traits like read-only/destructive hints. The description adds context about bulk operations and filtering, but doesn't disclose critical behavioral details such as whether this is a mutation (implied by 'Attaches'), permission requirements, rate limits, or what happens on partial failures. With minimal annotations, the description carries more burden but provides only basic operational context.

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 two sentences, front-loaded with the core purpose and followed by prerequisite guidance. Every sentence earns its place: the first defines the tool's function and scope, the second provides essential usage context. There is zero waste or redundancy.

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

Completeness4/5

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

Given the tool's moderate complexity (bulk mutation with filtering), the description is reasonably complete: it covers purpose, prerequisites, and basic operation. With an output schema present (per context signals), return values need not be explained. However, it lacks details on behavioral aspects like error handling or side effects, which are important for a bulk mutation tool.

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%, with all parameters well-documented in the schema itself (tool_id, agent_name_filter, agent_tag_filter). The description adds no additional parameter semantics beyond what's in the schema—it mentions filter criteria generically but doesn't elaborate on syntax, format, or behavior. Baseline 3 is appropriate since the schema does the heavy lifting.

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 ('Attaches a specified tool to multiple agents') and the resource ('multiple agents'), distinguishing it from sibling tools like 'attach_tool' (likely single agent) and 'add_mcp_tool_to_letta' (specific to Letta). It explicitly mentions the filter criteria (name or tags) for targeting agents.

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 provides explicit guidance on when to use this tool by naming alternative tools for prerequisite steps: 'Use list_agents to find agents and list_mcp_tools_by_server or upload_tool to get tool IDs.' This clearly indicates the tool should be used after identifying agents and tools via those other tools, though it doesn't explicitly state when NOT to use it (e.g., vs. single-agent attachment).

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