Function Calling — Tool Use API chi tiết
Tool Use là gì?
Tool Use (còn gọi là Function Calling) là khả năng cho phép Claude gọi các hàm hoặc công cụ bên ngoài trong quá trình sinh câu trả lời. Thay vì chỉ trả về text, Claude có thể quyết định rằng nó cần thêm thông tin — và yêu cầu bạn chạy một hàm cụ thể, sau đó tiếp tục dựa trên kết quả trả về.
Đây là cơ chế nền tảng để xây dựng AI agents thực sự hữu ích: Claude không bị giới hạn bởi kiến thức tĩnh mà có thể tìm kiếm web, truy vấn database, gọi API ngoài, hoặc thực thi code trong thời gian thực.
Defining Tools — JSON Schema
Mỗi tool được định nghĩa bằng JSON Schema với ba trường bắt buộc:
tools = [
{
"name": "get_weather",
"description": "Lấy thông tin thời tiết hiện tại cho một thành phố.",
"input_schema": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "Tên thành phố, ví dụ: 'Hà Nội', 'TP. Hồ Chí Minh'"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "Đơn vị nhiệt độ"
}
},
"required": ["city"]
}
}
]
Description của tool và từng parameter là yếu tố quan trọng nhất — Claude dựa vào đây để quyết định khi nào và cách nào sử dụng tool. Viết description rõ ràng, cụ thể, bao gồm ví dụ nếu cần.
Tool Use Flow — Vòng lặp hoàn chỉnh
Luồng xử lý Tool Use có 4 bước:
Bước 1: Gửi request với tools
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-4",
max_tokens=1024,
tools=tools,
messages=[
{"role": "user", "content": "Thời tiết Hà Nội hôm nay thế nào?"}
]
)
Bước 2: Nhận tool_use response
Khi Claude quyết định gọi tool, stop_reason sẽ là "tool_use" và content sẽ chứa block tool_use:
# response.stop_reason == "tool_use"
# response.content:
[
TextBlock(text="Để trả lời câu hỏi này, tôi cần..."),
ToolUseBlock(
id="toolu_01A09q90qw90lq917835lq9",
name="get_weather",
input={"city": "Hà Nội", "unit": "celsius"}
)
]
Bước 3: Thực thi tool và trả kết quả
import json
def process_tool_calls(response, tools_map):
tool_results = []
for block in response.content:
if block.type == "tool_use":
tool_fn = tools_map[block.name]
result = tool_fn(**block.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": json.dumps(result)
})
return tool_results
# Gọi tool thực tế
tools_map = {
"get_weather": lambda city, unit="celsius": {
"temperature": 28,
"condition": "Nhiều mây",
"humidity": 75
}
}
tool_results = process_tool_calls(response, tools_map)
Bước 4: Tiếp tục conversation với tool_result
messages = [
{"role": "user", "content": "Thời tiết Hà Nội hôm nay thế nào?"},
{"role": "assistant", "content": response.content},
{"role": "user", "content": tool_results}
]
final_response = client.messages.create(
model="claude-opus-4",
max_tokens=1024,
tools=tools,
messages=messages
)
# final_response.stop_reason == "end_turn"
print(final_response.content[0].text)
Parallel Tool Calls
Claude có thể gọi nhiều tools cùng lúc trong một response khi cần thông tin từ nhiều nguồn độc lập nhau:
# Claude trả về nhiều tool_use blocks cùng lúc:
[
ToolUseBlock(id="tu_001", name="get_weather", input={"city": "Hà Nội"}),
ToolUseBlock(id="tu_002", name="get_weather", input={"city": "TP. Hồ Chí Minh"}),
ToolUseBlock(id="tu_003", name="get_exchange_rate", input={"currency": "USD"})
]
# Bạn cần trả về kết quả cho TẤT CẢ tool calls:
tool_results = [
{"type": "tool_result", "tool_use_id": "tu_001", "content": "28°C, nhiều mây"},
{"type": "tool_result", "tool_use_id": "tu_002", "content": "32°C, nắng"},
{"type": "tool_result", "tool_use_id": "tu_003", "content": "25,450 VND/USD"}
]
Khi xử lý parallel tool calls, bạn nên thực thi chúng đồng thời (asyncio hoặc threading) để giảm latency.
Sequential Tool Calls
Claude tự động thực hiện nhiều vòng tool calls liên tiếp khi kết quả của tool trước ảnh hưởng đến tool sau:
# Vòng 1: Claude gọi search
ToolUseBlock(name="web_search", input={"query": "giá iPhone 15 Pro Max VN"})
# Sau khi nhận kết quả search...
# Vòng 2: Claude gọi calculator
ToolUseBlock(name="calculate", input={"expression": "34990000 * 0.95"})
# Sau khi nhận kết quả tính toán...
# Claude trả lời cuối cùng
Error Handling
Khi tool gặp lỗi, trả về is_error: true trong tool_result. Claude sẽ xử lý lỗi và có thể thử cách khác:
tool_results = [
{
"type": "tool_result",
"tool_use_id": block.id,
"content": "Không thể kết nối đến API thời tiết. Lỗi: timeout",
"is_error": True
}
]
Forcing Tool Use với tool_choice
Mặc định Claude tự quyết định có dùng tool hay không. Bạn có thể kiểm soát hành vi này:
# Bắt buộc Claude PHẢI dùng tool (bất kỳ tool nào)
tool_choice = {"type": "any"}
# Bắt buộc dùng tool cụ thể
tool_choice = {"type": "tool", "name": "get_weather"}
# Không được dùng tool (chỉ text)
tool_choice = {"type": "none"}
# Tự động quyết định (mặc định)
tool_choice = {"type": "auto"}
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
tools=tools,
tool_choice={"type": "tool", "name": "get_weather"},
messages=[...]
)
Complex Pattern: Search → Analyze → Respond
Ví dụ thực tế: agent tìm kiếm thông tin, phân tích, và trả lời dựa trên dữ liệu thực:
tools = [
{
"name": "search_products",
"description": "Tìm kiếm sản phẩm trong database theo từ khóa",
"input_schema": {
"type": "object",
"properties": {
"query": {"type": "string"},
"category": {"type": "string"},
"max_price": {"type": "number"}
},
"required": ["query"]
}
},
{
"name": "get_product_reviews",
"description": "Lấy đánh giá của sản phẩm theo product_id",
"input_schema": {
"type": "object",
"properties": {
"product_id": {"type": "string"},
"limit": {"type": "integer", "default": 5}
},
"required": ["product_id"]
}
},
{
"name": "compare_prices",
"description": "So sánh giá sản phẩm trên các sàn thương mại điện tử",
"input_schema": {
"type": "object",
"properties": {
"product_name": {"type": "string"}
},
"required": ["product_name"]
}
}
]
Caching với Tools
Khi dùng nhiều tools hoặc tool definitions dài, hãy cache chúng để giảm chi phí:
response = client.messages.create(
model="claude-opus-4",
max_tokens=1024,
tools=tools,
system=[
{
"type": "text",
"text": "Bạn là trợ lý mua sắm thông minh...",
"cache_control": {"type": "ephemeral"}
}
],
messages=[{"role": "user", "content": user_query}]
)
Tool definitions được tính vào input tokens và có thể được cache riêng nếu chúng ổn định giữa các requests.
Best Practices
- Description chất lượng cao: Mô tả rõ tool làm gì, khi nào nên dùng, format input mong muốn
- Tối thiểu hóa tool set: Chỉ cung cấp tools thực sự cần thiết cho task — quá nhiều tools làm Claude khó quyết định
- Idempotent tools: Thiết kế tools có thể gọi lại nhiều lần mà không gây side effects ngoài ý muốn
- Timeout và retry: Luôn có timeout cho external API calls, retry logic cho transient failures
- Validate input: Validate và sanitize input từ Claude trước khi thực thi — không tin tưởng blindly
- Log mọi tool calls: Ghi lại tool name, input, output để debug và audit
Ví dụ hoàn chỉnh: Weather + Calculator
import anthropic
import json
client = anthropic.Anthropic()
tools = [
{
"name": "get_weather",
"description": "Lấy nhiệt độ và điều kiện thời tiết cho thành phố",
"input_schema": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "Tên thành phố tiếng Việt"}
},
"required": ["city"]
}
},
{
"name": "calculate",
"description": "Tính toán biểu thức toán học",
"input_schema": {
"type": "object",
"properties": {
"expression": {"type": "string", "description": "Biểu thức toán học, ví dụ: '28 * 1.8 + 32'"}
},
"required": ["expression"]
}
}
]
def run_tool(name, inputs):
if name == "get_weather":
# Mock — thay bằng API thật
return {"city": inputs["city"], "temp_celsius": 28, "condition": "Nhiều mây"}
if name == "calculate":
return {"result": eval(inputs["expression"])} # Trong production dùng safe eval
def agent_loop(user_message):
messages = [{"role": "user", "content": user_message}]
while True:
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
tools=tools,
messages=messages
)
if response.stop_reason == "end_turn":
return response.content[0].text
# Xử lý tool calls
messages.append({"role": "assistant", "content": response.content})
tool_results = []
for block in response.content:
if block.type == "tool_use":
result = run_tool(block.name, block.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": json.dumps(result, ensure_ascii=False)
})
messages.append({"role": "user", "content": tool_results})
result = agent_loop("Nhiệt độ Hà Nội bao nhiêu độ F?")
print(result)
Kết luận
Tool Use API là nền tảng để biến Claude từ chatbot thành agent thực sự. Với khả năng xử lý parallel và sequential tool calls, Claude có thể orchestrate các workflow phức tạp một cách tự nhiên. Điều quan trọng nhất là thiết kế tool definitions rõ ràng và xây dựng error handling robust để agent hoạt động tin cậy trong môi trường production.
Bai viet co huu ich khong?
Bản quyền thuộc về tác giả. Vui lòng dẫn nguồn khi chia sẻ.






