{"product_id":"calculator-tool-bai-học-dầu-tien-về-tool-use-với-claude","title":"Calculator Tool — Bài học đầu tiên về Tool Use với Claude","description":"\n\u003cp\u003eTool Use (còn gọi là Function Calling) là một trong những tính năng mạnh nhất của Claude API. Thay vì chỉ trả lời bằng văn bản, Claude có thể \u003cstrong\u003equyết định gọi một công cụ bên ngoài\u003c\/strong\u003e — tìm kiếm web, tra cứu database, thực thi code — và sau đó tổng hợp kết quả thành câu trả lời hoàn chỉnh.\u003c\/p\u003e\n\n\u003cp\u003eBài này hướng dẫn bạn xây dựng tool đơn giản nhất có thể: một chiếc \u003cstrong\u003emáy tính bỏ túi\u003c\/strong\u003e. Mục tiêu không phải là sức mạnh của tool, mà là hiểu rõ \u003cstrong\u003evòng lặp Tool Use\u003c\/strong\u003e — cơ chế nền tảng cho mọi ứng dụng AI phức tạp hơn sau này.\u003c\/p\u003e\n\n\u003ch2\u003eTool Use hoạt động như thế nào?\u003c\/h2\u003e\n\n\u003cp\u003eHãy tưởng tượng bạn thuê một trợ lý thông minh nhưng không có điện thoại. Mỗi khi cần tìm thông tin, trợ lý đó phải \u003cem\u003eyêu cầu bạn\u003c\/em\u003e tra hộ, rồi sử dụng kết quả bạn trả về để hoàn thành công việc. Tool Use hoạt động theo đúng cơ chế đó:\u003c\/p\u003e\n\n\u003col\u003e\n  \u003cli\u003e\n\u003cstrong\u003eBạn\u003c\/strong\u003e định nghĩa danh sách tools và gửi cùng với user message\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eClaude\u003c\/strong\u003e đọc câu hỏi, quyết định cần dùng tool nào, trả về \u003ccode\u003etool_use\u003c\/code\u003e block\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eClient của bạn\u003c\/strong\u003e thực sự thực thi tool (ví dụ: tính toán, gọi API)\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eBạn\u003c\/strong\u003e gửi kết quả lại cho Claude qua \u003ccode\u003etool_result\u003c\/code\u003e block\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eClaude\u003c\/strong\u003e đọc kết quả, viết câu trả lời cuối cùng cho người dùng\u003c\/li\u003e\n\u003c\/ol\u003e\n\n\u003cp\u003eClaude \u003cstrong\u003ekhông tự thực thi tool\u003c\/strong\u003e. Claude chỉ ra quyết định \"cần dùng tool X với input Y\". Toàn bộ logic thực thi nằm ở phía client — đây là điểm quan trọng nhất cần nắm.\u003c\/p\u003e\n\n\u003ch2\u003eBước 1: Định nghĩa Tool với JSON Schema\u003c\/h2\u003e\n\n\u003cp\u003eMỗi tool được mô tả bằng một object JSON với 3 trường bắt buộc:\u003c\/p\u003e\n\n\u003cpre\u003e\u003ccode\u003ecalculator_tool = {\n    \"name\": \"calculator\",\n    \"description\": \"Thực hiện các phép tính số học cơ bản: cộng, trừ, nhân, chia.\",\n    \"input_schema\": {\n        \"type\": \"object\",\n        \"properties\": {\n            \"operation\": {\n                \"type\": \"string\",\n                \"enum\": [\"add\", \"subtract\", \"multiply\", \"divide\"],\n                \"description\": \"Phép tính cần thực hiện\"\n            },\n            \"operand1\": {\n                \"type\": \"number\",\n                \"description\": \"Số thứ nhất\"\n            },\n            \"operand2\": {\n                \"type\": \"number\",\n                \"description\": \"Số thứ hai\"\n            }\n        },\n        \"required\": [\"operation\", \"operand1\", \"operand2\"]\n    }\n}\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003cp\u003eBa trường quan trọng:\u003c\/p\u003e\n\u003cul\u003e\n  \u003cli\u003e\n\u003cstrong\u003ename\u003c\/strong\u003e — tên tool, Claude dùng tên này khi muốn gọi\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003edescription\u003c\/strong\u003e — mô tả ngắn gọn chức năng; Claude đọc description để quyết định khi nào dùng tool này\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003einput_schema\u003c\/strong\u003e — JSON Schema mô tả các parameters; Claude sẽ tạo ra JSON đúng format này khi gọi tool\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003cp\u003e\u003cstrong\u003eLưu ý quan trọng:\u003c\/strong\u003e Viết description thật rõ ràng. Nếu description mơ hồ, Claude có thể gọi tool sai lúc hoặc không gọi khi cần.\u003c\/p\u003e\n\n\u003ch2\u003eBước 2: Gửi Request với Tools\u003c\/h2\u003e\n\n\u003cpre\u003e\u003ccode\u003eimport anthropic\n\nclient = anthropic.Anthropic()\n\nresponse = client.messages.create(\n    model=\"claude-opus-4-5\",\n    max_tokens=1024,\n    tools=[calculator_tool],\n    messages=[\n        {\n            \"role\": \"user\",\n            \"content\": \"Tính 1984 nhan 1984 bằng bao nhiêu?\"\n        }\n    ]\n)\n\nprint(\"Stop reason:\", response.stop_reason)\nprint(\"Content:\", response.content)\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003cp\u003eKhác biệt duy nhất so với API call thông thường: thêm parameter \u003ccode\u003etools=[...]\u003c\/code\u003e.\u003c\/p\u003e\n\n\u003ch2\u003eBước 3: Xử lý Response tool_use\u003c\/h2\u003e\n\n\u003cp\u003eKhi Claude muốn gọi tool, response sẽ có \u003ccode\u003estop_reason = \"tool_use\"\u003c\/code\u003e và content chứa \u003ccode\u003etool_use\u003c\/code\u003e block:\u003c\/p\u003e\n\n\u003cpre\u003e\u003ccode\u003e# Response từ Claude:\n# stop_reason = \"tool_use\"\n# content = [\n#   TextBlock(text=\"De tinh 1984 x 1984, toi se dung calculator.\"),\n#   ToolUseBlock(\n#       id=\"toolu_01ABC123\",\n#       name=\"calculator\",\n#       input={\"operation\": \"multiply\", \"operand1\": 1984, \"operand2\": 1984}\n#   )\n# ]\n\ndef process_tool_call(tool_name, tool_input):\n    if tool_name == \"calculator\":\n        op = tool_input[\"operation\"]\n        a = tool_input[\"operand1\"]\n        b = tool_input[\"operand2\"]\n\n        if op == \"add\":\n            return a + b\n        elif op == \"subtract\":\n            return a - b\n        elif op == \"multiply\":\n            return a * b\n        elif op == \"divide\":\n            if b == 0:\n                return \"Loi: Khong the chia cho 0\"\n            return a \/ b\n    return \"Tool khong ton tai\"\n\n# Tim tool_use block trong response\ntool_use_block = None\nfor block in response.content:\n    if block.type == \"tool_use\":\n        tool_use_block = block\n        break\n\nif tool_use_block:\n    result = process_tool_call(tool_use_block.name, tool_use_block.input)\n    print(f\"Ket qua tinh toan: {result}\")\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eBước 4: Gửi Kết quả về cho Claude\u003c\/h2\u003e\n\n\u003cp\u003eĐây là bước nhiều người mắc lỗi nhất. Bạn phải gửi \u003cem\u003etoàn bộ conversation history\u003c\/em\u003e kèm theo kết quả tool:\u003c\/p\u003e\n\n\u003cpre\u003e\u003ccode\u003efinal_response = client.messages.create(\n    model=\"claude-opus-4-5\",\n    max_tokens=1024,\n    tools=[calculator_tool],\n    messages=[\n        # Message gốc của user\n        {\n            \"role\": \"user\",\n            \"content\": \"Tinh 1984 nhan 1984 bang bao nhieu?\"\n        },\n        # Response của Claude (bao gồm tool_use block)\n        {\n            \"role\": \"assistant\",\n            \"content\": response.content  # Giu nguyen content object\n        },\n        # Kết quả tool từ client\n        {\n            \"role\": \"user\",\n            \"content\": [\n                {\n                    \"type\": \"tool_result\",\n                    \"tool_use_id\": tool_use_block.id,  # ID phải khớp\n                    \"content\": str(result)\n                }\n            ]\n        }\n    ]\n)\n\nprint(final_response.content[0].text)\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003cp\u003eClaude sẽ đọc kết quả \u003ccode\u003e3936256\u003c\/code\u003e và viết câu trả lời như: \u003cem\u003e\"1984 nhân 1984 bằng 3.936.256.\"\u003c\/em\u003e\u003c\/p\u003e\n\n\u003ch2\u003eVòng lặp Tool Use đầy đủ\u003c\/h2\u003e\n\n\u003cp\u003eGộp tất cả lại thành một hàm hoàn chỉnh:\u003c\/p\u003e\n\n\u003cpre\u003e\u003ccode\u003edef run_tool_loop(user_message):\n    messages = [{\"role\": \"user\", \"content\": user_message}]\n\n    while True:\n        response = client.messages.create(\n            model=\"claude-opus-4-5\",\n            max_tokens=1024,\n            tools=[calculator_tool],\n            messages=messages\n        )\n\n        # Neu Claude tra loi binh thuong, ket thuc vong lap\n        if response.stop_reason == \"end_turn\":\n            return response.content[0].text\n\n        # Neu Claude muon goi tool\n        if response.stop_reason == \"tool_use\":\n            # Them response cua Claude vao history\n            messages.append({\"role\": \"assistant\", \"content\": response.content})\n\n            # Xu ly tung tool_use block\n            tool_results = []\n            for block in response.content:\n                if block.type == \"tool_use\":\n                    result = process_tool_call(block.name, block.input)\n                    tool_results.append({\n                        \"type\": \"tool_result\",\n                        \"tool_use_id\": block.id,\n                        \"content\": str(result)\n                    })\n\n            # Them ket qua vao history\n            messages.append({\"role\": \"user\", \"content\": tool_results})\n\n        else:\n            # Stop reason khong mong doi\n            break\n\n    return None\n\n# Test\nanswer = run_tool_loop(\"125 chia 5 roi nhan 8 bang bao nhieu?\")\nprint(answer)\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003cp\u003eVòng \u003ccode\u003ewhile True\u003c\/code\u003e quan trọng vì một số câu hỏi yêu cầu \u003cstrong\u003enhiều lần gọi tool\u003c\/strong\u003e. Ví dụ: \u003cem\u003e\"125 chia 5 rồi nhân 8\"\u003c\/em\u003e — Claude sẽ gọi calculator 2 lần: một lần chia, một lần nhân.\u003c\/p\u003e\n\n\u003ch2\u003eKiểm tra Thực tế\u003c\/h2\u003e\n\n\u003cpre\u003e\u003ccode\u003etest_cases = [\n    \"15 cong 27 bang bao nhieu?\",\n    \"Dien tich hinh tron ban kinh 7cm la bao nhieu? (Pi = 3.14159)\",\n    \"Neu toi mua 3 san pham gia 250.000 dong moi cai, tong tien la bao nhieu?\"\n]\n\nfor question in test_cases:\n    print(f\"Cau hoi: {question}\")\n    print(f\"Tra loi: {run_tool_loop(question)}\")\n    print(\"---\")\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003cp\u003eCâu hỏi thứ hai thú vị: Claude sẽ tự chia nhỏ thành \u003cem\u003e7 nhân 7 = 49\u003c\/em\u003e, rồi \u003cem\u003e49 nhân 3.14159\u003c\/em\u003e — hai lần gọi tool để tính diện tích.\u003c\/p\u003e\n\n\u003ch2\u003eNhững điểm cần nhớ\u003c\/h2\u003e\n\n\u003ctable\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n\u003cth\u003eKhái niệm\u003c\/th\u003e\n\u003cth\u003eChi tiết\u003c\/th\u003e\n\u003c\/tr\u003e\n  \u003c\/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003estop_reason\u003c\/code\u003e\u003c\/td\u003e\n\u003ctd\u003e\n\u003ccode\u003e\"tool_use\"\u003c\/code\u003e = Claude muốn gọi tool; \u003ccode\u003e\"end_turn\"\u003c\/code\u003e = Claude trả lời xong\u003c\/td\u003e\n\u003c\/tr\u003e\n    \u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003etool_use_id\u003c\/code\u003e\u003c\/td\u003e\n\u003ctd\u003eID duy nhất cho mỗi lần gọi tool; phải khớp trong \u003ccode\u003etool_result\u003c\/code\u003e\n\u003c\/td\u003e\n\u003c\/tr\u003e\n    \u003ctr\u003e\n\u003ctd\u003eTool execution\u003c\/td\u003e\n\u003ctd\u003eClient thực thi, không phải Claude — bạn có toàn quyền kiểm soát\u003c\/td\u003e\n\u003c\/tr\u003e\n    \u003ctr\u003e\n\u003ctd\u003eMulti-turn\u003c\/td\u003e\n\u003ctd\u003eGiữ nguyên toàn bộ history; không bỏ tool_use blocks giữa chừng\u003c\/td\u003e\n\u003c\/tr\u003e\n    \u003ctr\u003e\n\u003ctd\u003eMultiple tools\u003c\/td\u003e\n\u003ctd\u003eMột lần gọi có thể trả về nhiều tool_use blocks — xử lý hết trước khi gửi lại\u003c\/td\u003e\n\u003c\/tr\u003e\n  \u003c\/tbody\u003e\n\u003c\/table\u003e\n\n\u003ch2\u003eKhi nào Claude gọi Tool?\u003c\/h2\u003e\n\n\u003cp\u003eClaude chỉ gọi tool khi thực sự cần. Nếu bạn hỏi \u003cem\u003e\"2 + 2 bằng mấy?\"\u003c\/em\u003e, Claude có thể trả lời thẳng mà không cần calculator. Tool Use được kích hoạt khi:\u003c\/p\u003e\n\n\u003cul\u003e\n  \u003cli\u003eCâu hỏi yêu cầu độ chính xác cao (phép tính phức tạp)\u003c\/li\u003e\n  \u003cli\u003eClaude không chắc về con số cụ thể\u003c\/li\u003e\n  \u003cli\u003eDescription của tool rõ ràng match với yêu cầu\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003cp\u003eBài tiếp theo, chúng ta sẽ khám phá cách dùng Tool Use để \u003cstrong\u003eép Claude output JSON có cấu trúc\u003c\/strong\u003e — một kỹ thuật cực kỳ hữu ích mà không cần viết regex phức tạp.\u003c\/p\u003e\n\n\u003chr\u003e\n\u003ch3\u003eBài viết liên quan\u003c\/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"\/en\/products\/extended-thinking-tool-use-suy-lu%E1%BA%ADn-sau-k%E1%BA%BFt-h%E1%BB%A3p-cong-c%E1%BB%A5\"\u003eExtended Thinking + Tool Use — Suy luận sâu kết hợp công cụ\u003c\/a\u003e\u003c\/li\u003e\n\u003cli\u003e\u003ca href=\"\/en\/products\/crop-tool-cho-claude-kh%E1%BA%A3-nang-zoom-vao-chi-ti%E1%BA%BFt-hinh-%E1%BA%A3nh\"\u003eCrop Tool — Cho Claude khả năng zoom vào chi tiết hình ảnh\u003c\/a\u003e\u003c\/li\u003e\n\u003cli\u003e\u003ca href=\"\/en\/products\/react-agent-v%E1%BB%9Bi-llamaindex-claude-ly-lu%E1%BA%ADn-hanh-d%E1%BB%99ng\"\u003eReAct Agent với LlamaIndex + Claude — Lý luận + Hành động\u003c\/a\u003e\u003c\/li\u003e\n\u003cli\u003e\u003ca href=\"\/en\/products\/claude-api-h%C6%B0%E1%BB%9Bng-d%E1%BA%ABn-t%E1%BB%AB-a-d%E1%BA%BFn-z-cho-developer\"\u003eClaude API — Hướng dẫn từ A đến Z cho developer\u003c\/a\u003e\u003c\/li\u003e\n\u003cli\u003e\u003ca href=\"\/en\/products\/claude-cho-engineering-debug-va-x%E1%BB%AD-ly-l%E1%BB%97i\"\u003eClaude cho Engineering: Debug và xử lý lỗi\u003c\/a\u003e\u003c\/li\u003e\n\u003c\/ul\u003e","brand":"Minh Tuấn","offers":[{"title":"Default Title","offer_id":47721764618452,"sku":null,"price":0.0,"currency_code":"VND","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0821\/0264\/9044\/files\/calculator-tool-bai-h_c-d_u-tien-v_-tool-use-v_i-claude.jpg?v=1774521024","url":"https:\/\/claude.vn\/en\/products\/calculator-tool-bai-h%e1%bb%8dc-d%e1%ba%a7u-tien-v%e1%bb%81-tool-use-v%e1%bb%9bi-claude","provider":"CLAUDE.VN","version":"1.0","type":"link"}