Loading

When Claude responds with a tool use request, your server needs to actually run the requested tool and send the results back. This step involves extracting tool use parts from Claude's response, executing the appropriate functions, and formatting the results properly.

Handling Multiple Tool Requests

Claude can send multiple tool use parts in a single response. Your code needs to handle this possibility defensively. An assistant message might contain a text part followed by one, two, or even more tool use parts.

Assistant message parts: a "Text" part offering to find the current time and a "toolUse" part for get_current_datetime.

The flow works like this: Claude sends a request with JSON schema, receives a tool use part, then your server runs the tool and sends back a tool result part for Claude to provide a final response.

Our server sends Claude the user message "What time is it?", the assistant text and tool use part, then a tool result part.

Extracting Tool Use Parts

First, create a function to process all the parts returned from a chat request:

python
def run_tools(parts):
    tool_requests = [part for part in parts if "toolUse" in part]
    tool_result_parts = []
    
    for tool_request in tool_requests:
        tool_use_id = tool_request["toolUse"]["toolUseId"]
        tool_name = tool_request["toolUse"]["name"]
        tool_input = tool_request["toolUse"]["input"]

This comprehension filters the parts list to only include dictionaries that contain a "toolUse" key, ignoring text parts.

Running the Actual Tools

Create a helper function to execute the requested tool:

python
def run_tool(tool_name, tool_input):
    if tool_name == "get_current_datetime":
        return get_current_datetime(**tool_input)
    else:
        raise Exception(f"Unknown tool name: {tool_name}")

The key detail here is using **tool_input to splat the dictionary of arguments into your tool function. Claude always returns arguments as a dictionary object, so you need to unpack it properly.

Creating Tool Result Parts

After running a tool, you need to format the response as a tool result part:

An assistant message content list with a text part and two "toolUse" parts, for get_current_datetime and other_tool.

Tool result parts require three key properties:

  • toolUseId - Must match the original tool use part's ID
  • content - The output from your tool, serialized as a string
  • status - Either "success" or "error"

Understanding Tool Use IDs

The tool use ID system becomes important when Claude requests multiple tools in parallel. For example, if Claude wants to run a calculator tool twice:

Claude sends calculator tool uses ab3 for 10 + 10 and po9 for 30 + 30; our server returns po9 output 60 and ab3 output 20. Claude sends calculator tool uses ab3 for 10 + 10 and po9 for 30 + 30; our server returns po9 output 60 and ab3 output 20.

Each tool use gets a unique ID (like "ab3" and "po9"), and your tool results must include the matching IDs so Claude knows which result corresponds to which request.

Error Handling

Wrap your tool execution in try-catch blocks. Claude is intelligent about tool errors and might adjust its approach if you return proper error information:

python
try:
    tool_output = run_tool(tool_name, tool_input)
    tool_result_part = {
        "toolResult": {
            "toolUseId": tool_use_id,
            "content": [{"text": json.dumps(tool_output)}],
            "status": "success"
        }
    }
except Exception as e:
    tool_result_part = {
        "toolResult": {
            "toolUseId": tool_use_id,
            "content": [{"text": f"Error: {e}"}],
            "status": "error"
        }
    }

Complete Implementation

Here's the full function that processes tool requests and returns formatted results:

python
def run_tools(parts):
    tool_requests = [part for part in parts if "toolUse" in part]
    tool_result_parts = []
    
    for tool_request in tool_requests:
        tool_use_id = tool_request["toolUse"]["toolUseId"]
        tool_name = tool_request["toolUse"]["name"]
        tool_input = tool_request["toolUse"]["input"]
        
        try:
            tool_output = run_tool(tool_name, tool_input)
            tool_result_part = {
                "toolResult": {
                    "toolUseId": tool_use_id,
                    "content": [{"text": json.dumps(tool_output)}],
                    "status": "success"
                }
            }
        except Exception as e:
            tool_result_part = {
                "toolResult": {
                    "toolUseId": tool_use_id,
                    "content": [{"text": f"Error: {e}"}],
                    "status": "error"
                }
            }
        
        tool_result_parts.append(tool_result_part)
    
    return tool_result_parts

Once you have the tool result parts, you can send them back to Claude in your next chat request, completing the tool use cycle.