tool_use

Tools

Definition

A content block type in Claude's response indicating the model wants to call a specific tool. Contains 'id', 'name', and 'input' fields. The agent must execute the tool and return results in a tool_result content block for the conversation to continue.

Example Usage

When response.content[0].type == 'tool_use', extract the tool name and inputs, execute the function, and return results.

Why It Matters for the CCA-F Exam

The CCA-F exam tests whether you know the exact fields of a `tool_use` block (`id`, `name`, `input`) and that `stop_reason: "tool_use"` is what signals a pending call. Questions frequently probe the ID-matching requirement between `tool_use` and `tool_result`, and whether you handle multiple `tool_use` blocks in a single response correctly.

In Depth

A tool_use content block is Claude's mechanism for requesting an external function call mid-conversation. When Claude determines it needs to invoke a tool, its response will contain one or more content blocks of type: "tool_use". Each block carries three required fields:

  • id — a unique identifier (e.g., "toolu_01XmpZ…") that you must echo back in the corresponding tool_result.
  • name — the exact name of the tool Claude has chosen to invoke.
  • input — a JSON object conforming to the tool's declared input schema.

The conversation only moves forward once you return the result. Practically, this means your agent loop must check response.stop_reason === "tool_use", iterate over response.content to find every block where block.type === "tool_use", execute each call, then append a new user message whose content array holds a tool_result block for every requested tool.

A critical accuracy point: always parse input as a JSON object. Never string-match against the serialized form. Claude constructs valid JSON per your schema, and your code should deserialize it accordingly.

Another common mistake is mismatching IDs. The tool_use_id in the tool_result must equal the id from the tool_use block — even in parallel tool use scenarios where multiple blocks arrive simultaneously. ID mismatches cause the API to return a validation error.

The agentic loop continues until Claude emits a stop_reason of end_turn (or another terminal reason like max_tokens). tool_use stop_reason signals that Claude has more work to do and is waiting on your execution layer.

Beyond simple scalar results, tool_result content can include images and structured data. This makes tool_use versatile for tasks ranging from database queries to screenshot capture. See the Tool Use Flow & Mechanics concept guide for the full lifecycle diagram.

Example

Minimal agentic loop: handle tool_use stop_reason, collect every tool_use block, and return all results in one user message.

javascript
// Minimal agentic loop handling tool_use
async function runLoop(client, messages, tools) {
  while (true) {
    const response = await client.messages.create({
      model: "claude-opus-4-8",
      max_tokens: 4096,
      tools,
      messages,
    });

    if (response.stop_reason === "end_turn") {
      return response;
    }

    if (response.stop_reason === "tool_use") {
      // Append assistant turn
      messages.push({ role: "assistant", content: response.content });

      // Collect all tool_use blocks and execute them
      const toolResults = [];
      for (const block of response.content) {
        if (block.type === "tool_use") {
          // Always parse input as JSON object — never string-match
          const result = await executeTool(block.name, block.input);
          toolResults.push({
            type: "tool_result",
            tool_use_id: block.id,  // Must match exactly
            content: result,
          });
        }
      }

      // Return ALL results in one user message
      messages.push({ role: "user", content: toolResults });
    }
  }
}

Frequently Asked Questions

What happens if I return tool results in separate messages instead of one?

The API requires all `tool_result` blocks for a given assistant turn to be returned together in a single user message. Splitting them across multiple user messages violates the conversation structure and will result in an API validation error.

Can `input` ever be a string rather than an object?

No. The `input` field is always a JSON object whose structure matches the tool's declared `input_schema`. If your schema defines an object with properties, `input` will be that object. You should always deserialize and access properties — never treat the value as a raw string to be parsed or matched against.

Does `stop_reason: "tool_use"` mean Claude is done thinking?

Not necessarily. It means Claude has decided it needs external information or action before it can continue. After you return the `tool_result`, Claude will resume reasoning and may issue more tool calls, produce text, or complete with `end_turn`. The loop continues until a terminal stop_reason is reached.