Trung cấpHướng dẫnClaude

Xây dựng Customer Service Agent với Claude Tool Use

Điểm nổi bật

Nhấn để đến mục tương ứng

  1. 1Khai thác tối đa công cụ AI: Agent của chúng ta cần 3 tools để phục vụ khách hàng: Tool 1: getcustomerinfo getcustomerinfo = { "name":. Bí quyết nằm ở cách bạn cấu trúc yêu cầu — prompt càng rõ ràng, output càng sát nhu cầu thực tế.
  2. 2Góc nhìn thực tế: Thay vì kết nối database thực, chúng ta dùng data tĩnh để demo: CUSTOMERS = { "CUST-001": { "name": "Nguyen Thi Mai",. Điều quan trọng là hiểu rõ khi nào nên và không nên áp dụng phương pháp này.
  3. 3Lợi ích đo lường được: import anthropic client = anthropic.Anthropic SYSTEMPROMPT = """Ban la nhan vien ho tro khach hang cua ShopViet - mot. Phương pháp này giúp tiết kiệm đáng kể thời gian so với cách làm truyền thống.
  4. 4Bước đầu tiên bạn nên làm: def democonversation: print"=== Customer Service Agent Demo === " history = Turn 1: Xem don hang response, history =. Áp dụng đúng cách sẽ thấy kết quả rõ rệt từ tuần đầu tiên.
  5. 5Cần lưu ý: Authentication trong tools — Luôn verify user có quyền với resource họ request. Không phải lúc nào AI cũng cho kết quả hoàn hảo — bạn vẫn cần kiểm tra và điều chỉnh output trước khi sử dụng chính thức.
Xây dựng Customer Service Agent với Claude Tool Use

Xây dựng chatbot customer service hoàn chỉnh với 3 tools: tra cứu khách hàng, xem đơn hàng, hủy đơn — từ tool definition đến multi-turn conversation.

Trong bài này, chúng ta sẽ xây dựng một Customer Service Agent hoàn chỉnh — chatbot có thể tra cứu thông tin khách hàng, xem chi tiết đơn hàng, và thực hiện hủy đơn. Đây là ứng dụng Tool Use thực tế nhất, gần với production deployment nhất.

Điểm khác biệt với bài Calculator: ở đây chúng ta có multi-turn conversation, nhiều tools tương tác với nhau, và business logic phức tạp hơn. Kết thúc bài, bạn sẽ có một agent có thể xử lý cuộc hội thoại như:

"Tôi muốn hủy đơn hàng #12345 của tôi."
[Claude tra cứu đơn hàng, kiểm tra điều kiện hủy, thực hiện hủy, xác nhận với khách]

Thiết kế 3 Tools

Agent của chúng ta cần 3 tools để phục vụ khách hàng:

Tool 1: get_customer_info

get_customer_info = {
    "name": "get_customer_info",
    "description": "Tra cuu thong tin khach hang theo customer_id hoac email",
    "input_schema": {
        "type": "object",
        "properties": {
            "identifier": {
                "type": "string",
                "description": "Customer ID (VD: CUST-001) hoac dia chi email"
            }
        },
        "required": ["identifier"]
    }
}

Tool 2: get_order_details

get_order_details = {
    "name": "get_order_details",
    "description": "Xem chi tiet don hang theo order_id",
    "input_schema": {
        "type": "object",
        "properties": {
            "order_id": {
                "type": "string",
                "description": "Ma don hang, bat dau bang #"
            }
        },
        "required": ["order_id"]
    }
}

Tool 3: cancel_order

cancel_order = {
    "name": "cancel_order",
    "description": "Huy don hang. Chi huy duoc don hang co trang thai pending hoac processing.",
    "input_schema": {
        "type": "object",
        "properties": {
            "order_id": {
                "type": "string",
                "description": "Ma don hang can huy"
            },
            "reason": {
                "type": "string",
                "description": "Ly do huy don hang"
            }
        },
        "required": ["order_id", "reason"]
    }
}

Chú ý description của cancel_order có ghi rõ điều kiện: "Chỉ hủy được đơn hàng có trạng thái pending hoặc processing." Claude đọc thông tin này và sẽ không cố gọi tool với đơn hàng đã giao.

Dữ liệu mẫu (Synthetic Backend)

Thay vì kết nối database thực, chúng ta dùng data tĩnh để demo:

CUSTOMERS = {
    "CUST-001": {
        "name": "Nguyen Thi Mai",
        "email": "mai.nguyen@email.com",
        "phone": "0901234567",
        "loyalty_points": 1250,
        "membership": "Gold"
    },
    "CUST-002": {
        "name": "Tran Van Hung",
        "email": "hung.tran@email.com",
        "phone": "0912345678",
        "loyalty_points": 320,
        "membership": "Silver"
    }
}

ORDERS = {
    "#12345": {
        "customer_id": "CUST-001",
        "status": "processing",
        "items": [
            {"name": "Ao thun nam", "qty": 2, "price": 250000},
            {"name": "Quan jeans", "qty": 1, "price": 650000}
        ],
        "total": 1150000,
        "created_at": "2026-03-20"
    },
    "#12346": {
        "customer_id": "CUST-001",
        "status": "delivered",
        "items": [
            {"name": "Giay the thao", "qty": 1, "price": 1200000}
        ],
        "total": 1200000,
        "created_at": "2026-03-10"
    }
}

Implement Tool Execution

import json

def execute_tool(tool_name, tool_input):
    """Xu ly tat ca cac tool calls tu Claude"""

    if tool_name == "get_customer_info":
        identifier = tool_input["identifier"]

        # Tim theo customer_id
        if identifier in CUSTOMERS:
            return json.dumps(CUSTOMERS[identifier], ensure_ascii=False)

        # Tim theo email
        for cust_id, cust_data in CUSTOMERS.items():
            if cust_data["email"] == identifier:
                return json.dumps({**cust_data, "customer_id": cust_id}, ensure_ascii=False)

        return json.dumps({"error": "Khong tim thay khach hang"})

    elif tool_name == "get_order_details":
        order_id = tool_input["order_id"]
        if order_id in ORDERS:
            order = ORDERS[order_id]
            # Tinh tong cho dep hon
            formatted = {
                **order,
                "order_id": order_id,
                "total_formatted": f"{order['total']:,}d"
            }
            return json.dumps(formatted, ensure_ascii=False)
        return json.dumps({"error": f"Don hang {order_id} khong ton tai"})

    elif tool_name == "cancel_order":
        order_id = tool_input["order_id"]
        reason = tool_input["reason"]

        if order_id not in ORDERS:
            return json.dumps({"success": False, "message": "Don hang khong ton tai"})

        order = ORDERS[order_id]
        if order["status"] not in ["pending", "processing"]:
            return json.dumps({
                "success": False,
                "message": f"Khong the huy don hang co trang thai '{order['status']}'"
            })

        # Thuc hien huy (trong demo, chi cap nhat in-memory)
        ORDERS[order_id]["status"] = "cancelled"
        return json.dumps({
            "success": True,
            "message": f"Don hang {order_id} da duoc huy thanh cong",
            "refund_amount": order["total"]
        })

    return json.dumps({"error": "Tool khong ton tai"})

Agent Loop với Multi-turn Support

import anthropic

client = anthropic.Anthropic()

SYSTEM_PROMPT = """Ban la nhan vien ho tro khach hang cua ShopViet - mot san thuong mai dien tu Viet Nam.
Ban co the:
- Tra cuu thong tin tai khoan khach hang
- Xem chi tiet don hang
- Ho tro huy don hang (chi don chua giao)

Hay luon lich su, than thien va nhanh chong giai quyet van de cua khach.
Neu khach hang chua cung cap du thong tin, hay hoi them truoc khi thuc hien tham so."""

ALL_TOOLS = [get_customer_info, get_order_details, cancel_order]

def run_customer_service_agent(user_message, conversation_history=None):
    """
    Chay agent voi lich su hoi thoai (ho tro multi-turn).
    conversation_history: list cac messages truoc do
    """
    if conversation_history is None:
        conversation_history = []

    # Them message moi cua user
    conversation_history.append({
        "role": "user",
        "content": user_message
    })

    while True:
        response = client.messages.create(
            model="claude-opus-4-5",
            max_tokens=2048,
            system=SYSTEM_PROMPT,
            tools=ALL_TOOLS,
            messages=conversation_history
        )

        # Them response cua Claude vao history
        conversation_history.append({
            "role": "assistant",
            "content": response.content
        })

        # Neu Claude da tra loi xong
        if response.stop_reason == "end_turn":
            # Lay text cuoi cung
            final_text = ""
            for block in response.content:
                if hasattr(block, "text"):
                    final_text += block.text
            return final_text, conversation_history

        # Xu ly tool calls
        if response.stop_reason == "tool_use":
            tool_results = []

            for block in response.content:
                if block.type == "tool_use":
                    print(f"[DEBUG] Claude goi tool: {block.name}({block.input})")
                    result = execute_tool(block.name, block.input)
                    tool_results.append({
                        "type": "tool_result",
                        "tool_use_id": block.id,
                        "content": result
                    })

            # Them ket qua tool vao history
            conversation_history.append({
                "role": "user",
                "content": tool_results
            })

        else:
            break

    return "", conversation_history

Demo: Cuộc hội thoại thực tế

def demo_conversation():
    print("=== Customer Service Agent Demo ===
")
    history = []

    # Turn 1: Xem don hang
    response, history = run_customer_service_agent(
        "Xin chao! Toi muon kiem tra don hang #12345 cua toi",
        history
    )
    print(f"Agent: {response}
")

    # Turn 2: Yeu cau huy
    response, history = run_customer_service_agent(
        "Toi muon huy don hang do vi toi dat nham mau. Duoc khong?",
        history
    )
    print(f"Agent: {response}
")

    # Turn 3: Xac nhan huy
    response, history = run_customer_service_agent(
        "Vang, toi xac nhan muon huy. Cam on ban.",
        history
    )
    print(f"Agent: {response}
")

    # Turn 4: Hoi ve don da giao (test edge case)
    response, history = run_customer_service_agent(
        "Con don hang #12346 toi cung muon huy duoc khong?",
        history
    )
    print(f"Agent: {response}
")

demo_conversation()

Output mong đợi:

[DEBUG] Claude goi tool: get_order_details({'order_id': '#12345'})
Agent: Toi da kiem tra don hang #12345 cua ban:
- 2x Ao thun nam: 500.000d
- 1x Quan jeans: 650.000d
- Tong: 1.150.000d
- Trang thai: Dang xu ly

Ban can ho tro gi voi don hang nay?

[DEBUG] Claude goi tool: cancel_order({'order_id': '#12345', 'reason': 'dat nham mau'})
Agent: Toi da huy thanh cong don hang #12345 cho ban.
So tien 1.150.000d se duoc hoan tra trong 3-5 ngay lam viec.

[DEBUG] Claude goi tool: get_order_details({'order_id': '#12346'})
Agent: Rat tiec, don hang #12346 (Giay the thao) da duoc giao thanh cong
nen khong the huy. Neu san pham co van de, ban co the yeu cau doi/tra
hang trong vong 7 ngay.

Xử lý Multiple Tool Calls

Đôi khi Claude cần gọi nhiều tools trong một lượt. Ví dụ: "Kiểm tra thông tin tài khoản và tất cả đơn hàng của tôi là CUST-001" — Claude có thể gọi get_customer_info và sau đó gọi get_order_details nhiều lần.

Code của chúng ta đã xử lý điều này trong vòng lặp for block in response.content — nó thu thập tất cả tool_use blocks trước khi gửi tất cả kết quả một lúc.

Best Practices cho Production

  • Authentication trong tools — Luôn verify user có quyền với resource họ request. Ví dụ: kiểm tra customer_id trong order khớp với user đang đăng nhập.
  • Error handling rõ ràng — Tools nên trả về error messages thân thiện thay vì raise exceptions.
  • Rate limiting — Giới hạn số lần gọi tool trong một session để tránh abuse.
  • Audit logging — Log tất cả tool calls với user_id, timestamp, input/output để debug và compliance.
  • Tool description cụ thể — Mô tả rõ điều kiện, giới hạn của từng tool để Claude không thử gọi tool sai lúc.

Mở rộng Agent

Từ skeleton này, bạn có thể thêm nhiều tools hơn:

  • search_products — Tìm kiếm sản phẩm theo tên, category
  • update_shipping_address — Cập nhật địa chỉ giao hàng (chỉ trước khi ship)
  • create_return_request — Tạo yêu cầu đổi/trả hàng
  • check_loyalty_rewards — Xem điểm tích lũy và ưu đãi
  • escalate_to_human — Chuyển sang nhân viên thật khi cần

Bài tiếp theo: tìm hiểu tool_choice parameter — cách kiểm soát chính xác khi nào Claude gọi tool, khi nào không, và cách ép buộc Claude dùng một tool cụ thể.

Bài viết có hữu ích không?

Bản quyền thuộc về tác giả. Vui lòng dẫn nguồn khi chia sẻ.

← Bài trước
Marketing Playbook — Claude cho marketers
Bài sau →
Agentic Coding — Phần 4: Bảo mật codebase khi dùng AI coding agent

Bình luận (0)

Khách
Bạn cần để bình luận