Bài học từ việc xây dựng Claude Code: nhìn thế giới như một agent

Nghe bài viết:

cc-260315001117

Thiết kế không gian hành động cho agent

Một trong những phần khó nhất khi xây dựng agent harness là thiết kế không gian hành động (action space) của nó.

Claude hoạt động thông qua Tool Calling, nhưng có nhiều cách để xây dựng tool trong Claude API với các primitive như bash, skills và gần đây là code execution (bạn có thể đọc thêm về programmatic tool calling trong bài viết mới của @RLanceMartin).

Với tất cả các lựa chọn này, câu hỏi đặt ra là: làm thế nào để thiết kế tool cho agent của bạn?

Bạn có cần chỉ một tool như code execution hoặc bash không?
Hay bạn nên có 50 tool, mỗi tool phục vụ một use case mà agent có thể gặp?

Để đặt mình vào góc nhìn của mô hình, tôi thường tưởng tượng rằng mình được giao một bài toán toán học khó. Bạn sẽ muốn có những công cụ gì để giải nó?

Điều đó phụ thuộc vào kỹ năng của chính bạn.

Giấy bút là mức tối thiểu, nhưng bạn sẽ bị giới hạn bởi việc tính toán thủ công.
Máy tính cầm tay sẽ tốt hơn, nhưng bạn cần biết cách dùng các chức năng nâng cao.
Lựa chọn nhanh và mạnh nhất là máy tính, nhưng bạn phải biết viết và chạy code.

Đây là một framework hữu ích khi thiết kế agent.

Bạn nên cung cấp cho agent những công cụ phù hợp với khả năng của nó.

Nhưng làm sao bạn biết khả năng của nó là gì?

Bạn phải quan sát, đọc output của nó, thử nghiệm nhiều lần.

Bạn học cách nhìn thế giới như một agent.

Dưới đây là một số bài học chúng tôi rút ra khi quan sát Claude trong quá trình xây dựng Claude Code.


Cải thiện khả năng hỏi thông tin và tool AskUserQuestion

hclxer3acaaf2r9-260314235949

Khi xây dựng AskUserQuestion, mục tiêu của chúng tôi là cải thiện khả năng đặt câu hỏi của Claude (thường được gọi là elicitation).

Claude có thể hỏi câu hỏi bằng text bình thường, nhưng chúng tôi nhận thấy việc trả lời những câu hỏi đó mất thời gian không cần thiết.

Làm sao để giảm ma sáttăng băng thông giao tiếp giữa người dùng và Claude?


Thử nghiệm #1 — chỉnh sửa ExitPlanTool

Điều đầu tiên chúng tôi thử là thêm một parameter vào ExitPlanTool, cho phép chứa một mảng câu hỏi cùng với kế hoạch.

Đây là cách dễ nhất để triển khai, nhưng nó khiến Claude bối rối.

Chúng tôi đang yêu cầu Claude đưa ra kế hoạchđặt câu hỏi về kế hoạch đó cùng lúc.

Nhưng nếu câu trả lời của người dùng mâu thuẫn với kế hoạch thì sao?

Claude có cần gọi ExitPlanTool hai lần không?

Chúng tôi nhận ra cần một cách tiếp cận khác.

(Bạn có thể đọc thêm về lý do chúng tôi tạo ExitPlanTool trong bài viết về prompt caching.)


Thử nghiệm #2 — thay đổi định dạng output

Sau đó chúng tôi thử sửa instruction output của Claude để nó sử dụng một định dạng markdown tùy chỉnh để đặt câu hỏi.

Ví dụ:

Claude có thể output một danh sách bullet point câu hỏi với các lựa chọn trong ngoặc.

Sau đó chúng tôi có thể parse danh sách này và hiển thị UI cho người dùng.

Đây là thay đổi tổng quát nhất mà chúng tôi có thể làm.

Claude thậm chí có vẻ khá tốt trong việc tạo format này.

Nhưng nó không được đảm bảo.

Claude đôi khi:

  • thêm câu không cần thiết

  • bỏ sót lựa chọn

  • hoặc dùng format khác


Thử nghiệm #3 — AskUserQuestion Tool

hcl0gcobkaa4tkt-260315000134

Cuối cùng chúng tôi tạo AskUserQuestion Tool.

Claude có thể gọi tool này bất cứ lúc nào, nhưng nó đặc biệt được khuyến khích gọi trong plan mode.

Khi tool được kích hoạt:

  • một modal UI hiển thị câu hỏi

  • vòng lặp agent tạm dừng cho đến khi người dùng trả lời

Tool này cho phép chúng tôi:

  • yêu cầu Claude tạo output có cấu trúc

  • đảm bảo Claude đưa ra nhiều lựa chọn

Người dùng cũng có thể kết hợp chức năng này trong Agent SDK hoặc skills.

Quan trọng nhất:

Claude dường như thích gọi tool này, và output của nó hoạt động rất tốt.

Ngay cả tool được thiết kế tốt nhất cũng vô dụng nếu Claude không hiểu cách gọi nó.

Đây có phải là phiên bản cuối cùng của elicitation trong Claude Code không?

Chúng tôi chưa chắc.

Như ví dụ tiếp theo cho thấy: cái hoạt động tốt với model này có thể không phải tốt nhất với model khác.


Cập nhật theo khả năng model: Tasks và Todos

hclxrfxbeauxwrv-260315000201

Khi Claude Code lần đầu ra mắt, chúng tôi nhận ra model cần Todo list để giữ nó đi đúng hướng.

Todo được viết ở đầu và đánh dấu hoàn thành khi model làm xong việc.

Để làm điều này, chúng tôi tạo TodoWrite Tool.

Tool này:

  • tạo hoặc cập nhật Todo

  • hiển thị Todo cho người dùng

Nhưng chúng tôi vẫn thấy Claude quên việc cần làm.

Để thích nghi, chúng tôi thêm system reminder mỗi 5 lượt hội thoại để nhắc Claude mục tiêu của nó.

Nhưng khi model trở nên mạnh hơn, chúng không cần reminder nữa.

Thậm chí Todo list còn trở thành hạn chế.

Reminder khiến Claude nghĩ rằng nó phải tuân thủ Todo list, thay vì cập nhật nó.

Chúng tôi cũng thấy Opus 4.5 tốt hơn nhiều trong việc sử dụng subagent.

Nhưng làm sao nhiều subagent phối hợp với một Todo list chung?

Vì vậy chúng tôi thay TodoWrite bằng Task Tool.

Nếu Todo nhằm giữ model đúng hướng, thì Task nhằm giúp agent giao tiếp với nhau.

Task có thể:

  • có dependency

  • chia sẻ update giữa subagent

  • được model chỉnh sửa hoặc xóa

Khi khả năng model tăng lên, những tool từng cần thiết có thể trở thành rào cản.

Vì vậy bạn cần liên tục xem lại giả định ban đầu về tool.

Đây cũng là lý do nên giữ số lượng model hỗ trợ nhỏ, với khả năng tương đối giống nhau.


Thiết kế giao diện tìm kiếm

Một nhóm tool đặc biệt quan trọng đối với Claude là search tools giúp nó xây dựng context của chính mình.

Khi Claude Code mới ra mắt, chúng tôi dùng RAG vector database để tìm context.

RAG rất mạnh và nhanh, nhưng nó cần:

  • indexing

  • setup

  • dễ bị lỗi trong nhiều môi trường khác nhau

Quan trọng hơn:

Claude được cung cấp context, thay vì tự tìm context.

Nhưng nếu Claude có thể search web, tại sao không search codebase?

Chúng tôi cung cấp cho Claude Grep tool, cho phép nó tìm file và tự xây context.

Đây là pattern chúng tôi thấy rõ:

Khi Claude thông minh hơn, nó ngày càng giỏi xây dựng context nếu có tool phù hợp.


Agent Skills và progressive disclosure

Khi chúng tôi giới thiệu Agent Skills, chúng tôi chính thức hóa khái niệm progressive disclosure.

Điều này cho phép agent khám phá context theo từng bước thông qua quá trình khám phá.

Claude có thể đọc skill file, và file đó có thể tham chiếu đến file khác.

Model có thể đọc đệ quy các file này.

Một use case phổ biến của skills là:

  • thêm khả năng search

  • hướng dẫn Claude dùng API

  • query database

Trong vòng một năm, Claude đã tiến từ:

  • gần như không thể tự xây context

đến

  • có thể thực hiện nested search qua nhiều lớp file để tìm context chính xác.

Ngày nay progressive disclosure là kỹ thuật phổ biến để thêm chức năng mà không cần thêm tool.


Progressive disclosure và Claude Code Guide Agent

Claude Code hiện có khoảng 20 tool.

Chúng tôi luôn tự hỏi có thực sự cần tất cả không.

Thêm một tool nghĩa là model có thêm một lựa chọn cần suy nghĩ.

Ví dụ:

Chúng tôi nhận thấy Claude không biết đủ về chính Claude Code.

Nếu bạn hỏi:

  • làm sao thêm MCP

  • slash command là gì

Claude không trả lời được.

Chúng tôi có thể đưa toàn bộ thông tin vào system prompt, nhưng vì người dùng hiếm khi hỏi, điều đó sẽ gây context rot và ảnh hưởng nhiệm vụ chính của Claude Code: viết code.

Thay vào đó chúng tôi thử progressive disclosure.

Chúng tôi cung cấp link tài liệu để Claude tự load khi cần.

Cách này hoạt động, nhưng Claude thường load quá nhiều nội dung.

Trong khi thực tế chỉ cần câu trả lời.

Vì vậy chúng tôi xây Claude Code Guide subagent.

Claude được prompt gọi subagent này khi người dùng hỏi về Claude Code.

Subagent có:

  • instruction chi tiết

  • cách search docs hiệu quả

  • logic chọn câu trả lời cần trả về

Giải pháp này chưa hoàn hảo.

Claude vẫn có thể nhầm lẫn khi hỏi về setup.

Nhưng tốt hơn trước rất nhiều.

Quan trọng nhất:

Chúng tôi đã mở rộng action space mà không cần thêm tool mới.


Một nghệ thuật, không phải khoa học

Nếu bạn hy vọng có một bộ quy tắc cứng nhắc để thiết kế tool, thì tiếc là bài viết này không phải vậy.

Thiết kế tool cho agent vừa là nghệ thuật vừa là khoa học.

Nó phụ thuộc vào:

  • model bạn dùng

  • mục tiêu agent

  • môi trường agent hoạt động

Hãy:

  • thử nghiệm thường xuyên

  • đọc output

  • thử ý tưởng mới

Và quan trọng nhất:

hãy học cách nhìn thế giới như một agent.