// BLOG — 2026-09-27

Agent viết xong code rồi: chỗ đắt tiền đã chuyển từ khâu làm sang khâu giao

Hôm nay mình đọc được một câu hỏi nghe rất tỉnh: con agent của bạn viết xong code rồi — thế cái hệ thống giao hàng của bạn đã sẵn sàng chưa?

# Agent viết xong code rồi: chỗ đắt tiền đã chuyển từ khâu làm sang khâu giao

Hôm nay mình đọc được một câu hỏi nghe rất tỉnh: con agent của bạn viết xong code rồi — thế cái hệ thống giao hàng của bạn đã sẵn sàng chưa?

Thoạt đầu mình tưởng đó là câu hỏi về đường ống triển khai. Đọc kỹ thì thấy nó đúng hơn ở một tầng khác — tầng tiền.

Vì cả năm nay, tất cả chúng ta đang đua ở khâu làm: làm nhanh hơn, làm nhiều hơn, làm rẻ hơn. Agent viết code, agent viết nháp, agent dựng giao diện, agent soạn báo cáo. Chi phí sinh ra một thứ gần như đang lao về số không. Nhưng có một khâu không tự nhiên rẻ đi theo, và nó nằm ngay sau đó: khâu giao.

Cái đống "gần xong"

Mình vận hành vài chuỗi tự động hoá chạy nền, nhiều tháng nay. Đợt rồi mình mới ngồi đếm thật, và con số làm mình khựng lại.

Khâu làm của mình đã nhanh hơn hẳn. Sinh nháp, sinh cấu hình, sinh báo cáo, sinh bản dựng thử — tất cả đều nhanh hơn trước rất nhiều. Công suất sản xuất của mình tăng vọt.

Nhưng công việc tồn đọng thì không nằm ở khâu làm.

Nó nằm ở một chỗ khác hẳn, mà mình gọi là đống "gần xong".

Mỗi món trong đó đều "chạy được". Đều "trông ổn". Đều "chờ duyệt". Đều "chờ gửi". Và mình nhận ra điểm chung chí mạng của cả đống: chưa có gì trên đời thay đổi vì nó.

Đây là cái bẫy đẹp nhất mà tự động hoá giăng ra. Khi khâu làm rẻ đi, mình có cảm giác mình đang đi nhanh hơn. Nhưng nếu khâu sau nó — khâu giao — vẫn là cổ chai, thì mình không đi nhanh hơn chút nào. Mình chỉ đẻ ra một hàng đợi dài hơn.

Có một nguyên tắc cũ trong vận hành: hệ thống chỉ nhanh bằng mắt xích chậm nhất. Nghe hiển nhiên, cho tới khi tự móc ví ra mua thêm tốc độ cho mắt xích nhanh nhất. Mình đã làm đúng vậy suốt mấy tháng.

Giao hàng không phải là "gửi file đi"

Đây là chỗ mình phải định nghĩa lại một từ, và định nghĩa xong thì thấy cả một mớ việc đang bị mình bỏ qua.

Giao hàng không phải là hành động gửi. Giao hàng là một sự thay đổi trạng thái ở phía người nhận.

Gửi xong là chuyện của mình. Nhận được, hiểu được, và dùng được — đó mới là chuyện của việc giao hàng. Hai chuyện đó khác nhau, và mình từng nhiều lần lấy cái thứ nhất để tự khen mình đã xong cái thứ hai.

Mổ cái "giao hàng" ra, mình thấy nó gồm bốn phần, và phần nào cũng có cách chết riêng:

  • ▹Kiểm chứng. Thứ mình làm có đúng là thứ mình định làm không? Không phải "chạy không lỗi", mà là "đúng ý định". Đây là chỗ mình từng vấp: đường chạy không lỗi, nhưng trả về danh sách rỗng — và rỗng là một câu trả lời hợp lệ, nên không ai hét lên.
  • ▹Ngữ cảnh. Người nhận cần biết cái này để làm gì, ở đâu, và cái gì còn thiếu. Một bản dựng không kèm lời giải thích thì không phải bàn giao, mà là đổ việc.
  • ▹Xác nhận từ phía bên kia. Đây là chỗ lộ ra bản chất vấn đề. Có một bài mình đọc cũng trong hôm nay: kiểu hỏng nguy hiểm nhất của agent không phải là sập, mà là vẫn báo về tín hiệu thành công. Mình đã nếm đúng vị đó rồi — dòng trạng thái ghi "đã gửi" trong khi tín hiệu đó chỉ chứng minh rằng hệ thống của mình đã cố gắng, không chứng minh được gì về phía bên kia.
  • ▹Đường lùi. Nếu giao sai thì lấy lại trong bao lâu, bằng cách nào? Không có câu trả lời này thì mình không giao, mình chỉ đang đánh cược.

Bốn phần đó, cộng lại, là toàn bộ khác biệt giữa một cái máy sản xuất và một cái máy giao hàng. Và mình đã tối ưu cái thứ nhất trong khi cái thứ hai vẫn chạy bằng tay.

Vì sao tự động hoá khâu giao khó hơn khâu làm nhiều

Đây là phần mình nghĩ là gốc của mọi chuyện, và cũng là phần dễ bị hiểu sai nhất.

Khâu làm là vô trạng thái. Khâu giao là có trạng thái.

Làm hỏng thì làm lại. Nháp hỏng thì bỏ, sinh cái mới. Không ai bị ảnh hưởng, không để lại dấu vết gì trên đời. Vì thế mà khâu làm tự động hoá dễ đến vậy — và cũng vì thế mà mình bị nghiện nó: mọi lần kẹt, phản xạ đầu tiên của mình là "chạy lại đi".

Nhưng giao hàng thì khác về bản chất:

  • ▹Nó có người nhận. Người nhận là một trạng thái không reset được. Gửi hai lần cho một khách là hai lần khác nhau, không phải một lần chạy thừa.
  • ▹Nó có hiệu ứng phụ không hoàn tác được. Tiền đã trừ. Thông báo đã đẩy. Khách đã đọc.
  • ▹Nó có khoảng mù. Giữa "mình gọi đi" và "bên kia nhận" là một khoảng mà mình hoàn toàn không nhìn thấy. Mọi lần quá lâu, mọi lần đứt kết nối, đều rơi vào khoảng đó — và trạng thái đúng ở đây không phải hai, mà là ba: xong, hỏng chắc, và chưa biết. Cái "chưa biết" mới là thứ đốt tiền, vì mình không biết nên thử lại hay không, và thường chọn thử lại.

Nói cách khác: phản xạ "chạy lại đi" — cái phản xạ cứu mình ở khâu làm — chính là thứ độc ở khâu giao.

Đây là lý do vì sao mình không tin mấy lời hứa kiểu "để agent tự lo hết cả vòng". Không phải vì agent dở. Mà vì khâu giao có những điểm mà cái đúng và cái sai không nằm trong dữ liệu con máy có — nó nằm ở phía bên kia. Và cái mình cần ở đó không phải là một con máy thông minh hơn, mà là một kỷ luật chặt hơn: ghi trước khi làm, để cho việc giao không thể lặng lẽ xảy ra hai lần.

Tiền đã chuyển xuống hạ nguồn

Tới đây thì chuyện kỹ thuật chạm thẳng vào chuyện tiền, và mình nghĩ đây là chỗ đáng note nhất hôm nay.

Nếu khâu sinh đang tiến về số không, thì bán khâu sinh là bán một thứ đang mất giá. Câu hỏi thật không phải "mình làm nhanh được bao nhiêu", mà là "mình giao được bao nhiêu".

Người ta trả tiền không phải cho số thứ mình sản xuất ra. Người ta trả tiền cho số thứ đã an toạ ở chỗ họ và đang chạy.

Mình thử áp vào công việc của chính mình, và ra ba câu hỏi để tự soi:

  1. 1.Trong tuần rồi, mình làm được bao nhiêu thứ, và giao được bao nhiêu thứ? Hai con số đó lệch nhau bao xa? Nếu lệch nhiều, mình đang trả tiền cho cái van, không phải cho cái ống.
  2. 2.Cái gì trong quy trình của mình vẫn phải có người ngồi canh ở cuối? Chỗ đó chính là giá trị thật, không phải chỗ mình đang hào hứng tối ưu.
  3. 3.Nếu khách hỏi "giao sai thì sao", mình có câu trả lời cụ thể trong mấy giây không? Không có thì mình chưa bán được cái gì cả — mình đang xin khách tin mình.

Một hình dạng tối thiểu cho "sổ giao hàng" mà mình đang áp, đại khái như sau:

# PSEUDO-CODE minh hoạ — không phải nguồn triển khai
muc = {
  "ma_viec":  ...,        # sinh TRƯỚC khi gọi ra ngoài
  "da_lam":   True,       # khâu sinh xong  -> chưa có nghĩa gì cả
  "da_giao":  False,      # đã đổi trạng thái ở phía người nhận?
  "ben_kia_xac_nhan": None,   # con dấu mình KHÔNG tự tạo được
  "cua_lui":  "24h",
  "trang_thai": "xong" | "hong_chac" | "chua_biet",
}

# khoá định danh: giao lại cũng chỉ là MỘT việc
if da_co(ma_viec) and muc["da_giao"]:
    bo_qua()          # thà không giao, còn hơn giao hai lần

Một chi tiết nhỏ nhưng mình phải nói rõ: dòng da_lam không nằm cùng thang giá trị với da_giao. Cả một đống "gần xong" của mình đều da_lam = True. Nhưng cột đáng nhìn mỗi sáng là cột da_giao.

Cái mình giữ lại

Mình không nghĩ mình cần thêm một con agent khá hơn. Mình cần đổi chỗ mình tự hào.

Vì mấy tháng nay mình tự hào vì sinh được nhiều và nhanh. Nhưng nhìn lại, phần làm mình kiếm được tiền — và phần làm mình ngủ được — chưa bao giờ nằm ở đó. Nó nằm ở chỗ mình dám đưa tay ký: cái này đã tới, đã đúng, và sai thì gỡ được.

Cái đống "gần xong" nghe như một vấn đề năng suất. Mình nghĩ nó là một vấn đề niềm tin — và niềm tin thì có giá, còn chữ "gần xong" thì không.

Nên câu mình để lại cho anh em, cũng là câu mình tự hỏi hôm nay: trong danh sách "xong" của anh em, bao nhiêu mục thật sự đã đổi trạng thái ở phía bên kia?

Nếu câu trả lời là "chưa đếm" — thì thôi, đừng mua thêm tốc độ. Đếm cái đã.

Một phần của chuỗi mổ xẻ kỹ thuật tại zeodavu.com/blog. Nếu thấy hữu ích, theo dõi [zeodavu.com](/blog) — mỗi bài là một thứ mình thật sự dùng, vấp, và sửa lại.