Bài 6.36 đã có 3 tools. Adding thêm tools = làm thế nào?
- Thêm tool mới vào existing system mà không refactor
- Hiểu pattern scalable cho 5-20 tools
- Test scenarios yêu cầu Claude combine nhiều tool
- Optimize tool selection qua description quality
4-step để thêm tool
Bước 1: Viết function
Bước 2: Define schema
@register_tool("search_web")
def search_web(query: str, max_results: int = 5) -> str:
# ... call search API
return formatted_resultsBước 2: Define schema
Bước 3: Add vào schemas list
search_web_schema = {
"name": "search_web",
"description": "Search the web for current information. Use when user asks about recent events, facts, or information not in your training data.",
"input_schema": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "Search query"},
"max_results": {"type": "integer", "default": 5}
},
"required": ["query"]
}
}Bước 3: Add vào schemas list
Bước 4: Test
ALL_TOOLS = [
get_current_datetime_schema,
add_duration_to_datetime_schema,
set_reminder_schema,
search_web_schema, # ← thêm
]Bước 4: Test
Xong. Không refactor code chính.
final, _ = run_conversation(
"What's the latest news about Anthropic?",
tools=ALL_TOOLS
)Test scenarios — force Claude dùng nhiều tool
Scenario 1: Sequential (output tool 1 → input tool 2)
Claude flow:
Scenario 2: Parallel
- add_duration_to_datetime(2050-01-01, 177, days) → 2050-06-27
- set_reminder("doctor's appointment", "2050-06-27T...") → confirmation
"Set a reminder for my doctor's appointment. It's 177 days after Jan 1st, 2050."Scenario 2: Parallel
Claude có thể request 2 tool trong 1 turn:
Bạn execute cả 2, send back results cùng lúc.
Scenario 3: Mixed (text + tool + text)
- add(10, 10)
- add(30, 30)
"What's 10+10 and 30+30?"Scenario 3: Mixed (text + tool + text)
Claude có thể:
- Turn 1: Output joke (text only)
- Turn 2: Call get_weather(SF)
- Turn 3: Translate joke (text only)
"Tell me a joke, then check current weather in SF, then translate joke to Vietnamese."Quality tool description = Claude dùng đúng tool
Tool description giúp Claude decide khi nào dùng tool nào. Bad description → Claude pick sai.
Bad
Cùng 1 function conceptually, Claude confused.
Good
tool1_schema = {"name": "search", "description": "Search things"}
tool2_schema = {"name": "query", "description": "Query information"}Good
Explicit về when NOT to use → Claude pick đúng.
search_emails_schema = {
"name": "search_emails",
"description": "Search user's email inbox. Use ONLY for finding emails. For web search use search_web. For internal knowledge base use search_docs."
}
search_web_schema = {
"name": "search_web",
"description": "Search the public web. Use for current events, facts from external sources. DO NOT use for emails or internal docs."
}
search_docs_schema = {
"name": "search_docs",
"description": "Search internal company knowledge base. Use for company policies, internal documentation. DO NOT use for email or web."
}Tool organization: 5+ tools
File tools/ với các module:
tools/__init__.py:
App imports:
tools/ ├── __init__.py # Export ALL_TOOLS ├── datetime.py # Date/time tools ├── email.py # Email tools ├── search.py # Search tools ├── calendar.py # Calendar tools └── file.py # File ops tools
from .datetime import (
get_current_datetime, get_current_datetime_schema,
add_duration_to_datetime, add_duration_to_datetime_schema,
)
from .email import search_emails, search_emails_schema
# ... etc
ALL_TOOLS = [
get_current_datetime_schema,
add_duration_to_datetime_schema,
search_emails_schema,
# ... etc
]Tool organization: 5+ tools (tiếp)
from tools import ALL_TOOLS
from tools import TOOL_FUNCTIONS # registered via decorator
run_conversation(user_msg, tools=ALL_TOOLS)Selective tool exposure
Không phải conversation nào cần tất cả tool. Expose theo context:
Giảm tool count → Claude pick chính xác hơn + cost thấp hơn (schemas tốn token).
# Customer service agent
CUSTOMER_SERVICE_TOOLS = [
get_order_status_schema,
create_refund_request_schema,
search_kb_schema
]
# Sales agent
SALES_TOOLS = [
lookup_customer_schema,
create_quote_schema,
schedule_meeting_schema
]
def run_agent(user_msg: str, agent_type: str):
tools_map = {
"customer_service": CUSTOMER_SERVICE_TOOLS,
"sales": SALES_TOOLS
}
return run_conversation(user_msg, tools=tools_map[agent_type])Parallel tool execution
Khi Claude request nhiều tool independent (không phụ thuộc nhau), execute parallel:
Nếu Claude call 5 API parallel, mỗi mất 1s → async tổng 1s (vs 5s sync).
import asyncio
async def run_tools_parallel(tool_uses):
async def _run_one(tu):
try:
output = await asyncio.to_thread(run_tool, tu.name, tu.input)
return {
"type": "tool_result",
"tool_use_id": tu.id,
"content": str(output),
"is_error": False
}
except Exception as e:
return {
"type": "tool_result",
"tool_use_id": tu.id,
"content": str(e),
"is_error": True
}
results = await asyncio.gather(*(_run_one(tu) for tu in tool_uses))
return resultsTool performance metrics
Track mỗi tool:
Insight:
- Tool nào dùng nhiều → optimize first
- Tool nào error rate cao → debug
- Tool nào slow → cache hoặc async
from collections import defaultdict
import time
tool_metrics = defaultdict(lambda: {"calls": 0, "errors": 0, "total_time": 0})
def run_tool_tracked(name, input_data):
start = time.time()
try:
result = run_tool(name, input_data)
tool_metrics[name]["calls"] += 1
return result
except Exception as e:
tool_metrics[name]["errors"] += 1
raise
finally:
tool_metrics[name]["total_time"] += time.time() - start
# Report
for name, m in tool_metrics.items():
avg_time = m["total_time"] / m["calls"] if m["calls"] > 0 else 0
error_rate = m["errors"] / m["calls"] if m["calls"] > 0 else 0
print(f"{name}: {m['calls']} calls, {error_rate:.1%} error, {avg_time:.2f}s avg")Anti-patterns
❌ 20 tools, không organization
Flat list → messy, hard to maintain.
Fix: Tách module theo domain.
❌ Expose all tools cho mọi context
Tool "admin_delete_user" exposed cho chatbot public.
Fix: Scoped tools theo role/context.
❌ Tool description giống nhau
Claude confused pick.
Fix: Description rõ + "don't use for X" để guide.
❌ Sequential execution khi parallel có thể
5 independent tool, chạy sync → 5x slower.
Fix: asyncio.gather parallel.
Áp dụng ngay
Bài tập 1: Add 3 tools mới (30 phút)
Cho reminder app, add:
Test scenario: "Show my reminders, delete the one about dentist, update the work meeting to 'team standup'."
Bài tập 2: Parallel execution (20 phút)
Scenario: "Get weather in SF, NYC, Tokyo."
Claude request 3 get_weather calls. Implement parallel với asyncio. Đo thời gian sync vs async.
- list_reminders() — list upcoming reminders
- delete_reminder(id) — delete by ID
- update_reminder(id, new_text) — update
Tóm tắt
🎯 Adding tool = 4 bước: function + schema + add to list + test. Không refactor.
🎯 Scale 10+ tools: organize modules, selective exposure, metrics.
🎯 Tool description quality quyết định Claude pick đúng.
🎯 Parallel execution cho independent tools → speedup 5-10x.
🎯 Track metrics per tool cho observability production.