FDE PulseViệc làm FDE đang mở 316Mới đăng 7 ngày qua 10Chủ đề nổi bật: Đào tạo kỹ năng FDE tại Đông Nam Á

Tờ báo của nghề Forward Deployed Engineer

Bách khoa

Tool calling: mô hình chỉ đề xuất, còn code của bạn mới thực thi

Khi agent “tự hoàn tiền” trong buổi demo, thứ thực sự cầm tiền của khách hàng là đoạn vòng lặp vài chục dòng do FDE viết, chứ không phải mô hình.

Đồ hoạMột vòng khứ hồi của tool calling
  1. 1Mô hình đề xuấtAPI trả về khối tool_use gồm tên tool và JSON đối số, stop_reason là tool_use
  2. 2Code trích đối sốỨng dụng đọc tên tool và đối số từ khối tool_use
  3. 3Code kiểm tra và thực thiKiểm tra nghiệp vụ, rồi gọi database, HTTP hoặc tạo yêu cầu chờ duyệt
  4. 4Gửi tool_resultTrả kết quả hoặc lỗi có hướng dẫn sửa trong request kế tiếp
  5. 5Mô hình đi tiếpLặp lại khi còn tool_use, gặp stop_reason khác thì thoát vòng

Mô hình chỉ viết yêu cầu, còn mọi bước kiểm tra và thực thi nằm trong code của bạn.

Đồ hoạ: FDE Times

Tóm tắt nhanh

  • Mô hình không tự thực thi gì. Nó chỉ trả về tên tool và JSON đối số, còn ứng dụng của bạn chạy thao tác rồi gửi tool_result.
  • Strict mode và enum giúp lời gọi bám đúng schema. Riêng các quy tắc nghiệp vụ như hạn mức hay quyền hạn vẫn phải kiểm tra trong code.
  • Thông báo lỗi trả về cho agent phải nói rõ cần sửa gì. Kết quả dài thì phải phân trang, lọc hoặc cắt ngắn.
Chia sẻLinkedInFacebookX

Buổi demo đang suôn sẻ. Agent chăm sóc khách hàng vừa nhận câu “đơn giao sai màu, hoàn tiền giúp tôi” và trả lời rằng yêu cầu hoàn tiền đã được tạo. Giám đốc vận hành phía khách hàng nhíu mày rồi hỏi một câu mà FDE nào cũng sẽ gặp: “Vậy là con AI này tự động vào hệ thống thanh toán của chúng tôi à?”

Câu trả lời đúng là không, và FDE phải giải thích được vì sao không. Nếu bạn chỉ nói “mô hình gọi API”, khách sẽ hình dung một cỗ máy tự do bấm nút trong hệ thống của họ. Nếu bạn hiểu đúng cơ chế, bạn chỉ ra được cho họ chỗ đặt chốt chặn, và cuộc trao đổi về bảo mật sẽ đi theo hướng khác hẳn.

Kỹ năng này là nền móng của mọi deployment có agent. Ai hiểu nhầm tool calling sẽ viết integration lỏng lẻo. Ai hiểu đúng sẽ thiết kế được một tầng tool mà cả đội bảo mật lẫn agent đều tin tưởng.

Mô hình không bấm nút nào cả

Tài liệu của Anthropic mô tả hợp đồng này rất thẳng: mô hình không bao giờ tự thực thi gì. Nó phát ra một yêu cầu có cấu trúc, code của bạn chạy thao tác, và kết quả quay lại cuộc hội thoại.

Google viết gần như cùng một câu cho Gemini API: mô hình không tự chạy hàm, ứng dụng trích tên hàm và đối số rồi tự thực thi.

OpenAI mô tả cùng luồng đó theo từng bước. Ứng dụng nhận tool call, chạy code phía ứng dụng với input lấy từ tool call, rồi gửi request thứ hai kèm output. Ba nhà cung cấp lớn dùng ba API khác nhau, nhưng cùng một kiến trúc. Mô hình chỉ đóng vai người đề xuất, còn quyền thực thi thuộc về code của bạn.

Có một ngoại lệ cần biết. Với một số tool như web_search hay code_execution, Anthropic tự thực thi phía server, và bạn không bao giờ phải tạo khối tool_result cho chúng. Còn mọi tool chạm vào hệ thống của khách hàng, như database, CRM hay cổng thanh toán, đều là tool do bạn định nghĩa và do code của bạn chạy.

Mỗi lần gọi tool là một vòng khứ hồi

Bài của đội kỹ sư Anthropic gọi tool là một loại phần mềm mới: hợp đồng giữa hệ thống tất định và agent phi tất định. Vì mô hình không chạy được code của bạn, mỗi lần gọi tool là một vòng khứ hồi: mô hình hỏi, bạn thực thi, bạn báo lại, mô hình đi tiếp.

Khi gặp tool do bạn định nghĩa, API trả về khối tool_use gồm tên tool và JSON đối số, và bạn gửi tool_result trong request kế tiếp.

Trên thực tế, vòng lặp này rất ngắn: còn stop_reason == "tool_use" thì thực thi tool và tiếp tục cuộc hội thoại, gặp lý do dừng khác thì thoát. Dưới đây là ví dụ giả định cho tình huống hoàn tiền ở đầu bài, viết bằng Python với SDK của Anthropic:

TOOLS = [{
    "name": "issue_refund",
    "description": "Tạo yêu cầu hoàn tiền CHỜ DUYỆT cho đơn đã giao.",
    "input_schema": {
        "type": "object",
        "properties": {
            "order_id": {"type": "string"},
            "amount": {"type": "number"},
            "reason": {"type": "string",
                       "enum": ["damaged", "late", "wrong_item"]}
        },
        "required": ["order_id", "amount", "reason"]
    }
}]

def run_tool(name, args):
    if name != "issue_refund":
        return f"Tool '{name}' không tồn tại. Tool hợp lệ: issue_refund."
    order = db.get_order(args["order_id"])
    if order is None:
        return (f"Không có đơn {args['order_id']}. "
                "Hãy hỏi lại khách mã đơn dạng DH-xxxxxx.")
    if args["amount"] > order.total:
        return (f"Số tiền {args['amount']} vượt tổng đơn {order.total}.

"
                f"Hãy đề xuất số tiền <= {order.total}.")
    ticket = refunds.create_pending(order.id, args["amount"], args["reason"])
    return f"Đã tạo yêu cầu {ticket.id}, trạng thái: chờ nhân viên duyệt."

messages = [{"role": "user",
             "content": "Đơn DH-104233 giao sai màu, hoàn tiền giúp tôi."}]

for _ in range(8):  # giới hạn số vòng, không để agent chạy vô tận
    resp = client.messages.create(model=MODEL, max_tokens=1024,
                                  tools=TOOLS, messages=messages)
    messages.append({"role": "assistant", "content": resp.content})
    if resp.stop_reason != "tool_use":
        break
    results = [{"type": "tool_result", "tool_use_id": b.id,
                "content": run_tool(b.name, b.input)}
               for b in resp.content if b.type == "tool_use"]
    messages.append({"role": "user", "content": results})

Hãy đọc lại đoạn code bằng con mắt của vị giám đốc vận hành kia. Mô hình chỉ đưa ra ba giá trị: mã đơn, số tiền, lý do. Việc tra đơn, so số tiền với tổng đơn, và tạo một yêu cầu chờ duyệt thay vì chuyển tiền ngay đều là quyết định nằm trong run_tool, tức là do bạn viết, bạn test, bạn chịu trách nhiệm.

Ba lớp chặn, và lớp nào không thay được lớp nào

Lớp đầu tiên là schema. OpenAI khuyên dùng enum và cấu trúc object để loại bỏ trạng thái không hợp lệ ngay từ schema. Trường reason ở trên chỉ nhận ba giá trị, nên agent không thể bịa ra lý do “khách quen”.

OpenAI còn có strict mode: trong định nghĩa function của OpenAI, bật strict lên true thì lời gọi hàm bám đúng schema một cách đáng tin cậy, thay vì chỉ cố gắng hết sức.

Nếu bạn dùng API khác, hãy kiểm tra tài liệu của chính API đó xem có cơ chế tương đương hay không.

Nhưng một JSON đúng schema vẫn có thể sai về nghiệp vụ. Schema không biết đơn DH-104233 có tổng bao nhiêu tiền, cũng không biết khách này đã được hoàn tiền tuần trước. Vì thế lớp thứ hai, phần kiểm tra trong code, là thứ không thể bỏ, dù bạn đã bật strict mode.

Lớp thứ ba hay bị xem nhẹ nhất: thông báo lỗi. Đội kỹ sư Anthropic khuyên phản hồi lỗi của tool nên nói rõ cần cải thiện cụ thể điều gì, thay vì trả về mã lỗi khó hiểu hay traceback. Câu “Hãy đề xuất số tiền <= 450000” cho agent một đường để tự sửa ở vòng sau. Còn ValueError at line 42 chỉ khiến nó đoán mò.

Tự làm cho dự án của bạn

Hãy bắt đầu bằng việc liệt kê mọi hành động agent cần làm và chia chúng thành hai nhóm: chỉ đọc và có ghi. Với nhóm có ghi, hãy hỏi khách hàng ngay từ customer discovery hành động nào phải có người duyệt, rồi thiết kế tool trả về trạng thái “chờ duyệt” như ví dụ trên, thay vì thực thi thẳng.

Tiếp theo, viết schema hẹp nhất có thể. Trường nào có tập giá trị cố định thì dùng enum, và chỉ đánh dấu bắt buộc những gì thật sự cần. Sau đó viết run_tool sao cho mỗi nhánh lỗi trả về một câu agent đọc xong biết phải làm gì tiếp.

Cuối cùng là để ý kích thước kết quả. Một tool tra cứu trả về 5.000 dòng log sẽ làm đầy context rất nhanh. Anthropic đề xuất kết hợp phân trang, chọn khoảng, lọc và cắt ngắn cho những phản hồi dạng này, và khi cắt thì nên kèm một câu hướng dẫn agent cách xin trang tiếp theo.

Những lỗi khiến deployment đổ vỡ

Lỗi phổ biến nhất là tin rằng mô hình “biết” quy tắc vì bạn đã ghi trong system prompt. Prompt chỉ là lời dặn, còn code mới là luật. Mọi ràng buộc liên quan đến tiền, quyền truy cập hay dữ liệu cá nhân đều phải nằm trong run_tool.

Lỗi thứ hai là vòng lặp không có giới hạn. Nếu tool cứ trả lỗi mà agent cứ thử lại, while True sẽ đốt token mãi mãi. Một trần số vòng cộng với log từng lời gọi là chi phí rất nhỏ so với một sự cố lúc nửa đêm.

Lỗi thứ ba là ném nguyên exception vào tool_result. Lỗi kiểu này vừa vô ích với agent, vừa có thể lộ đường dẫn file hay cấu trúc database của khách hàng ra ngoài cuộc hội thoại.

Nếu bạn đang nhắm tới vai trò FDE, đây là kỹ năng nên thể hiện rõ khi ứng tuyển: gặp JD nào yêu cầu kinh nghiệm tích hợp LLM hay xây agent, hãy coi đó là chỗ để kể chi tiết về tầng tool bạn từng làm. Trong CV, đừng chỉ ghi “tích hợp LLM”.

Hãy viết cụ thể bạn đặt validation ở đâu, tool nào bắt buộc có người duyệt, bạn phân trang kết quả ra sao. Người phỏng vấn sẽ hiểu ngay bạn biết quyền thực thi nằm ở phía nào.

Lần tới có khách hàng hỏi “AI có tự làm được không?”, đừng vội trấn an. Hãy mở run_tool ra và cho họ xem từng dòng code quyết định điều gì được phép xảy ra.

4 nguồn
Đọc tiếp trên lộ trình · Chặng 3: AI ứng dụngKhoan dựng RAG: đếm token trước, đo Recall@k sauKhi khách hàng gửi một thư mục PDF và đòi một chatbot, việc đầu tiên nên làm là đếm token, chưa phải chọn vector database.