Implementing Tool Use or Function Calling with Claude: A Complete Guide
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_completionfunction sends the user message plus system prompt to the Anthropic API, optionally halting when Claude emits a<function_calls>block detected viastop_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:
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:
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.
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:
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:
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:
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 forcalculator,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– 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-tutorialprovide complete working implementations in10.2_Appendix_Tool Use.ipynband reusable schemas inhints.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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →