# Implementing Tool Use or Function Calling with Claude: A Complete Guide

> Master Claude tool use with this guide. Learn prompt-based function calling using XML and structured output parsing to integrate real-world functions into your AI applications.

- Repository: [Anthropic/prompt-eng-interactive-tutorial](https://github.com/anthropics/prompt-eng-interactive-tutorial)
- Tags: how-to-guide
- Published: 2026-03-09

---

**Claude implements tool use through a pure-prompt-based architecture where the system prompt defines available functions in XML format, the API client halts generation at `</function_calls>` stop sequences, and a Python wrapper parses the structured output to execute real functions before returning results to the model.**

The `anthropics/prompt-eng-interactive-tutorial` repository demonstrates how to implement tool use or function calling with Claude without relying on native API function calling features. This approach uses carefully constructed system prompts and stop sequences to create a secure, extensible framework for extending Claude's capabilities with external Python functions.


## How Tool Use Works in Claude

Unlike native function-calling APIs that modify the model's logit sampling, Claude's tool use relies entirely on **prompt engineering** and **structured generation control**. The architecture consists of three tightly coupled components that orchestrate the round-trip between the language model and external Python functions.

### Core Components of the Architecture

- **System-prompt generator** – Builds a two-part prompt that (1) explains the concept of tool use and (2) enumerates the available functions in a `<tools>` block. This provides Claude with the contract it must obey when invoking a function. Source: `Anthropic 1P/10.2_Appendix_Tool Use.ipynb` (lines 19-45).

- **Control-logic wrapper** – The `get_completion` function sends the user message plus system prompt to the Anthropic API, optionally halting when Claude emits a `<function_calls>` block detected via `stop_sequences`. This orchestrates the round-trip: forward Claude's request, run the real Python function, and feed results back. Source: `Anthropic 1P/10.2_Appendix_Tool Use.ipynb` (lines 31-45).

- **Tool definitions** – JSON-style schema describing each function (name, parameters, description) stored in `system_prompt_tools_specific_tools`. This gives Claude a machine-readable description it can embed in its `<function_calls>` markup. Source: `Anthropic 1P/10.2_Appendix_Tool Use.ipynb` (lines 61-88).

- **Python implementations** – Ordinary functions (`calculator`, `get_user`, etc.) that the wrapper invokes once Claude's request is parsed. These execute the real work on behalf of Claude. Source: `Anthropic 1P/hints.py` (lines 175-244).


## Building the System Prompt for Tool Use

The system prompt serves as the contract between Claude and your application. It concatenates a general explanation of the tool-use protocol with specific function schemas.

### General Tool Use Explanation

The first section teaches Claude the XML structure it must use to request function execution. This template lives in `system_prompt_tools_general_explanation`:

```python
system_prompt_tools_general_explanation = """You have access to a set of functions you can use to answer the user's question. If you need to use a function, you can request it by writing a <function_calls> block.

Here is the format for a <function_calls> block:

<function_calls>
<invoke name="$FUNCTION_NAME">
<parameter name="$PARAMETER_NAME">$PARAMETER_VALUE</parameter>
...
</invoke>
</function_calls>

Here are the functions available to you:
"""

```

*Source: `Anthropic 1P/10.2_Appendix_Tool Use.ipynb` (lines 19-45)*

### Defining Available Tools

The second section enumerates concrete tools using a JSONSchema-like XML format. This example defines a `calculator` tool:

```python
system_prompt_tools_specific_tools = """<tools>
  <tool_description>
    <tool_name>calculator</tool_name>
    <description>Calculator function for basic arithmetic.</description>
    <parameters>
      <parameter>
        <name>first_operand</name>
        <type>int</type>
        <description>The first operand.</description>
      </parameter>
      <parameter>
        <name>second_operand</name>
        <type>int</type>
        <description>The second operand.</description>
      </parameter>
      <parameter>
        <name>operator</name>
        <type>str</type>
        <description>The operator to use (+, -, *, /).</description>
      </parameter>
    </parameters>
  </tool_description>
</tools>"""

# Concatenate for the final system prompt

system_prompt = system_prompt_tools_general_explanation + system_prompt_tools_specific_tools

```

*Source: `Anthropic 1P/10.2_Appendix_Tool Use.ipynb` (lines 61-88)*


## Implementing the Control Logic Wrapper

The `get_completion` function orchestrates communication with the Anthropic API. Crucially, it uses `stop_sequences` to halt generation when Claude emits a tool call, allowing your application to intercept the request before Claude continues.

```python
import anthropic

client = anthropic.Anthropic(api_key="YOUR_API_KEY")

def get_completion(messages, system_prompt="", stop_sequences=None):
    response = client.messages.create(
        model="claude-3-sonnet-20240229",  # Sonnet works best for tool use

        max_tokens=2000,
        temperature=0.0,
        system=system_prompt,
        messages=messages,
        stop_sequences=stop_sequences,
    )
    return response.content[0].text

```

*Source: `Anthropic 1P/10.2_Appendix_Tool Use.ipynb` (lines 31-45)*

To trigger a tool call, invoke `get_completion` with `stop_sequences=["</function_calls>"]`. This ensures Claude stops immediately after closing the function calls tag, allowing your code to parse and execute the request.


## Parsing and Executing Function Calls

When Claude requests a tool, it returns XML within `<function_calls>` tags. Your application must parse this structure, execute the corresponding Python function, and return the results wrapped in `<function_results>`.

### Extracting Function Calls from Claude's Response

Use regular expressions to parse the XML structure. This example extracts the function name and parameters:

```python
import re

def parse_function_calls(text):
    # Extract function name

    name_match = re.search(r'<invoke name="([^"]+)">', text)
    if not name_match:
        return None, {}
    function_name = name_match.group(1)
    
    # Extract parameters

    params = {}
    for match in re.finditer(r'<parameter name="([^"]+)">(.*?)</parameter>', text):
        param_name = match.group(1)
        param_value = match.group(2)
        params[param_name] = param_value
    
    return function_name, params

```

*Parsing logic is described in the notebook's "Now we can extract..." section (lines 220-250).*

### Executing the Python Implementation

Implement the actual function logic in pure Python. This `calculator` function matches the schema defined in the system prompt:

```python
def calculator(first_operand, second_operand, operator):
    """Execute arithmetic operations based on Claude's request."""
    a, b = int(first_operand), int(second_operand)
    ops = {
        "+": a + b,
        "-": a - b,
        "*": a * b,
        "/": a / b if b != 0 else "Error: Division by zero"
    }
    return ops.get(operator, "Error: Unknown operator")

# Example execution flow

func_name, args = parse_function_calls(raw_reply)
if func_name == "calculator":
    result = calculator(**args)
    result_message = {
        "role": "assistant",
        "content": f"<function_results>{result}</function_results>"
    }

```

Because Claude never runs code itself, **security** is maintained: only the wrapper decides which functions are exposed and validates parameters before execution.


## Complete End-to-End Example

This script combines all components into a single runnable workflow that multiplies two numbers using Claude's tool use capabilities:

```python
import anthropic, re

# Initialize client

client = anthropic.Anthropic(api_key="YOUR_API_KEY")

def get_completion(messages, system_prompt="", stop_sequences=None):
    response = client.messages.create(
        model="claude-3-sonnet-20240229",
        max_tokens=2000,
        temperature=0.0,
        system=system_prompt,
        messages=messages,
        stop_sequences=stop_sequences,
    )
    return response.content[0].text

def parse_function_calls(text):
    name = re.search(r'<invoke name="([^"]+)">', text).group(1)
    params = {}
    for match in re.finditer(r'<parameter name="([^"]+)">(.*?)</parameter>', text):
        params[match.group(1)] = match.group(2)
    return name, params

def calculator(first_operand, second_operand, operator):
    a, b = int(first_operand), int(second_operand)
    ops = {"+": a+b, "-": a-b, "*": a*b, "/": a/b}
    return ops[operator]

# Build system prompt

system_prompt_tools_general_explanation = """You have access to functions..."""  # (truncated for brevity)

system_prompt_tools_specific_tools = """<tools><tool_description>...</tool_description></tools>"""
system_prompt = system_prompt_tools_general_explanation + system_prompt_tools_specific_tools

# Execute workflow

user_msg = {"role": "user", "content": "What is 8 * 9?"}
stop = ["</function_calls>"]

# Step 1: Get Claude's function request

first_response = get_completion([user_msg], system_prompt=system_prompt, stop_sequences=stop)

# Step 2: Parse and execute

func_name, args = parse_function_calls(first_response)
if func_name == "calculator":
    value = calculator(**args)
    result_msg = {"role": "assistant", "content": f"<function_results>{value}</function_results>"}
    
    # Step 3: Get final answer

    final_response = get_completion([user_msg, result_msg], system_prompt=system_prompt)
    print(final_response)  # Output: "The answer is 72."

```

This implementation mirrors the exact pattern found in `Anthropic 1P/10.2_Appendix_Tool Use.ipynb`, providing a secure, prompt-driven alternative to native function calling.


## Key Files in the Repository

Understanding the source structure helps you extend this implementation for custom use cases:

- **`Anthropic 1P/10.2_Appendix_Tool Use.ipynb`** – Full, runnable notebook demonstrating system-prompt creation, stop-sequence handling, parsing, and orchestration of tool calls.

- **`Anthropic 1P/hints.py`** – Contains reusable tool-schema snippets (e.g., `exercise_10_2_1_solution`) defining schemas for `calculator`, `get_user`, `add_product`, and other example functions.

- **`AmazonBedrock/.../10_2_Appendix_Tool_Use.ipynb`** – Adaptation of the same lesson for AWS Bedrock SDK, useful when targeting Bedrock instead of the direct Anthropic API.

- **[`README.md`](https://github.com/anthropics/prompt-eng-interactive-tutorial/blob/main/README.md)** – Explains the tutorial structure and locates the Tool Use lesson within the Appendix section.


## Summary

Implementing tool use or function calling with Claude requires orchestrating several components to create a secure, prompt-driven execution loop:

- **Pure-prompt architecture** eliminates the need for native function-calling endpoints by teaching Claude XML-based function call syntax through system prompts.
- **Stop sequences** (`</function_calls>`) halt generation immediately when Claude requests a tool, allowing your application to intercept and validate the call.
- **XML parsing** extracts function names and parameters from `<invoke>` and `<parameter>` tags using regular expressions.
- **Security isolation** ensures Claude never executes code directly; your Python wrapper controls which functions are exposed and validates all parameters.
- **Repository resources** in `anthropics/prompt-eng-interactive-tutorial` provide complete working implementations in `10.2_Appendix_Tool Use.ipynb` and reusable schemas in [`hints.py`](https://github.com/anthropics/prompt-eng-interactive-tutorial/blob/main/hints.py).


## Frequently Asked Questions

### How does Claude's tool use differ from OpenAI's function calling?

Claude's approach uses **pure prompt engineering** rather than a native API feature. While OpenAI provides a `functions` parameter in the API request, Claude's implementation requires you to embed function schemas directly in the system prompt using XML tags like `<tools>` and `<tool_description>`. The API interaction relies on `stop_sequences` to detect when Claude has emitted a `<function_calls>` block, whereas OpenAI's model outputs a JSON object that conforms to a predefined schema. This prompt-based approach offers greater flexibility in how you structure tool definitions but requires more manual orchestration of the execution loop.

### Is it safe to let Claude execute Python code directly?

**No, and this implementation specifically prevents that.** The architecture maintains security by ensuring Claude never runs code itself. Instead, Claude only generates XML markup requesting a function call. Your Python wrapper (`get_completion` and the parsing logic) intercepts this request, validates the function name against an allowlist, sanitizes parameters, and executes only the predefined Python functions you have explicitly implemented. This isolation ensures that arbitrary code execution is impossible, as the wrapper controls the entire execution environment and can implement additional validation layers before calling any external APIs or databases.

### Can I use this approach with AWS Bedrock?

**Yes.** The repository includes an adapted implementation specifically for AWS Bedrock in the `AmazonBedrock/` directory. The file `AmazonBedrock/.../10_2_Appendix_Tool_Use.ipynb` contains the same lesson structure but uses the Bedrock SDK (`boto3`) instead of the direct Anthropic client. The core concepts—system prompt construction, XML-based tool definitions, stop sequences, and result parsing—remain identical, though the API client initialization and message formatting differ slightly to accommodate Bedrock's request/response structure.

### What models support this tool use implementation?

According to the source code in `Anthropic 1P/10.2_Appendix_Tool Use.ipynb`, **Claude 3 Sonnet** (`claude-3-sonnet-20240229`) is explicitly recommended for tool use implementations. The notebook initializes the client with this model version, noting that it "works best for tool use" compared to other Claude 3 model variants. While other Claude 3 models (Haiku or Opus) can technically follow the XML-based tool use prompts, the tutorial specifically validates the implementation against Sonnet's instruction-following capabilities for structured output generation.