Hướng dẫn AgentFlow

Mã lệnh (Code)

Chạy một đoạn mã Python hoặc JavaScript ngắn trên các giá trị bạn gán, rồi dùng kết quả trả về ở các bước sau.

Mục đích

Bước Mã lệnh (Code) chạy một hàm ngắn do bạn viết — bằng Python hoặc JavaScript — trên các giá trị bạn gán vào, và trả về một đối tượng mà các bước sau có thể đọc theo tên trường.

Dùng bước này khi việc cần làm là tính toán, chứ không phải gọi ra bên ngoài: định dạng lại một mảng JSON, tính một khoản tiền, tách một chuỗi, tổng hợp kết quả của một vòng lặp, hoặc dựng sẵn một payload trước khi gửi đi. Trước khi có bước này, khả năng tính toán duy nhất là Đặt biến (Set variable) với biểu thức {{ }}, vốn không diễn đạt được vòng lặp hay điều kiện nhiều nhánh.

Bước này chỉ khả dụng khi quản trị viên đã bật một môi trường chạy mã cho hệ thống (biến CODE_RUNNER). Nếu chưa bật, quy trình chứa bước Mã lệnh sẽ bị từ chối khi xuất bản, kèm thông báo nêu đúng tên biến cần thiết lập.

Khi nào dùng

  • Biến đổi dữ liệu mà biểu thức {{ }} không diễn đạt nổi: lọc, gộp, sắp xếp, đếm.
  • Tổng hợp kết quả của một bước Lặp theo phần tử (For each) thành một con số hoặc một bảng.
  • Dựng một payload có cấu trúc trước khi đưa sang bước Gọi webhook hoặc Tích hợp.
  • Kiểm tra một điều kiện phức tạp rồi trả về một cờ đơn giản cho bước Quyết định (Decision).

Cài đặt chính

Cài đặtBắt buộcMô tả
Language (Ngôn ngữ)CóPython hoặc JavaScript.
Code (Mã lệnh)CóĐịnh nghĩa một hàm tên main nhận một tham số và trả về một đối tượng.
Inputs (Dữ liệu đầu vào)KhôngDanh sách tên và giá trị được gán. Mỗi tên là một khóa trong inputs; giá trị lấy từ biến quy trình, biểu thức {{ }} hoặc giá trị cố định.
Output shape (Hình dạng kết quả)KhôngMô tả các trường mà main trả về. Giá trị trả về được kiểm tra theo mô tả này, và đây cũng là danh sách trường các bước sau chọn được theo tên.

Năm điều cần biết trước khi viết

Đây là năm điều mà nhìn vào Trình thiết kế sẽ không đoán ra được.

1. Một bước có thể chạy nhiều hơn một lần

Khi một lần chạy gặp lỗi, hệ thống thử lại, và mã lệnh của bạn sẽ chạy lại từ đầu. Đây là cách toàn bộ nền tảng hoạt động — bước Truy vấn SQL ở chế độ ghi và bước Gọi webhook cũng vậy — nhưng Mã lệnh là bước đầu tiên mà chính bạn viết phần có thể không an toàn khi lặp lại.

Cho nên: mã lệnh thay đổi bất cứ thứ gì bên ngoài quy trình này phải an toàn khi chạy lại. Tính toán thuần túy thì không có vấn đề gì.

Không có tùy chọn "chạy đúng một lần". Đặt bước sang bỏ qua lỗi (Continue) chỉ làm cho một lần chạy lỗi không dừng cả quy trình — nó không đảm bảo mã lệnh chỉ chạy một lần, vì một sự cố xảy ra sau khi mã đã chạy vẫn dẫn đến một lần chạy lại.

2. inputs chỉ chứa đúng những tên bạn khai báo

Đọc một tên không có trong danh sách sẽ báo lỗi, chứ không trả về giá trị rỗng:

CodeInputError: no input named 'tong_tien'. Declared inputs on this step: amount, currency

Điều này là cố ý. Nếu đọc một tên sai mà nhận về None / undefined, thì khi bạn đổi tên một đầu vào, bước vẫn chạy "thành công" với dữ liệu trống và lỗi chỉ lộ ra ở đâu đó rất xa. Ở đây nó hỏng ngay, và nói rõ tên nào có.

Cả inputs["x"], inputs.x và inputs.get("x") (Python) đều theo quy tắc này.

Khi bạn gõ inputs. hoặc inputs[", trình soạn thảo gợi ý các tên đã khai báo; khi gõ context., nó gợi ý các trường của context. Gợi ý đi theo tên bạn đặt cho tham số: với def main(data, ctx): thì chính data. mới gợi ý các tên.

3. Không có mạng và không đọc được nội dung tệp

Mã lệnh chạy trong một môi trường không có kết nối mạng. Không gọi được API, không tải được thư viện lúc chạy, không đọc được cơ sở dữ liệu.

Nó cũng không đọc được nội dung tệp: một đầu vào gán từ trường tệp sẽ đến dưới dạng chuỗi mã định danh, không phải dữ liệu tệp.

Khi cần những việc đó, hãy dùng đúng bước dành cho chúng:

Việc cần làmBước nên dùng
Gọi một API bên ngoàiGọi webhook hoặc Tích hợp
Đọc nội dung một tệpTrích xuất văn bản (Doc Extractor)
Đọc dữ liệu từ cơ sở dữ liệuTruy vấn SQL

4. main phải trả về một đối tượng

Các bước sau đọc kết quả theo đường dẫn nodes.{mã bước}.output.{tên trường}, nên một số hay một chuỗi thì không có trường nào để đọc. Trả về giá trị không phải đối tượng sẽ làm bước lỗi.

Nếu bạn khai báo Output shape, đối tượng trả về còn được kiểm tra theo mô tả đó — và đó cũng chính là danh sách trường mà bộ chọn biến của các bước sau sẽ gợi ý.

5. context — thông tin về lần chạy

Ngoài inputs, hàm main nhận tham số thứ hai là context, chứa bốn giá trị mà bạn không cần gán:

TrườngÝ nghĩa
context.run_idMã của lần chạy quy trình. Không đổi khi bước được chạy lại.
context.node_idMã của chính bước này trong sơ đồ. Không bao giờ đổi.
context.node_run_idMã của lần thử này. Mỗi lần chạy lại sẽ có mã khác.
context.org_idMã tổ chức.

Nếu bạn cần một khóa chống trùng (idempotency key) — vì bước có thể chạy nhiều hơn một lần, xem mục 1 — hãy dựng từ context.run_id (kèm context.node_id), đừng dùng context.node_run_id: nó đổi ở đúng lần chạy lại mà khóa đó sinh ra để xử lý.

context cũng nghiêm ngặt như inputs: đọc một tên không có sẽ báo lỗi, kèm danh sách các tên hợp lệ.

Nếu không cần, bạn có thể bỏ tham số này và viết def main(inputs): như bình thường.

Ví dụ

Python

def main(inputs, context):
    lines = inputs["lines"]
    total = sum(line["quantity"] * line["unit_price"] for line in lines)
    return {
        "total": total,
        "line_count": len(lines),
        "over_limit": total > inputs["limit"],
    }

JavaScript

function main(inputs, context) {
  const lines = inputs["lines"];
  const total = lines.reduce((sum, l) => sum + l.quantity * l.unitPrice, 0);
  return {
    total,
    lineCount: lines.length,
    overLimit: total > inputs["limit"],
  };
}

Với ví dụ trên, bước sau có thể đọc nodes.tinh_tong.output.total hoặc dùng over_limit làm điều kiện cho một bước Quyết định.

Giới hạn

Giới hạnGiá trị
Thời gian chạyTối đa 20 giây cho mỗi lần chạy. Có thể đặt ngắn hơn, không đặt dài hơn được.
Kích thước kết quả1 MB sau khi chuyển thành JSON. Vượt quá thì bước lỗi, chứ không cắt bớt — một kết quả bị cắt trông không khác gì một kết quả đầy đủ.
Thư việnChỉ những gì có sẵn trong môi trường chạy. Không cài thêm gói lúc chạy.

Nếu bước cần nhiều hơn 20 giây, hãy tách công việc: dùng Lặp theo phần tử để chia nhỏ, hoặc đẩy phần nặng sang một dịch vụ bên ngoài và gọi bằng Gọi webhook.

Khi có lỗi

  • Lỗi cú pháp, thiếu main, hoặc main khai báo quá nhiều tham số — trình soạn thảo đánh dấu cả ba ngay khi bạn gõ, dựa trên chính kết quả phân tích dùng để tô màu mã. Việc xuất bản không bị chặn vì các lỗi này: nơi quyết định cuối cùng là trình thông dịch chạy mã của bạn. Một main được tạo theo cách trình soạn thảo không đọc được — gán từ biến, sinh ra bởi decorator — sẽ được bỏ qua thay vì báo nhầm.
  • Mã lệnh báo lỗi — thông báo và vết gọi (traceback) của chính bạn hiện trên bước bị lỗi, kèm số dòng đúng theo mã bạn viết.
  • Chạy quá giờ — bước lỗi với thông báo nêu rõ giới hạn thời gian.
  • Chưa bật môi trường chạy — quy trình bị từ chối ngay khi xuất bản, không phải đợi đến lúc chạy.

Trên trang lần chạy, nút Thử lại (Retry) chạy lại bước — hãy nhớ điều 1 ở trên trước khi bấm.

Chạy thử (Simulation)

Trong một lần chạy thử, mã lệnh được thực thi, trong cùng sandbox như khi chạy thật. Sandbox không có mạng và bị xóa sau mỗi lần chạy, nên không có gì bên ngoài lần chạy thử bị ảnh hưởng.

Chọn bước trong bảng chạy thử để xem kết quả. Thẻ Đầu vào bắt đầu bằng mục Giá trị truyền vào bước: từng đầu vào bạn đã khai báo, kèm giá trị nó nhận được. Các biến của quy trình được liệt kê bên dưới. Thẻ Đầu ra là giá trị main trả về. Bước bị lỗi vẫn hiển thị đầu vào của nó.

Nếu hệ thống chưa cấu hình trình chạy mã, mã lệnh không thể chạy. Khi đó bước trả về một đối tượng có đúng hình dạng bạn khai báo ở Output shape, với giá trị rỗng cho từng trường (0, "", false, [], {}), để các bước phía sau vẫn có dữ liệu đúng kiểu mà chạy tiếp. Thẻ Tác động của bước cho biết mã lệnh không được chạy và lý do. Nếu bạn không khai báo Output shape thì bước trả về một đối tượng rỗng.

On this page