Tool run_command cho agent chạy test, build, cài package, chạy linter. Đây là tool mạnh nhất và nguy hiểm nhất. Bài này tập trung: chạy đúng, đọc kết quả trung thực, và bọc lớp an toàn.
Bước 1: Bắt trọn stdout, stderr, exit code
import subprocess
def run_command(command, cwd=".", timeout=120):
try:
r = subprocess.run(command, shell=True, cwd=cwd,
capture_output=True, text=True, timeout=timeout)
except subprocess.TimeoutExpired:
return f"ERROR: lệnh vượt {timeout}s, đã hủy."
out = r.stdout[-5000:] # cắt bớt output khổng lồ
err = r.stderr[-5000:]
return f"exit_code={r.returncode}\nSTDOUT:\n{out}\nSTDERR:\n{err}"
Ba dữ kiện exit_code + stdout + stderr đều phải trả về. Rất nhiều lỗi (đặc biệt của test runner) chỉ hiện ở stderr. Nếu bạn chỉ trả stdout, agent sẽ "tưởng" mọi thứ ổn.
Bước 2: Cắt output để không tràn context
Lệnh npm install hay pytest -v có thể in hàng nghìn dòng. Nhồi hết vào LLM tốn token và loãng thông tin. Chiến lược: giữ phần cuối (nơi thường chứa lỗi/summary) bằng [-5000:]. Với test, phần tóm tắt "3 failed, 10 passed" nằm ở cuối.
Bước 3: Timeout là bắt buộc
Không có timeout, một lệnh khởi động server (python -m http.server) sẽ chạy mãi và treo agent. Luôn đặt timeout hợp lý; báo rõ khi hết giờ để LLM biết lệnh bị hủy chứ không phải xong.
Bước 4: Lớp an toàn — danh sách chặn và xác nhận
BLOCKED = ["rm -rf /", "rm -rf ~", ":(){:|:&};:", "mkfs", "dd if="]
def guard(command):
low = command.lower()
if any(b in low for b in BLOCKED):
return "BLOCKED: lệnh nguy hiểm bị chặn."
return None
Danh sách chặn không đủ để an toàn tuyệt đối (bài 8 bàn sâu), nhưng là hàng rào đầu tiên chống thảm họa. Với lệnh có tác dụng phụ (xóa, push, deploy), nên yêu cầu xác nhận người dùng trước khi chạy.
Ví dụ: agent chạy test và đọc lỗi
- LLM:
run_command("pytest -q"). - Trả về:
exit_code=1 ... STDERR: AssertionError: expected 5 got 4. - LLM thấy
exit_code=1≠ 0 → biết test rớt, đọc AssertionError → sửa code → chạy lại.
exit_code cho agent tín hiệu nhị phân "đạt/không đạt" rõ ràng nhất.Khung tư duy: lệnh an toàn theo mức rủi ro
- Đọc (an toàn):
ls,cat,grep,pytest,git status— chạy tự do. - Ghi cục bộ (trung bình): tạo/sửa file,
git add— chạy trong thư mục dự án, tránh đường dẫn tuyệt đối ra ngoài. - Phá hủy / mạng (cao):
rm -rf,git push,curl | bash,deploy— cần xác nhận hoặc chặn.
Checklist run_command
- [ ] Trả cả exit_code, stdout, stderr.
- [ ] Có timeout và thông báo khi hết giờ.
- [ ] Cắt output dài, giữ phần cuối.
- [ ] Có guard chặn lệnh phá hủy.
- [ ] Lệnh rủi ro cao cần xác nhận người dùng.
- [ ] Ràng buộc
cwdtrong thư mục dự án.
Sai lầm thường gặp
- Chỉ trả stdout. Bỏ stderr khiến agent mù trước lỗi build/test.
- Không đọc exit_code. Agent "đoán" thành công từ text, dễ sai; exit_code mới là sự thật.
- Không cắt output. Một lần
pip installverbose có thể ngốn cả context window. - Thiếu timeout. Lệnh chạy nền treo agent vô thời hạn.
- Tin danh sách chặn là đủ an toàn. Nó chỉ chặn mẫu đã biết; kẻ xấu/LLM vẫn có thể vòng qua. Cần thêm sandbox (bài 8).