Originally published on NextFuture
Bạn đang trong flow. Claude Code xử lý một refactor phức tạp. Bạn rời bàn phím lấy cà phê, quay lại, agent vẫn đang “thinking”. Terminal trông bận rộn, nhưng thực ra không có gì đang chạy — và bill API vừa tăng thêm 20 đô.
Đây không phải chuyện hiếm gặp với Claude Code tốn tiền theo kiểu âm thầm. Một bug vừa được báo cáo trên repo Claude Code, số hiệu #76837, cho thấy khi Claude Code chạm token limit, nó tự động retry liên tục thay vì dừng lại và báo lỗi.
Bill là tín hiệu cảnh báo duy nhất bạn nhận được — sau khi tiền đã mất.
Vấn đề không chỉ nằm ở Claude Code. Một pipeline bốn agent dự kiến tốn khoảng 0.80 đô mỗi lần chạy có thể đốt tới 47 đô chỉ trong một ngày, vì một researcher agent kẹt trong loop mà không ai phát hiện kịp. 57% tổ chức đã chạy AI agent trong production — phần lớn dev đọc bài này đang đứng trước rủi ro tương tự, dù chưa nhận ra.
Bài này đi thẳng vào các bước đặt giới hạn chi phí AI agent cụ thể: nhận diện đúng pattern đốt tiền, rồi dựng từng lớp phòng thủ — retry cap, timeout, budget alert, kill-switch. Mọi bước đều áp dụng được ngay, không cần đợi vendor fix bug.
Nhận diện hai pattern khiến Claude Code tốn tiền
Trước khi chặn, bạn cần phân biệt hai kiểu lỗi tốn tiền khác nhau. Chúng trông giống nhau trên bề mặt nhưng cần fix theo cách khác nhau.
Auto-retry khi chạm token limit
Đây là trường hợp bug #76837 mô tả. Agent chạm giới hạn token trong một request, nhận lỗi từ API, rồi tự động thử lại — với context đã tích lũy từ lần trước, tức là tốn nhiều token hơn. Vòng lặp này lặp lại nhiều lần, mỗi lần retry đắt hơn lần trước, cho đến khi bạn phát hiện qua bill, không phải qua terminal.
Agent loop kẹt (stuck agent loop)
Khác với auto-retry, agent loop kẹt xảy ra khi một agent trong pipeline không đạt điều kiện dừng. Ví dụ một researcher agent cứ gọi lại tool tìm kiếm vì không nhận đủ tín hiệu “đã xong”. Không có lỗi API nào xuất hiện, agent vẫn chạy “hợp lệ”, chỉ là hợp lệ vô thời hạn. Đây chính là cách một pipeline giá 0.80 đô mỗi lần chạy đội lên 47 đô.
Cả hai pattern có chung một đặc điểm: không có tín hiệu dừng rõ ràng, và không có ai theo dõi cho đến khi nhìn hoá đơn.
Bước 1: Đặt retry cap và timeout cứng cho mọi call
Chốt chặn đầu tiên là giới hạn số lần retry và thời gian tối đa cho một task. Đừng để agent tự quyết định khi nào dừng — code phải quyết định thay nó. Ví dụ dưới đây minh họa ý tưởng cấu hình, không phải flag thật của bất kỳ SDK nào:
// Ví dụ minh họa — cấu hình retry/timeout cho một agent call
const agentConfig = {
maxRetries: 2, // dừng sau 2 lần retry, không chạy vô hạn
retryBackoffMs: 1000, // backoff tuyến tính, không retry dồn dập
taskTimeoutMs: 90000, // hard timeout: 90 giây mỗi task
onTimeout: (taskId) => {
logAndKill(taskId, 'timeout_exceeded'); // log rồi kill, không im lặng bỏ qua
},
};
Retry cap phải áp cho toàn bộ chuỗi gọi, không chỉ một request đơn lẻ. Nếu agent retry ở tầng tool call rồi lại retry ở tầng orchestrator, bạn có hai lớp retry nhân lên nhau — đúng cơ chế khiến bill tăng theo cấp số nhân.
Bước 2: Giới hạn chi phí AI agent theo giờ, không chỉ theo tháng
Alert cuối tháng vô dụng khi agent đốt 47 đô chỉ trong một buổi chiều. Bạn cần ngưỡng chi phí theo giờ, tính riêng cho từng pipeline hoặc từng agent, không gộp chung toàn bộ tài khoản.
// Ví dụ minh họa — kiểm tra ngưỡng chi phí theo giờ
async function checkHourlyBudget(pipelineId, spentUsd) {
const HOURLY_CAP_USD = 5; // chỉnh theo baseline thực tế của bạn
if (spentUsd > HOURLY_CAP_USD) {
await notifySlack(`Pipeline ${pipelineId} vượt budget: $${spentUsd}/h`);
await pausePipeline(pipelineId);
}
}
Đặt ngưỡng dựa trên baseline thực tế. Nếu một run bình thường tốn 0.80 đô, cap theo giờ ở mức gấp 5-10 lần baseline là hợp lý, không phải một con số tùy tiện chọn đại.
Bước 3: Giám sát real-time thay vì hậu kiểm qua bill
Bill là tín hiệu chậm nhất để phát hiện sự cố. Bạn cần một lớp giám sát chạy song song, theo dõi số token và số call theo thời gian thực, không phải chờ báo cáo cuối kỳ.
- Log số token tiêu thụ theo từng step của agent, không chỉ theo từng session.
- Cảnh báo khi một agent gọi cùng một tool quá N lần liên tiếp — dấu hiệu điển hình của agent loop kẹt.
- Theo dõi thời gian “thinking” không kèm output — terminal bận nhưng không tiến triển chính là dấu hiệu của lỗi dạng #76837.
Dashboard không cần phức tạp. Một bảng đơn giản hiển thị chi phí tích lũy theo từng pipeline, cập nhật mỗi phút, đã đủ để bạn phát hiện bất thường trước khi nó thành hoá đơn 47 đô.
Bước 4: Dựng kill-switch tự động, đừng chỉ dựa vào con người
Alert chỉ có tác dụng nếu có người đọc nó ngay lúc đó. Với 57% tổ chức đã chạy agent trong production, bạn không thể giả định luôn có người trực dashboard 24/7. Kill-switch tự động là lớp phòng thủ cuối cùng, không phụ thuộc con người.
// Ví dụ minh họa — kill-switch tự động khi vượt ngưỡng tuyệt đối
async function enforceKillSwitch(pipelineId) {
const spent = await getCumulativeSpend(pipelineId);
const HARD_CAP_USD = 20; // ngưỡng tuyệt đối, không được vượt qua
if (spent >= HARD_CAP_USD) {
await killAllAgentProcesses(pipelineId);
await notifyOnCall(`Kill-switch kích hoạt: ${pipelineId} đã tốn $${spent}`);
}
}
Ngưỡng kill-switch nên thấp hơn mức bạn sẵn sàng mất trong trường hợp xấu nhất, không phải mức bạn kỳ vọng chi tiêu trung bình.
Kết luận: kiểm soát chi phí API LLM là năm lớp phòng thủ cộng dồn
Auto-retry và agent loop kẹt đều chạy “hợp lệ” về mặt kỹ thuật cho đến khi bạn nhìn hoá đơn. Retry cap, timeout, giới hạn chi phí AI agent theo giờ, giám sát real-time và kill-switch là năm lớp phòng thủ độc lập — mất một lớp không có nghĩa mất toàn bộ.
Bắt đầu từ lớp rẻ nhất: retry cap và timeout cứng thêm được vào code trong một buổi chiều. Budget alert và kill-switch cần thêm hạ tầng, nhưng đáng công khi một lần kẹt loop có thể biến 0.80 đô dự kiến thành 47 đô thực tế.
This article was originally published on NextFuture. Follow us for more fullstack & AI engineering content.
Top comments (0)