Tại sao "harness" của tác nhân AI nên nằm bên ngoài sandbox?

02 tháng 5, 2026·7 phút đọc

Bài viết phân tích kiến trúc của các tác nhân AI (AI agents), so sánh việc đặt vòng lặp điều khiển (harness) bên trong hay bên ngoài sandbox. Tác giả lập luận rằng đối với môi trường đa người dùng, việc đặt harness bên ngoài sandbox mang lại lợi thế lớn về bảo mật, quản lý tài nguyên và chia sẻ trạng thái, dù đi kèm với những thách thức về thực thi bền bỉ và ảo hóa hệ thống tệp.

Tại sao "harness" của tác nhân AI nên nằm bên ngoài sandbox?

Tại sao "harness" của tác nhân AI nên nằm ngoài sandbox?

Trong thế giới phát triển các tác nhân AI (AI agents), một câu hỏi kiến trúc quan trọng thường bị bỏ qua là: Vòng lặp điều khiển (agent harness) nên chạy ở đâu? Harness là thành phần quan trọng, đóng vai trò như "bộ não" điều phối, gửi prompt đến mô hình ngôn ngữ lớn (LLM), nhận phản hồi, thực thi các công cụ (tool calls) và lặp lại quy trình cho đến khi nhiệm vụ hoàn thành.

Mặc dù mọi tác nhân sản xuất đều cần một harness, vị trí của nó — bên trong hay bên ngoài sandbox — lại quyết định tính bảo mật, khả năng chịu lỗi và quy mô của hệ thống. Đối với các hệ thống đơn người dùng (như một kỹ sư sử dụng trên laptop), việc đặt harness bên trong sandbox có thể chấp nhận được. Tuy nhiên, với môi trường đa người dùng (nhiều kỹ sư chia sẻ cùng một tác nhân), việc đặt harness bên ngoài sandbox mới là giải pháp tối ưu.

Kiến trúc tổng quanKiến trúc tổng quan

Hai kiến trúc phổ biến

Harness nằm bên trong Sandbox

Đây là mô hình đơn giản nhất, nơi vòng lặp điều khiển sống cùng trong container với mã nguồn mà nó đang thao tác. Các lệnh gọi LLM đi ra từ bên trong container, và các công cụ như bash, read, write được thực thi cục bộ. Các kỹ năng (skills), ký ức (memories) và dữ liệu khác được lưu trực tiếp trên hệ thống tệp của container. Đây là cách Claude Code hoạt động khi bạn chạy nó trên máy tính cá nhân.

Harness nằm bên ngoài Sandbox

Trong mô hình này, vòng lặp chạy trên backend của bạn. Khi cần thực thi một công cụ, nó gọi đến sandbox thông qua API. Sandbox chạy công cụ và trả về kết quả, nhưng vòng lặp điều khiển không bao giờ bước vào bên trong sandbox.

Tại sao chọn mô hình "Bên ngoài"?

Mặc dù mô hình bên trong đơn giản và dễ sử dụng các harness có sẵn (off-the-shelf), mô hình bên ngoài mang lại những lợi thế không thể bỏ qua cho các hệ thống sản xuất quy mô lớn.

Bảo mật tốt hơn Thông tin xác thực (credentials) của bạn sẽ không bao giờ nằm trong sandbox. Vòng lặp giữ các khóa API LLM, token người dùng và quyền truy cập cơ sở dữ liệu. Sandbox chỉ chứa môi trường làm việc tối thiểu cần thiết cho tác nhân. Nếu không có gì để "thoát ra" (escape), bạn không cần thực thi mô hình quyền hạn phức tạp hay lo lắng về việc rò rỉ chứng chỉ.

Quản lý vòng đời Sandbox linh hoạt Bạn có thể tạm dừng (suspend) sandbox khi tác nhân không sử dụng đến. Rất nhiều hành động của tác nhân như suy nghĩ, gọi API, tóm tắt hoặc chờ CI không cần đến sandbox. Với harness bên ngoài, bạn chỉ cấp phát sandbox khi cần chạy lệnh và tạm ngưng nó khi rảnh rỗi. Điều này giúp tiết kiệm tài nguyên đáng kể.

Vòng đời SandboxVòng đời Sandbox

Khả năng phục hồi cao Sandboxes trở nên "vô giá trị" (cattle). Nếu một sandbox chết giữa chừng, vòng lặp chỉ việc cấp phát một cái mới và tiếp tục công việc. Nếu harness nằm bên trong, việc mất sandbox đồng nghĩa với việc mất toàn bộ phiên làm việc (session).

Giải quyết vấn đề đa người dùng Khi nhiều kỹ sư trong cùng một tổ chức sử dụng một tác nhân, họ cần chia sẻ kỹ năng và ký ức. Với harness bên ngoài, đây đơn giản là một cơ sở dữ liệu dùng chung. Nếu nằm bên trong, bạn sẽ phải đối mặt với bài toán khó khăn về hệ thống tệp phân tán (distributed filesystem).

Các thách thức và giải pháp

Chúng tôi đã chọn mô hình bên ngoài, nhưng để nó hoạt động hiệu quả, ba vấn đề lớn cần được giải quyết.

1. Thực thi bền bỉ (Durable Execution)

Vòng lặp của tác nhân là một hàm chạy dài (từ vài phút đến vài giờ) và phải sống sót qua các lần triển khai (rolling deploys) hay sự cố máy chủ. Giữ vòng lặp trong bộ nhớ của máy chủ API sẽ khiến nó bị mất ngay khi bạn cập nhật phiên bản mới.

Giải pháp của chúng tôi là sử dụng Inngest. Vòng lặp trở thành một hàm của Inngest, trong đó mỗi lượt quay (turn) là một bước (step) được lưu trữ trạng thái. Nếu máy chủ khởi động lại, vòng lặp sẽ tiếp tục từ điểm nó dừng lại.

2. Vòng đời Sandbox

Vấn đề lớn nhất là "khởi động nguội" (cold starts). Một sandbox mất vài giây để khởi động, quá chậm đối với một tương tác theo thời gian thực. Chúng tôi sử dụng Blaxel, cho phép khôi phục sandbox từ trạng thái chờ chỉ trong 25ms. Điều này đủ nhanh để tác nhân không nhận ra sandbox đã từng biến mất.

3. Hệ thống tệp ảo hóa

Các harness hiện đại giả định mọi thứ là tệp cục bộ: kỹ năng là tệp .md, ký ức cũng là tệp .md. Nhưng với sandbox bên ngoài, sandbox là tạm thời (ephemeral). Nếu nó chết và một cái mới được tạo ra, mọi dữ liệu ghi trên hệ thống tệp sẽ biến mất. Hơn nữa, việc chia sẻ dữ liệu giữa nhiều người dùng trở nên phức tạp.

Giải pháp là ngừng giả định và đưa kỹ năng, ký ức vào cơ sở dữ liệu. Tuy nhiên, chúng tôi vẫn muốn tác nhân "nghĩ" rằng nó đang thao tác trên tệp.

Phân luồng đường dẫnPhân luồng đường dẫn

Chúng tôi tạo ra một lớp ảo hóa hệ thống tệp. Tác nhân chỉ có một công cụ đọc và một công cụ ghi. Khi nó gọi các công cụ này, harness sẽ kiểm tra đường dẫn:

  • Các đường dẫn trong không gian làm việc (workspace) sẽ được chuyển đến sandbox như bình thường.
  • Các đường dẫn trong không gian kỹ năng/ký ức sẽ được chuyển đến cơ sở dữ liệu (ví dụ: Postgres).

Tác nhân không biết sự khác biệt. Đối với nó, đó chỉ là hệ thống tệp, dù một số tệp thực sự sống trong một cơ sở dữ liệu.

Tại sao không chỉ thêm công cụ mới?

Một cách tiếp cận phổ biến là cung cấp cho tác nhân các công cụ riêng biệt như memory_readmemory_write song song với readwrite. Tuy nhiên, cách này có hai nhược điểm lớn.

Thứ nhất, quá nhiều công cụ sẽ làm tác nhân hoạt động kém hiệu quả hơn. Mỗi công cụ mới làm loãng sự chú ý của mô hình, làm dài prompt và thêm một quyết định mà mô hình phải đưa ra. Việc có hai công cụ làm gần giống nhau (readmemory_read) đặc biệt gây nhầm lẫn.

Thứ hai, và quan trọng hơn, các mô hình tiên phong hiện nay đang được huấn luyện tăng cường (reinforcement learning) dựa trên các harness giống như Claude Code, với giao diện chuẩn là read(path), write(path, content). Nếu bạn tạo ra memory_read, bạn đang đi chệch khỏi con đường huấn luyện đó. Giao diện ảo hóa giúp giữ nguyên bề mặt API mà mô hình đã được huấn luyện, đồng thời xử lý ngữ nghĩa cơ sở dữ liệu ở backend.

Những khó khăn còn lại

Mặc dù giải pháp này hiệu quả, vẫn còn những thách thức. Tiêu chuẩn công nghệ (SOTA) thay đổi rất nhanh, và việc không sử dụng Claude Code gốc đồng nghĩa với việc chúng tôi luôn phải chạy đua để hỗ trợ các tính năng mới.

Ngoài ra, Bash là một điểm rò rỉ (leak). Tác nhân có thể sử dụng lệnh grep trong bash để truy cập trực tiếp vào hệ thống tệp thực của sandbox, bỏ qua lớp ảo hóa. Chúng tôi xử lý điều này bằng cách hướng dẫn trong system prompt và phân tích cú pháp bash, nhưng đây không phải là giải pháp hoàn hảo.

Cuối cùng, vấn đề tính nhất quán (consistency) khi nhiều phiên làm việc cùng cập nhật ký ức vẫn là một câu hỏi mở. Hiện tại chúng tôi sử dụng cơ chế "người ghi sau cùng thắng" (last-writer-wins), nhưng giải pháp này có thể sẽ gặp vấn đề khi quy mô mở rộng.

Bài viết được tổng hợp và biên soạn bằng AI từ các nguồn tin tức công nghệ. Nội dung mang tính tham khảo. Xem bài gốc ↗