Khi bạn viết function Python, bạn thêm docstring cho dev khác đọc:
- Viết tool schema đầy đủ với name, description, input_schema
- Hiểu JSON Schema spec — types, required, defaults
- Viết description chất lượng giúp Claude biết khi nào call tool
- Generate schema bằng Claude (self-generate) để tiết kiệm thời gian
- Dùng ToolParam type cho type safety
3 thành phần của schema
1. name
Examples: get_weather, search_emails, create_calendar_event.
2. description
Quan trọng nhất. Claude dựa vào đây quyết định khi nào call tool.
Best practices:
Bad: "Gets data"
Good: "Get current weather conditions for a specified location. Use this when user asks about weather, temperature, or wind. Returns a formatted string with temperature, conditions, and wind speed."
3. input_schema
Follows JSON Schema spec — standard cho validate JSON data.
- Snake_case
- Descriptive verb
- Match Python function name (convention)
- 3-4 sentences
- Describe what tool does
- When Claude nên dùng
- What tool returns
{
"name": "get_weather",
"description": "Get current weather conditions for a specified location. Use this when user asks about current weather, temperature, or atmospheric conditions. Returns text with temperature, conditions, and wind.",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name or airport code, e.g., 'San Francisco' or 'SFO'"
},
"unit": {
"type": "string",
"enum": ["F", "C"],
"description": "Temperature unit: F for Fahrenheit, C for Celsius",
"default": "F"
}
},
"required": ["location"]
}
}JSON Schema basics
Types
Example object schema
Additional constraints
- string — text
- integer — số nguyên
- number — float / int
- boolean — true/false
- array — list
- object — dict (nested)
- null — null value
- enum: restrict to list of values
- default: default value if not provided
- minimum / maximum: numeric range
- minLength / maxLength: string length
- pattern: regex for string
- description: per-field docs
{
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"is_admin": {"type": "boolean"},
"tags": {
"type": "array",
"items": {"type": "string"}
},
"address": {
"type": "object",
"properties": {
"street": {"type": "string"},
"city": {"type": "string"}
}
}
},
"required": ["name", "age"]
}Viết schema đầy đủ — Ví dụ get_current_datetime
Naming convention: function_name + function_name_schema. Dễ pair.
from datetime import datetime
def get_current_datetime(date_format="%Y-%m-%d %H:%M:%S"):
if not date_format:
raise ValueError("date_format cannot be empty")
return datetime.now().strftime(date_format)
get_current_datetime_schema = {
"name": "get_current_datetime",
"description": "Returns the current date and time formatted according to the specified format. Use when user asks for current time, today's date, or to timestamp an event.",
"input_schema": {
"type": "object",
"properties": {
"date_format": {
"type": "string",
"description": "Python strftime format string. Examples: '%Y-%m-%d' for date only, '%H:%M' for hour:minute, '%Y-%m-%d %H:%M:%S' for full datetime.",
"default": "%Y-%m-%d %H:%M:%S"
}
},
"required": []
}
}Ví dụ phức tạp hơn — search_emails
Phân tích
- query là required
- from_sender, date_from, date_to optional — Claude sẽ pass nếu user mention
- max_results có default + min/max để tránh abuse
- pattern cho date validate format
search_emails_schema = {
"name": "search_emails",
"description": "Search user's email inbox by keywords, sender, or date range. Use when user asks to find emails, check inbox, or recall past conversations. Returns list of emails matching criteria.",
"input_schema": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "Search keywords to match in email subject or body"
},
"from_sender": {
"type": "string",
"description": "Filter by sender email address (optional)"
},
"date_from": {
"type": "string",
"description": "Start date in YYYY-MM-DD format (optional)",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"date_to": {
"type": "string",
"description": "End date in YYYY-MM-DD format (optional)",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"max_results": {
"type": "integer",
"description": "Max number of emails to return",
"minimum": 1,
"maximum": 50,
"default": 10
}
},
"required": ["query"]
}
}Tự generate schema bằng Claude
Thay vì viết schema thủ công, dùng Claude:
Prompt
Output (Claude generate)
Generate a JSON schema for tool calling for this Python function.
Follow Anthropic best practices.
Function:
def create_calendar_event(title, start_time, duration_minutes=60, attendees=None):
"""Create calendar event. Returns event ID."""
...
Reference: https://docs.anthropic.com/en/docs/build-with-claude/tool-useOutput (Claude generate)
Bạn chỉ cần review + adjust. Tiết kiệm 10 phút/schema.
{
"name": "create_calendar_event",
"description": "Create a new calendar event and return the event ID. Use when user asks to schedule meetings, appointments, or reminders.",
"input_schema": {
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Event title/subject"
},
"start_time": {
"type": "string",
"description": "Event start time in ISO 8601 format (e.g., '2026-04-20T14:00:00')"
},
"duration_minutes": {
"type": "integer",
"description": "Event duration in minutes",
"default": 60,
"minimum": 15
},
"attendees": {
"type": "array",
"items": {"type": "string"},
"description": "List of attendee email addresses (optional)"
}
},
"required": ["title", "start_time"]
}
}Type safety với ToolParam
Thay vì raw dict, dùng ToolParam type từ SDK:
Benefits
- IDE autocomplete
- Mypy type checking
- Catch schema typo trước runtime
from anthropic.types import ToolParam
get_weather_schema: ToolParam = {
"name": "get_weather",
"description": "...",
"input_schema": {
...
}
}Pass schema trong API call
Claude sẽ thấy tất cả schema và decide dùng cái nào (hoặc không dùng).
response = client.messages.create(
model=model,
max_tokens=1000,
messages=messages,
tools=[
get_weather_schema,
get_current_datetime_schema,
search_emails_schema,
], # ← List of schemas
)Organize schemas
Cho app nhiều tool, tách file:
Usage:
# tools/weather.py
def get_weather(location, unit="F"):
...
get_weather_schema = {...}
# tools/email.py
def search_emails(query, ...):
...
search_emails_schema = {...}
# tools/__init__.py
from .weather import get_weather, get_weather_schema
from .email import search_emails, search_emails_schema
ALL_TOOLS = [
{"schema": get_weather_schema, "function": get_weather},
{"schema": search_emails_schema, "function": search_emails},
]
ALL_SCHEMAS = [t["schema"] for t in ALL_TOOLS]
TOOL_FUNCTIONS = {t["schema"]["name"]: t["function"] for t in ALL_TOOLS}Organize schemas (tiếp)
response = client.messages.create(
tools=ALL_SCHEMAS,
...
)
# Sau này dispatch
if response.stop_reason == "tool_use":
tool_call = response.content[-1]
func = TOOL_FUNCTIONS[tool_call.name]
result = func(**tool_call.input)Anti-patterns
❌ Description quá ngắn
Claude không biết khi nào dùng. Fix: 3-4 sentences.
❌ Param name không rõ
"description": "Weather tool"❌ Param name không rõ
Fix: location, query, order_id — tên có ý nghĩa.
❌ Quên required
"properties": {"x": {"type": "string"}}❌ Quên required
Claude có thể pass incomplete, tool crash.
Fix: List required properly.
❌ Dùng any type
Không có any trong JSON Schema. Nếu cần flexible:
❌ Schema quá dài
15 nested levels → Claude overwhelm.
Fix: Flatten. Nếu nested cần → bẻ thành nhiều tool.
- oneOf cho multi type
- string rồi parse trong function
"required": [] // mọi field optionalÁp dụng ngay
Bài tập 1: Generate schema tool đầu tiên (15 phút)
Chọn 1 function cho app của bạn. Dùng Claude generate schema. Review + adjust.
Bài tập 2: Review schema quality (10 phút)
Cho schema bạn viết, check:
- [ ] Name snake_case, descriptive?
- [ ] Description 3-4 sentences?
- [ ] Mỗi property có description?
- [ ] required đúng?
- [ ] Có default cho optional params?
Tóm tắt
🎯 Schema = docstring cho Claude. Rõ ràng → Claude dùng tool đúng.
🎯 3 phần: name, description, input_schema. Description là quan trọng nhất.
🎯 Tự generate schema bằng Claude tiết kiệm 10 phút.
🎯 ToolParam type cho IDE autocomplete + type check.
🎯 Organize multi-tool qua ALL_SCHEMAS và TOOL_FUNCTIONS dict.