Tool function là Python function bình thường — nhưng có 2 khác biệt:
- Viết tool function theo best practices: descriptive names, validation, error messages
- Hiểu Claude "thấy" error → tự retry với corrected params
- Viết 3 function mẫu: datetime, duration, reminders
- Connect function với schema
Mở đầu: Function đơn giản nhưng cần robust
- Caller là Claude, không phải devparams có thể "kỳ quặc", need validation
- Error visible to ClaudeClaude có thể retry nếu error clear
Best practices
1. Descriptive names
def f(x, y): ...
def get_current_datetime(date_format): ...
def calculate_shipping_cost(weight, destination): ...
Tên function + param phải tự-documenting.
2. Validate inputs
def get_weather(location, unit="F"):
if not location:
raise ValueError("Location cannot be empty")
if unit not in ("F", "C"):
raise ValueError(f"Unit must be F or C, got {unit}")
# ... actual logic
3. Meaningful error messages
raise Exception("error")
raise ValueError(f"Invalid date format '{fmt}'. Use Python strftime syntax (e.g., '%Y-%m-%d')")
Claude đọc error, có thể retry với correction.
4. Return strings (thường)
Claude dễ process string. Nếu function return dict/list, Claude vẫn OK nhưng string thường preferred:
return {"temp": 72, "condition": "sunny"}
return "Current weather in SF: 72°F, sunny with 10mph wind"
3 tool functions mẫu
1. get_current_datetime
from datetime import datetime
def get_current_datetime(date_format="%Y-%m-%d %H:%M:%S"):
"""Get current date/time."""
if not date_format:
raise ValueError("date_format cannot be empty")
try:
return datetime.now().strftime(date_format)
except ValueError as e:
raise ValueError(f"Invalid format string: {date_format}. {str(e)}")
print(get_current_datetime()) # "2026-04-20 14:30:25"
print(get_current_datetime("%H:%M")) # "14:30"
print(get_current_datetime("%A")) # "Monday"
2. add_duration_to_datetime
from datetime import datetime, timedelta
def add_duration_to_datetime(
datetime_str: str,
duration: int,
unit: str = "days"
) -> str:
"""Add duration to a datetime."""
if unit not in ("seconds", "minutes", "hours", "days", "weeks"):
raise ValueError(f"Unit must be seconds/minutes/hours/days/weeks, got {unit}")
try:
dt = datetime.fromisoformat(datetime_str)
except ValueError:
raise ValueError(f"Invalid datetime: '{datetime_str}'. Expected ISO format like '2026-04-20T14:30:00'")
delta = timedelta(**{unit: duration})
result = dt + delta
return result.isoformat()
print(add_duration_to_datetime("2026-04-20T00:00:00", 103, "days"))
3. set_reminder
def set_reminder(
reminder_text: str,
remind_at_iso: str
) -> str:
"""Set a reminder. Returns confirmation."""
if not reminder_text.strip():
raise ValueError("Reminder text cannot be empty")
try:
remind_at = datetime.fromisoformat(remind_at_iso)
except ValueError:
raise ValueError(f"Invalid datetime format: {remind_at_iso}")
if remind_at < datetime.now():
raise ValueError("Reminder time must be in the future")
# Store in DB (simplified)
reminder_id = f"rem_{int(datetime.now().timestamp())}"
# save to db...
return f"Reminder set: '{reminder_text}' at {remind_at.strftime('%Y-%m-%d %H:%M')}. ID: {reminder_id}"
Pattern: Try-except với informative error
def query_database(sql: str) -> str:
if not sql.strip().lower().startswith("select"):
raise ValueError("Only SELECT queries allowed. Got: " + sql[:50])
try:
results = db.execute(sql).fetchall()
return format_results(results)
except db.OperationalError as e:
raise ValueError(f"SQL error: {str(e)}. Check syntax.")
except db.TimeoutError:
raise TimeoutError("Query too slow. Try narrower WHERE clause.")
Claude có thể retry:
- First call:
SELECT * FROM usrs→ error "table usrs not found" - Retry:
SELECT * FROM users→ works
Pattern: Side effects + confirmation
Cho tools có side effect (create, delete, send), return rõ ràng:
def send_email(to: str, subject: str, body: str) -> str:
if not is_valid_email(to):
raise ValueError(f"Invalid email: {to}")
try:
email_service.send(to=to, subject=subject, body=body)
return f"Email sent successfully to {to}. Subject: '{subject}'"
except EmailServiceError as e:
raise RuntimeError(f"Email failed: {e}")
Return confirmation giúp Claude biết action thành công.
Function + schema pairing
def get_weather(location: str, unit: str = "F") -> str:
# ... implementation
pass
get_weather_schema = {
"name": "get_weather",
# ... schema
}
TOOLS = {
"get_weather": get_weather,
"get_current_datetime": get_current_datetime,
"add_duration_to_datetime": add_duration_to_datetime,
"set_reminder": set_reminder,
}
def run_tool(name: str, input: dict) -> str:
"""Execute tool by name with args."""
if name not in TOOLS:
raise ValueError(f"Unknown tool: {name}")
return TOOLS[name](**input)
Usage:
tool_call = response.content[-1] # ToolUseBlock
result = run_tool(tool_call.name, tool_call.input)
Security considerations
Tool có thể run code / modify data — nguy hiểm
Validate strictly:
def execute_python(code: str) -> str:
# DANGEROUS — code injection
return str(eval(code))
Never. Dùng sandbox (Docker, subprocess với limits).
Rate limiting
Tool gọi external API → có thể abuse.
from functools import lru_cache
from time import time
@lru_cache(maxsize=100)
def _cached_weather(location: str, hour: int):
return weather_api.get(location)
def get_weather(location: str, unit: str = "F"):
# Cache per hour
hour = int(time()) // 3600
return _cached_weather(location, hour)
Whitelisting
def get_order_status(order_id: str, user_id: str) -> str:
order = db.get(order_id)
if order.user_id != user_id:
raise PermissionError("Order not yours")
return order.status
Pass user_id trong context từ session, không trust Claude pass.
Anti-patterns
No validation
Claude pass location="" → crash or wrong query.
Fix: Validate + raise.
Silent failure
try:
do_something()
except:
return "" # Claude không biết có lỗi
Fix: Raise với message. Claude sẽ retry.
Return nothing
def save_to_db(data):
db.save(data)
# không return gì
Fix: Return "Saved with ID: xyz". Claude xác nhận.
Complex nested return
return {"a": {"b": {"c": {"d": "value"}}}}
Claude xử lý OK nhưng string prose thường clearer.
Fix: Return formatted string hoặc flat dict.
Áp dụng ngay
Bài tập 1: Viết 3 tool function (30 phút)
Chọn 3 tool cho app của bạn. Viết function với:
- Type hints
- Docstring
- Input validation
- Error message
- Return formatted string
Test mỗi function với valid + invalid input.
Bài tập 2: Pair với schema (15 phút)
Viết schema cho mỗi function. Commit cả 2 cùng file tools.py:
def my_tool(...): ...
my_tool_schema = {...}
Tóm tắt bài học
- Tool function = Python function + robust validation.
- Error message informative — Claude đọc và retry được.
- Return string formatted giúp Claude process dễ hơn.
- Security: validate, sandbox, rate-limit, whitelist.
- Function + schema pair:
my_tool+my_tool_schema.