Debug Fix intermediate · 3 min read

How to handle Claude tool use response

Quick answer
When using Claude with tool use enabled, check if response.choices[0].finish_reason is tool_calls. Then parse response.choices[0].message.tool_calls to extract the tool name and JSON arguments. This ensures you handle tool invocation results properly.
ERROR TYPE model_behavior
⚡ QUICK FIX
Check finish_reason for tool_calls and parse message.tool_calls JSON arguments to handle Claude tool use responses correctly.

Why this happens

Claude models with tool use enabled return responses indicating when the model wants to invoke a tool. Instead of a normal text reply, the finish_reason is set to tool_calls, and the message.tool_calls array contains the tool invocation details. If your code treats the response as plain text without checking for tool calls, you will miss the tool invocation or get errors when accessing the content.

Example broken code:

python
import anthropic
import os

client = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])

response = client.messages.create(
    model="claude-3-5-sonnet-20241022",
    max_tokens=1024,
    tools=[{"type": "computer_20241022", "name": "computer"}],
    messages=[{"role": "user", "content": "Run a calculation"}],
    betas=["computer-use-2024-10-22"]
)

# Incorrect: assuming normal text response
print(response.choices[0].message.content)
output
Traceback (most recent call last):
  File "example.py", line 15, in <module>
    print(response.choices[0].message.content)
AttributeError: 'NoneType' object has no attribute 'content'

# Or prints None or empty string if content is missing

The fix

Check if finish_reason is tool_calls. If so, access message.tool_calls to get the tool invocation details. Parse the function.arguments JSON string to extract parameters. This lets you handle the tool call properly and respond accordingly.

python
import anthropic
import os
import json

client = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])

response = client.messages.create(
    model="claude-3-5-sonnet-20241022",
    max_tokens=1024,
    tools=[{"type": "computer_20241022", "name": "computer"}],
    messages=[{"role": "user", "content": "Calculate 2 + 2"}],
    betas=["computer-use-2024-10-22"]
)

choice = response.choices[0]
if choice.finish_reason == "tool_calls":
    tool_call = choice.message.tool_calls[0]
    tool_name = tool_call.function.name
    args = json.loads(tool_call.function.arguments)
    print(f"Tool to call: {tool_name}")
    print(f"Arguments: {args}")
else:
    print(choice.message.content)
output
Tool to call: computer
Arguments: {'code': '2 + 2'}

Preventing it in production

Implement robust handling for tool_calls in your Claude integration by:

  • Checking finish_reason on every response.
  • Parsing tool_calls JSON arguments safely with json.loads().
  • Adding error handling for malformed or unexpected tool call data.
  • Implementing retries or fallbacks if tool execution fails.
  • Logging tool call details for debugging and auditing.

This ensures your app correctly interprets when Claude wants to invoke tools and can respond or execute accordingly.

Key Takeaways

  • Always check finish_reason for tool_calls when using Claude with tools.
  • Parse message.tool_calls JSON arguments to extract tool invocation details.
  • Include betas=["computer-use-2024-10-22"] and proper tools in requests to enable tool use.
  • Add error handling and logging around tool call parsing for production robustness.
  • Ignoring tool calls leads to missing or incorrect responses from Claude models.
Verified 2026-04 · claude-3-5-sonnet-20241022
Verify ↗