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
Mở đầu: Schema là "docstring" cho Claude
def get_weather(location: str, unit: str = "F"):
"""Get current weather for a location.
Args:
location: City name or airport code (e.g., "SF", "NYC")
unit: "F" for Fahrenheit or "C" for Celsius
Returns:
String describing current weather
"""
...
Tool schema y hệt, nhưng là JSON cho Claude đọc thay vì Python developer. Schema càng rõ → Claude dùng tool càng chính xác.
3 thành phần của schema
{
"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"]
}
}
1. name
- Snake_case
- Descriptive verb
- Match Python function name (convention)
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:
- 3-4 sentences
- Describe what tool does
- When Claude nên dùng
- What tool returns
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.
JSON Schema basics
Types
string— textinteger— số nguyênnumber— float / intboolean— true/falsearray— listobject— dict (nested)null— null value
Example object schema
{
"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"]
}
Additional constraints
enum: restrict to list of valuesdefault: default value if not providedminimum/maximum: numeric rangeminLength/maxLength: string lengthpattern: regex for stringdescription: per-field docs
Viết schema đầy đủ — Ví dụ get_current_datetime
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": []
}
}
Naming convention: function_name + function_name_schema. Dễ pair.
Ví dụ phức tạp hơn — search_emails
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"]
}
}
Phân tích
querylà requiredfrom_sender,date_from,date_tooptional — Claude sẽ pass nếu user mentionmax_resultscó default + min/max để tránh abusepatterncho date validate format
Tự generate schema bằng Claude
Thay vì viết schema thủ công, dùng Claude:
Prompt
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-use
Output (Claude generate)
{
"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"]
}
}
Bạn chỉ cần review + adjust. Tiết kiệm 10 phút/schema.
Type safety với ToolParam
Thay vì raw dict, dùng ToolParam type từ SDK:
from anthropic.types import ToolParam
get_weather_schema: ToolParam = {
"name": "get_weather",
"description": "...",
"input_schema": {
...
}
}
Benefits
- IDE autocomplete
- Mypy type checking
- Catch schema typo trước runtime
Pass schema trong API call
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
)
Claude sẽ thấy tất cả schema và decide dùng cái nào (hoặc không dùng).
Organize schemas
Cho app nhiều tool, tách file:
def get_weather(location, unit="F"):
...
get_weather_schema = {...}
def search_emails(query, ...):
...
search_emails_schema = {...}
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}
Usage:
response = client.messages.create(
tools=ALL_SCHEMAS,
...
)
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
"description": "Weather tool"
Claude không biết khi nào dùng. Fix: 3-4 sentences.
Param name không rõ
"properties": {"x": {"type": "string"}}
Fix: location, query, order_id — tên có ý nghĩa.
Quên required
"required": [] // mọi field optional
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:
oneOfcho multi typestringrồi parse trong function
Schema quá dài
15 nested levels → Claude overwhelm.
Fix: Flatten. Nếu nested cần → bẻ thành nhiều tool.
Á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 bài học
- 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_SCHEMASvàTOOL_FUNCTIONSdict.