Hướng dẫn tự build AI Agent với n8n trên VPS
Xây dựng AI Agent trên n8n với node AI Agent, Claude API, HTTP Request và bộ nhớ. Hướng dẫn cấu hình trigger, thiết lập giới hạn token để kiểm soát chi phí hiệu quả.
AI Agent trong n8n là gì và sự khác biệt so với chain
AI Agent trong n8n là một node AI Agent đơn lẻ với các sub-node được gắn kèm: một chat model, một hoặc nhiều tool, và bộ nhớ tùy chọn. Bạn nêu mục tiêu bằng ngôn ngữ tự nhiên, sau đó model sẽ quyết định gọi tool nào và theo thứ tự nào cho đến khi có câu trả lời. Mọi nội dung bên dưới là cấu hình xoay quanh ý tưởng đó.
Chain hoạt động theo hướng ngược lại. Trong một Basic LLM Chain, bạn quyết định các bước và model chỉ điền văn bản. Trong một agent, model tự quyết định các bước, vì vậy cùng một câu hỏi có thể tốn một lần gọi model hôm nay nhưng lại tốn chín lần vào ngày mai. Sự khác biệt duy nhất đó quyết định mọi thiết lập trong hướng dẫn này.
Hướng dẫn này giả định n8n đang chạy sau HTTPS trên máy chủ do bạn quản lý. Nếu chưa, hãy bắt đầu với tự host n8n trên Docker với chứng chỉ thực, vì API key mà bạn sắp lưu trữ cần bản sao lưu encryption-key mà hướng dẫn đó yêu cầu. Đối với các mô hình không phải agent, như webhook summarizer và scheduled classifier, hãy xem các mẫu workflow Claude và n8n.
Hãy kiểm tra phiên bản của bạn trước khi tin tưởng bất kỳ tên trường nào ở đây, vì n8n thay đổi các AI node thường xuyên.
docker compose exec n8n n8n --versionCác tên gọi trong hướng dẫn này khớp với phiên bản n8n stable tính đến tháng 7 năm 2026. Kể từ phiên bản 1.82.0, mọi node AI Agent đều chạy dưới dạng Tools Agent, vì vậy menu thả xuống chọn loại agent cũ không còn tồn tại nữa.
Bước 1: chọn trigger
Đối với một tác nhân hội thoại, hãy thêm node Chat Trigger. Hãy để tùy chọn Make Chat Publicly Available ở trạng thái tắt trong khi bạn xây dựng, để chỉ bảng chat của trình chỉnh sửa mới có thể truy cập được. Hãy bật nó lên khi tác nhân đã hoàn tất và bạn đã quyết định xong phương thức xác thực.
Chat Trigger cung cấp cho tác nhân một trường có tên là chatInput. Tên đó rất quan trọng trong bước 3, và việc đặt sai tên là lỗi phổ biến nhất của người mới bắt đầu.
Đối với một tác nhân chạy tự động, hãy sử dụng node Schedule Trigger hoặc Webhook thay thế. Cả hai đều không tạo ra chatInput, vì vậy bạn sẽ phải tự viết prompt.
Bước 2: credential của model
Kéo một node AI Agent vào canvas. n8n sẽ hiển thị ngay một cổng kết nối Chat Model trống bên dưới nó. Hãy gắn một sub-node Anthropic Chat Model vào đó.
Tạo credential từ Anthropic Console tại platform.claude.com, trong mục Settings rồi chọn API Keys. Key này chỉ hiển thị một lần. Việc sử dụng API được tính phí theo token và tách biệt với bất kỳ gói đăng ký Claude.ai nào, vì vậy tài khoản cần được thiết lập thanh toán trước lần chạy đầu tiên.
Chọn model theo từng agent, không phải theo công ty. Một agent chỉ có một công cụ để tra cứu và báo cáo kết quả sẽ chạy tốt trên Haiku, model này tính đến tháng 7 năm 2026 có giá 1 USD cho mỗi triệu input token và 5 USD cho mỗi triệu output token. Khi agent có nhiều công cụ và cần lập kế hoạch sử dụng chúng, hãy chuyển sang Sonnet. Lỗi bạn cần tránh là sử dụng model rẻ tiền nhưng lại gọi sai công cụ bốn lần, chi phí này sẽ cao hơn so với việc dùng model đắt tiền nhưng gọi đúng công cụ chỉ một lần.
Thiết lập Maximum Number of Tokens trong các tùy chọn của sub-node. Nó giới hạn độ dài của mỗi phản hồi mà model tạo ra. Nếu để mặc định ở mức cao, một lần chạy bị lỗi có thể tạo ra câu trả lời rất dài và bạn sẽ bị tính phí cho phần đó.
Một lưu ý từ tài liệu n8n mà ai cũng dễ mắc phải: các biểu thức bên trong sub-node luôn phân giải dựa trên item đầu vào đầu tiên, không bao giờ phân giải theo từng item. Hãy đặt các biểu thức theo từng item vào các trường prompt của node gốc.
Bước 3: prompt mà agent nhận được
Mở node AI Agent. Tham số Prompt có hai thiết lập.
- Take from previous node automatically yêu cầu một trường đầu vào có tên là
chatInput. Đây là lựa chọn phù hợp khi đứng sau một Chat Trigger. - Define below hiển thị trường Prompt (User Message), nơi bạn viết văn bản tĩnh hoặc biểu thức. Đây là lựa chọn phù hợp khi đứng sau một Schedule Trigger hoặc một node Webhook.
Với một node Webhook ở phía trước, nội dung POST sẽ nằm dưới $json.body, vì vậy trường prompt sẽ trông như thế này.
Check the current status of {{ $json.body.service }} and tell me
whether it is up. If it is down, say for how long. No preamble.Bước 4: cấp cho agent một công cụ
Một node AI Agent không có node công cụ con sẽ từ chối chạy. Hãy bắt đầu với một công cụ, vì một công cụ hoạt động tốt sẽ dạy bạn nhiều hơn bốn công cụ được cấu hình dở dang.
Gắn một node HTTP Request vào cổng kết nối Tool của agent. Cấu hình nó chính xác như cách bạn làm với một node HTTP Request thông thường, sau đó hãy kiểm tra endpoint đó từ shell trước.
curl -s -H 'Accept: application/json' \
https://status.example.com/api/status/database | head -c 400Nếu lệnh curl đó trả về lỗi hoặc trang đăng nhập HTML, agent cũng sẽ thất bại, và lỗi đó sẽ hiển thị như một vấn đề của model trong khi thực tế lại là vấn đề về URL hoặc xác thực. Hãy sửa nó tại shell, không phải trong node.
Trường Description của công cụ không phải là tài liệu dành cho đồng nghiệp của bạn. Đó là thứ duy nhất model đọc khi quyết định xem công cụ này có phù hợp hay không. Hãy viết nó như một tuyên bố đơn giản về những gì được trả về: "Trả về trạng thái up hoặc down hiện tại và thời gian downtime cho một dịch vụ được giám sát, dưới dạng JSON."
Để cho phép model tự điền một phần của request, hãy sử dụng biểu thức $fromAI(). Nó chỉ hoạt động trong các công cụ được kết nối với node AI Agent, và không hoạt động trong công cụ Code.
{{ $fromAI('service', 'The name of the service to look up', 'string') }}Các tham số là key, sau đó là description, type và defaultValue tùy chọn. Key phải có độ dài từ 1 đến 64 ký tự, sử dụng chữ cái, chữ số, dấu gạch dưới và dấu gạch ngang. Kiểu dữ liệu là một trong các loại string, number, boolean hoặc json, và mặc định là string. Một lệnh gọi đầy đủ hơn trông như thế này.
{{ $fromAI('limit', 'How many records to return', 'number', 20) }}Key là một gợi ý, không phải là tham chiếu đến dữ liệu hiện có. $fromAI('service') không đọc một trường có tên service từ bất kỳ đâu. Nó ra lệnh cho model "tạo ra một giá trị và gọi nó là service", và model sẽ tìm kiếm trong cuộc hội thoại, dữ liệu đầu vào và các kết quả công cụ khác để tìm ra giá trị đó. Trong một workflow chat, nó có thể chỉ đơn giản là hỏi người dùng.
Bước 5: bộ nhớ và lý do agent bị quên
Nếu không có sub-node bộ nhớ, mỗi tin nhắn sẽ bắt đầu từ con số không. Hãy gắn một sub-node Simple Memory để lưu trữ cuộc hội thoại gần đây.
Nó có hai tham số. Session Key quyết định đây là cuộc hội thoại nào, vì vậy hai người dùng với các key khác nhau sẽ có lịch sử riêng biệt. Context Window Length là số lượng tương tác trước đó được phát lại vào trong prompt.
Context Window Length vừa là nút điều chỉnh chi phí, vừa là nút điều chỉnh chất lượng, vì mỗi lượt được ghi nhớ sẽ được gửi lại dưới dạng input token trong mỗi lần gọi sau đó. Một cửa sổ 20 trên một agent hay trò chuyện nghĩa là bạn phải trả phí cho cùng những tin nhắn đầu tiên đó hai mươi lần.
Simple Memory không hoạt động trong quy trình production đang chạy khi n8n ở chế độ queue mode, vì lịch sử nằm trong dữ liệu của chính workflow đó thay vì nằm trong một kho lưu trữ dùng chung. Trên một instance chạy queue mode, hãy sử dụng sub-node Postgres Chat Memory thay thế và trỏ nó vào một cơ sở dữ liệu mà cả tiến trình chính và các worker đều có thể truy cập được.
Bước 6: System Message
Mở phần Options của agent và thêm một System Message. Đây là nơi đặt mô tả công việc, và đây là đoạn văn bản có sức ảnh hưởng lớn nhất trong quy trình làm việc.
You are an infrastructure status assistant. Always call the status
tool before answering a question about whether something is running.
Never guess. If the tool returns an error, say so and stop.Câu lệnh "Luôn gọi công cụ status trước khi trả lời" thực sự phát huy tác dụng ở đây. Nếu thiếu nó, model sẽ tự cho rằng nó đã biết câu trả lời, bỏ qua công cụ và phản hồi dựa trên bộ nhớ. Điều này dẫn đến các câu trả lời sai lệch ngay khi hạ tầng của bạn có thay đổi.
Tại sao agent bị lặp và cơ chế dừng nó
Trong phần Options còn có mục Max Iterations, giá trị mặc định là 10. Một iteration là một lần gọi model cộng với kết quả từ tool được đưa ngược lại vào context. Do đó, một lần chạy agent không chỉ là một lần gọi API, mà có thể lên tới mười lần, và mỗi lần đều mang theo toàn bộ đoạn hội thoại đang dài dần làm input.
Hãy giảm giá trị này xuống. Hầu hết các agent dùng một tool duy nhất sẽ hoàn thành trong hai iteration, và giới hạn 3 hoặc 4 sẽ biến một vòng lặp vô tận thành một lỗi dừng rõ ràng mà bạn có thể thấy trong danh sách thực thi.
Trong khi debug, hãy bật Return Intermediate Steps. Output cuối cùng khi đó sẽ bao gồm các lần gọi tool mà agent đã thực hiện, đây là cách để bạn phân biệt giữa "model không bao giờ gọi tool" và "tool không trả về kết quả hữu ích". Hãy tắt nó đi trước khi đưa vào môi trường production, vì những bước đó là nhiễu đối với người dùng cuối.
Hãy theo dõi quá trình chạy từ shell.
docker compose logs -f n8nNgăn chặn agent tự động tiêu tốn tài nguyên âm thầm
Một agent nằm sau Chat Trigger có con người giám sát, và người đó sẽ dừng nó lại khi câu trả lời có vẻ sai. Một agent nằm sau Schedule Trigger thì không có ai theo dõi. Giải pháp đầy đủ nằm trong kiểm soát chi phí AI agent trên VPS chạy liên tục. Bốn thiết lập sau đây sẽ thực hiện phần lớn công việc này.
- Giới hạn Maximum Number of Tokens trên sub-node của model, để không một phản hồi đơn lẻ nào có thể chạy quá dài.
- Đặt Max Iterations ở con số nhỏ nhất mà vẫn hoàn thành được tác vụ.
- Giữ cho các phản hồi từ tool ở mức nhỏ gọn. Một tool trả về một blob JSON dài 4.000 dòng sẽ đưa toàn bộ nội dung đó vào lần gọi model tiếp theo, và sau đó vào mọi lần gọi kế tiếp trong cùng một phiên chạy.
- Tự hỏi liệu agent có thực sự cần lịch trình (schedule) hay không. Một job chạy mỗi năm phút sẽ kích hoạt 288 lần một ngày. Chi phí của một lần chạy là bao nhiêu, thì đó chính là con số bạn cần nhân lên.
Hãy vô hiệu hóa workflow trong khi bạn đang chỉnh sửa. Một workflow đang hoạt động với Schedule Trigger sẽ tiếp tục chạy dựa trên phiên bản mà n8n đã lưu, vốn không phải lúc nào cũng là phiên bản đang hiển thị trên màn hình của bạn.
FAQ
Tại sao node AI Agent của tôi từ chối thực thi?
Node AI Agent yêu cầu một sub-node mô hình chat và ít nhất một sub-node công cụ. Một node có mô hình nhưng không có công cụ sẽ thất bại trước khi thực hiện bất kỳ lệnh gọi API nào. Hãy đính kèm một công cụ, dù là công cụ đơn giản nhất, và chạy lại.
Agent trả lời, nhưng không bao giờ gọi công cụ của tôi. Có vấn đề gì?
Gần như luôn luôn là do trường Description của công cụ. Mô hình chọn công cụ bằng cách đọc các mô tả đó, vì vậy một mô tả như "HTTP Request" không cho nó biết gì về thời điểm áp dụng công cụ. Hãy viết lại để nêu rõ dữ liệu nào sẽ trả về và trong tình huống nào thì nó hữu ích, sau đó thêm một dòng vào System Message để hướng dẫn agent gọi công cụ đó trước khi trả lời.
Tại sao cùng một câu hỏi lại có chi phí khác nhau mỗi lần chạy?
Vì mô hình tự chọn số lượng bước thực hiện. Mỗi lần lặp sẽ gửi lại toàn bộ nội dung hội thoại cho đến thời điểm đó, bao gồm cả kết quả đầu ra của công cụ trước đó, vì vậy một lần chạy mất bốn lần lặp sẽ tốn kém hơn nhiều so với bốn lần gọi đơn lẻ. Max Iterations là giới hạn tối đa cho việc đó, và Return Intermediate Steps sẽ cho bạn biết một lần chạy cụ thể đã sử dụng bao nhiêu bước.
Bộ nhớ của tôi hoạt động trong trình chỉnh sửa nhưng không hoạt động trong môi trường production. Điều gì đã thay đổi?
Hãy kiểm tra xem instance có đang chạy ở chế độ queue hay không. Simple Memory lưu trữ lịch sử trong dữ liệu thực thi của chính workflow, dữ liệu này sẽ không tồn tại khi được chuyển sang một worker process riêng biệt, vì vậy một workflow đang chạy ở môi trường production sẽ làm mất nó. Hãy thay thế bằng sub-node Postgres Chat Memory, sub-node này lưu trữ lịch sử trong cơ sở dữ liệu mà mọi worker đều chia sẻ.