# Pi thêm Codemode: MCP chạy trong JavaScript sandbox

[George Kintu](https://homus.dev/speakers/george-kintu) · [kintu](https://homus.dev/orgs/kintu)

> Codemode của Pi chạy MCP tool trong QuickJS sandbox, chỉ trả kết quả gọn cho model; hai test đo token, chi phí, và phản ứng của cộng đồng.

Topics: Coding Agents, Context Engineering, Dev Tools

Canonical: https://homus.dev/talks/pi-agent-just-added-codemode-and-its-insane

## 1. Pi bỏ dòng chữ "No MCP"

George mở video bằng một tin lớn: Pi coding agent vừa tung ra một trong những bản cập nhật lớn nhất của năm, nhưng bản cập nhật này không đến mà không bị soi xét. Lý do là trong phần lớn năm vừa qua, người tạo ra Pi là Mario Zechner, và Armin Ronacher, người tạo ra Flask, thuộc nhóm những người phê bình MCP to tiếng nhất. Trang web của Pi thậm chí còn tự hào tuyên bố thẳng: **No MCP**.

![George Kintu nói trước camera trong phòng làm việc](https://homus.dev/photos/IrQE95cUiMU-0103.jpg)

George Kintu, người dẫn kênh kintu, nói trước camera ở phần mở đầu video.

Hai người từng công khai chỉ trích MCP là thứ phình to, lãng phí token (token-wasting bloat), và lập luận rằng agent thường làm tốt hơn khi chỉ dùng bash, các CLI tool và code. Nhưng giờ dòng tuyên bố đó đã biến mất. Pi vừa ship hỗ trợ MCP native, đi kèm với **Codemode**: một tính năng mới xây quanh một JavaScript sandbox nhúng sẵn, được thiết kế để làm cho MCP hiệu quả hơn rất nhiều.

![Trang chủ Pi, mục No MCP bị gạch đi và thay bằng Now with MCP+Codemode](https://homus.dev/photos/IrQE95cUiMU-0003.jpg)

Trang chủ Pi sau bản cập nhật: dòng "No MCP" bị gạch ngang, thay bằng "Now with MCP+Codemode". Mô tả bên dưới ghi MCP đã được tích hợp sẵn, Codemode cho agent ghép các lời gọi tool trong một JavaScript sandbox, và các extension MCP vẫn được hỗ trợ. Các ô khác như "No sub-agents", "No plan mode", "No background bash" vẫn giữ nguyên.

Trong video này, George hứa ba việc: đi qua những gì đã thay đổi, đem Codemode ra thử đối đầu với plain MCP để xem có khác biệt thật hay không, và phân tích những phản ứng ngược (pushback) mà nhóm Pi nhận được từ cộng đồng sau bản cập nhật.

## 2. Cách agent dùng tool truyền thống: đầu bếp và xe tải khoai tây

Để hiểu vì sao chuyện này quan trọng, trước hết cần nhìn cách AI agent thường dùng tool. Theo cách truyền thống, nếu bạn bảo một agent kiểm tra ticket báo lỗi của 50 khách hàng, nó thường phải làm theo cách khó nhất. Nó hỏi database ticket số một. Database gửi về một đống dữ liệu thô khổng lồ, và AI đọc hết đống đó ngay trong context window của nó. Rồi nó hỏi ticket số hai, và cứ thế lặp đi lặp lại, qua lại, qua lại.

![Hình minh hoạ đầu bếp ngồi soi từng củ khoai tây trên băng chuyền từ một xe tải](https://homus.dev/photos/IrQE95cUiMU-0126.jpg)

Hình minh hoạ phép so sánh của George: một xe tải đổ khoai tây lên băng chuyền, và người đầu bếp phải ngồi cầm kính lúp soi từng củ một, trong khi gian bếp nơi lẽ ra anh ta nấu ăn thì nằm trống ở góc bên kia.

George ví nó như thuê một master chef, nhưng thay vì để người đó nấu ăn, bạn bắt họ kiểm tra từng củ khoai tây trong cả một xe tải, từng củ một. Tất cả dữ liệu thô ấy bắt đầu làm tắc nghẽn bộ nhớ của AI, tức là context window.

## 3. Codemode: một script JavaScript trong QuickJS sandbox

Đây là chỗ Codemode bước vào. Thay vì để AI làm người trung gian cho từng lời gọi tool, AI viết một script JavaScript nhỏ. Script đó chạy bên trong **QuickJS sandbox** nhúng sẵn của Pi, nơi nó có thể lặp qua dữ liệu, gọi các tool song song, tính toán, loại bỏ trùng lặp và lọc rác.

Như vậy, thay vì đổ 50 tool response khổng lồ vào context của frontier model, Codemode "nhai" mớ hỗn độn đó ở phía sau và chỉ trả về những gì quan trọng. Kết quả có thể là một bảng gọn gàng, có thể là năm ticket khớp điều kiện, hoặc chỉ là một câu kiểu "đây là vấn đề nghiêm trọng của ba khách hàng".

![Sơ đồ Keep the bulk inside the sandbox: dữ liệu trung gian ở QuickJS sandbox, chỉ kết quả nhỏ sang context window](https://homus.dev/photos/IrQE95cUiMU-0223.jpg)

Bên trái là QuickJS sandbox giữ toàn bộ dữ liệu trung gian (full tool results stay here); chỉ output của script đi qua ranh giới sang context window của frontier model, ở đây là một dòng "3 critical customers" với ba cái tên ví dụ, để lại chỗ trống cho reasoning ở mức cao.

Toàn bộ ý tưởng là dữ liệu trung gian cồng kềnh nằm lại bên trong sandbox, thay vì tràn vào context của model. Điều đó có thể giảm mạnh lượng token dùng, chi phí và tình trạng context phình to (context bloat).

Trang tài liệu Codemode của Pi mô tả đúng điều này: tool `codemode` cho model viết một script JavaScript gọi các tool khác của Pi và chạy các model không phải LLM như classifier hay model tạo ảnh; chỉ output của script mới tới được model, nên script có thể gọi song song và lọc kết quả lớn trước khi model nhìn thấy. Script chạy như thân của một async function trong QuickJS sandbox, không có Node API, file system, network hay timer; nó chỉ chạm ra thế giới bên ngoài qua tool và model ([pi.dev/docs/latest/codemode](https://pi.dev/docs/latest/codemode)).

## 4. MCP là gì, và vì sao nó làm phình context window

Để AI kết nối được với các tool bên ngoài, ví dụ GitHub, Linear, Slack hay database của một công ty, thì hiển nhiên đó là chỗ của MCP, tức Model Context Protocol. Phần lớn mọi người đã biết MCP là gì, nhưng George nhắc lại nhanh: hãy nghĩ MCP như một sợi cáp USB vạn năng cho AI. Thay vì mỗi app AI phải tự build một integration riêng cho từng dịch vụ, MCP cho chúng một protocol chung để khám phá (discover) và gọi tool.

MCP như một sợi cáp USB vạn năng: nhiều app AI, nhiều dịch vụ, một protocol chung. Vấn đề George chỉ ra không nằm ở protocol mà ở cách agent nạp mô tả tool vào context.

Nhưng vấn đề nằm ở cách nhiều agent xử lý các tool đó. Bạn kết nối một MCP server, và lập tức model bị trao cho một cuốn technical manual khổng lồ giải thích mọi tool, mọi parameter và mọi description, trước cả khi bạn kịp yêu cầu nó làm gì. Kết nối đủ nhiều tool là bạn đốt hàng nghìn token chỉ để giải thích những cái nút mà model có thể không bao giờ bấm tới.

Đây chính là thứ Pi từng chỉ trích. Cách tiếp cận mới của họ về cơ bản là: được thôi, chúng tôi sẽ hỗ trợ MCP, nhưng chúng tôi không đổ tất cả nó vào context.

## 5. Gọi MCP tool như hàm JavaScript

Pi đưa các MCP tool ra dưới dạng những hàm JavaScript có thể gọi được bên trong Codemode, nên model có thể viết một đoạn code gọi tool như gọi một hàm bình thường. Sau đó sandbox lo phần gọi, xử lý kết quả, và chỉ trả lại đúng những gì model cần.

![Sơ đồ Full result in. Selected output out: QuickJS sandbox nhận toàn bộ MCP result, xử lý rồi trả summary](https://homus.dev/photos/IrQE95cUiMU-0343.jpg)

Sơ đồ "Full result in. Selected output out.": bên trong QuickJS sandbox, toàn bộ MCP result (một `CallToolResult` với `content`, `structuredContent`, `isError`) đi qua ba bước Receive (`const result = await tools…`), Process (`data.filter(...)`) và Emit (`text(summary)`). Với frontier model, MCP lúc này trông như một programming interface: Fetch, Process, Return.

Nhờ vậy MCP không còn có cảm giác như một đống tool chat khổng lồ nữa, mà bắt đầu hành xử giống một programming interface bình thường. Dữ liệu trung gian nằm yên trong QuickJS, chỉ phần tóm tắt được đẩy ra ngoài.

## 6. Tool search và progressive disclosure

Nhưng điều này tạo ra một vấn đề khác. Nếu AI không còn có sẵn mọi tool bày ra trước mặt, làm sao nó biết có những tool nào? Pi giải quyết bằng **tool search** và **progressive disclosure**. Thay vì nạp tất cả mọi thứ ngay từ đầu, model chỉ nhận một bản tổng quan gọn nhẹ, về cơ bản nói rằng: bạn có quyền truy cập vào những nhóm tool này.

Vậy nếu bạn nói "update my DNS record", AI không phải đọc qua 2000 tool không liên quan. Nó tìm riêng chữ DNS, thấy những tool có liên quan, xem kỹ đúng cái nó cần, rồi làm tiếp. Bên trong Codemode, nó dùng các hàm như search tools và describe tool.

![Sơ đồ Search. Then describe. với hai hàm searchTools và describeTool](https://homus.dev/photos/IrQE95cUiMU-0423.jpg)

Hai helper khám phá tool của Codemode: `searchTools("DNS")` tìm ứng viên và trả về tên tool kèm mô tả ngắn; `describeTool(name)` xem một tool cụ thể và trả về mô tả đầy đủ cùng TypeScript declaration của nó.

George tóm lại bằng một hình ảnh: thay vì đưa cho model nguyên cuốn sách dạy nấu ăn, Pi đưa cho nó trang mục lục và để nó tự rút ra đúng công thức khi cần. Các tool còn lại không bao giờ cần làm rối cuộc hội thoại.

## 7. System 1 model ngay trong vòng lặp JavaScript

Một tính năng hay khác: Codemode còn có thể gọi một **System 1 model**, ví dụ Jev hoặc một lựa chọn open-weights như Winnow, trực tiếp từ bên trong vòng lặp JavaScript.

George đưa ví dụ: giả sử Pi kéo về 200 comment GitHub qua MCP. Thay vì gửi cả 200 comment đó vào GPT hay Claude, script Codemode có thể cho từng comment đi qua classifier trước. Ví dụ các câu hỏi: người dùng này có đang bực bội không? Cái này có thật sự gấp không? Hoặc nó thuộc nhóm nào? Khi đó System 1 model đứng ra xử lý hàng trăm quyết định ngữ nghĩa nhỏ, trong khi frontier model chỉ nhìn thấy kết quả cuối cùng đã lọc hoặc đã tổng hợp.

![Sơ đồ Each layer has a job: MCP, Codemode với System One, Frontier model](https://homus.dev/photos/IrQE95cUiMU-0523.jpg)

MCP lấy dữ liệu (GitHub comments), Codemode xử lý dữ liệu, bên trong nó System One ra các quyết định ngữ nghĩa nhỏ qua `models.classify()`, rồi lọc, tổng hợp và trả `text(summary)`; frontier model chỉ nhận kết quả đã thu gọn để reasoning ở mức cao.

Như vậy Pi giờ có thể kết hợp MCP để lấy dữ liệu, Codemode để xử lý, System 1 model cho các quyết định ngữ nghĩa nhanh, và frontier model cho phần reasoning ở mức cao thật sự. Theo George, về cơ bản đây là thêm nhiều lớp để bảo vệ model khỏi sự phình to và những việc vặt (busy work) mà nó thực sự không cần làm.

Trên màn hình, trang Hugging Face của Winnow-12B ghi đây là một model cho "local Jev-style decisions", chat và vision, fine-tune từ Gemma 4 12B IT cho các quyết định có kiểu (typed decisions) như chọn lựa (`choice`) hay chấm điểm (`score`), chạy trên một inference server dựa trên llama.cpp.

## 8. Test 1: so sánh 10 mẫu SUV bằng dữ liệu NHTSA

Đến phần thử nghiệm. George dùng Pi coding agent với một model GPT đặt ở mức reasoning high (thanh trạng thái trên màn hình ghi `gpt-6.1-sol • high`) cho các bài test.

Ở test đầu tiên, anh dùng NHTSA MCP: một bộ MCP tool bọc các API công khai về an toàn xe của NHTSA (cơ quan an toàn giao thông đường bộ của Mỹ). Repo của nó trên GitHub mô tả là dữ liệu an toàn xe từ NHTSA gồm recall, complaint, crash rating, investigation và giải mã VIN ([cyanheads/nhtsa-vehicle-safety-mcp-server](https://github.com/cyanheads/nhtsa-vehicle-safety-mcp-server)).

Prompt anh dùng rất dài. George nói sẽ để link trong phần mô tả video, lấy qua newsletter của anh, kèm hướng dẫn cách dựng toàn bộ setup này để bạn tự thử plain MCP đối đầu Codemode. Cùng một prompt được chạy hai lần: một lần ở chế độ plain, tức MCP đi thẳng vào model, và một lần dùng MCP với Codemode. Về cơ bản, prompt yêu cầu so sánh 10 mẫu SUV bằng cách kéo về các thông tin như recall, complaint, crash rating và investigation.

## 9. Kết quả test 1: plain MCP gãy, Codemode chạy hết

George cho xem kết quả. Plain MCP đụng tường gần như ngay lập tức. Vấn đề là các payload thô bị đổ thẳng vào context window của model. Sáu trong 10 mẫu xe không thể hoàn thành đầy đủ. Bản baseline đốt 95.000 uncached token, lần chạy tốn 26 cent, và chỉ xếp hạng được 4 trên 10 mẫu xe.

![Hai cửa sổ terminal Pi cạnh nhau với bảng so sánh SUV, bên trái là test1-plain-mcp](https://homus.dev/photos/IrQE95cUiMU-0715.jpg)

Hai lần chạy cạnh nhau. Bên trái, session `test1-plain-mcp`: bảng có nhiều dòng "unranked" (Ford Escape, Honda CR-V, Kia Sportage, Nissan Rogue, Toyota RAV4, Volkswagen Tiguan), ghi chú rằng dấu gạch nghĩa là chưa xác lập được từ một response đầy đủ, chưa bị cắt; thanh trạng thái ghi khoảng 95k input và 0,266 USD. Bên phải là lần chạy có Codemode với khoảng 21k input.

Rồi anh chạy lại đúng prompt đó với Codemode bật. Lần này, thay vì đổ mọi thứ vào context window, model viết một script nhỏ để fetch, lọc, khử trùng lặp và tính toán mọi thứ bên trong bộ nhớ của sandbox. Khi xong, nó xếp hạng được cả 10 mẫu xe với không lần truncation nào.

Uncached input giảm từ 95.000 xuống còn 21.000, George gọi con số này là điên rồ (insane). Chi phí ước tính cũng giảm từ 26 cent xuống 9 cent. Kết luận của anh: Codemode chắc chắn đáng giá.

Kết quả test 1 theo các con số George đọc: Codemode dùng chưa tới một phần tư uncached input, rẻ hơn khoảng ba lần, và hoàn thành đủ 10 mẫu xe.

## 10. Test 2: phân loại 100 issue của VS Code

Ở test thứ hai, George bảo model phân tích 100 issue công khai của VS Code trong tháng 9. Lần này, bản baseline về cơ bản phải đọc tất cả chỗ đó, rồi tự phân loại chúng ngay trong context. Anh cho xem màn hình đầy chữ và nhấn mạnh: nhìn này, đây là rất nhiều.

Nên hiển nhiên nó gặp vấn đề. Chính model cũng tự nói ra: nó dừng ở 50 thread đã xử lý đầy đủ, vì các source response quá lớn và những lần output bị cắt lặp đi lặp lại khiến không còn đủ context để hoàn thành đáng tin cậy cả 100 thread. Model kiểu như bảo: thế này là quá nhiều. Và George lưu ý con số trên màn hình mới chỉ là phần uncached; nếu tính cả phần cached thì tổng input sẽ vượt xa 1 triệu token. Rốt cuộc nó chỉ đi được nửa đường.

![Terminal Pi của session test2-llm-baseline với bảng thống kê và câu giải thích vì sao model dừng](https://homus.dev/photos/IrQE95cUiMU-0903.jpg)

Session `test2-llm-baseline`: bảng thống kê ghi 0 API call lỗi nhưng 4 lần tool output bị cắt, khung thời gian tìm kiếm từ 2026-09-01 tới 2026-09-30, và câu model tự giải thích rằng nó dừng vì response nguồn quá lớn cùng các lần output bị cắt lặp lại, không đủ context để hoàn thành cả 100 thread, chỉ dùng dữ liệu từ GitHub MCP server chính thức. Thanh trạng thái ghi khoảng 92k uncached input và khoảng 926k token đọc từ cache.

Sau đó anh chạy lại đúng prompt đó (cũng sẽ có link trong mô tả, kèm cách dựng setup), nhưng lần này cho đi qua một classifier model chạy local tên là **Winnow 12B**. Lần chạy này có vấp một chỗ nhưng vẫn vượt qua được, và output khác hoàn toàn: nó hoàn thành đủ 100 issue.

Dù làm trọn 100, uncached input token vẫn thấp hơn nhiều: baseline là 92.000, bản Codemode chỉ 30.000, tức ít hơn khoảng 67%. Theo George, trong một production pipeline, những thứ kiểu này thật sự, thật sự quan trọng để tối ưu mọi thứ. Chi phí cũng vậy: baseline tốn 35 cent, còn với Codemode và một classifier model trong pipeline thì chỉ còn 14 cent.

## 11. Cộng đồng phản ứng: ba phe trên Hacker News

Cùng với bản cập nhật, Earendil, công ty đứng sau Pi, đăng một bài blog về chuyện từng nói "no MCP", và cộng đồng có cảm xúc rất lẫn lộn. George chia phản ứng trên Hacker News thành mấy nhóm.

Đầu tiên là nhóm "tôi đã bảo mà" (who told you so). Ví dụ một người dùng lập luận rằng làn sóng chống MCP đã bỏ qua hoàn toàn phía doanh nghiệp: những thứ như remote credential, ranh giới bảo mật (security boundaries), telemetry, và việc quản lý tool giữa nhiều team.

Rồi đến nhóm ở giữa. Một người dùng nói MCP có thể có khuyết điểm, nhưng các chuẩn như USB-C hay HDMI cũng vậy, và tới một lúc nào đó, một hệ sinh thái khổng lồ vẫn tốt hơn bảy cách "hoàn hảo" khác nhau để làm cùng một việc.

![Một comment trên Hacker News so sánh MCP với USB-C, NVMe và HDMI](https://homus.dev/photos/IrQE95cUiMU-0943.jpg)

Comment trên Hacker News, câu đầu được tô vàng: "I appreciate their reluctance towards MCP, but /something/ is better than nothing." Người viết nói MCP chưa tối ưu, nhưng USB-C, NVMe và HDMI cũng thế (hai mũi tên đỏ chỉ vào), và họ thà có hệ sinh thái MCP rộng như hiện nay còn hơn bảy, tám cách "tối ưu" khác nhau để cắm một LLM vào thứ gì đó hữu ích.

Nhưng có những người dùng Pi không vui. Ví dụ một người viết: vậy là Pi cũng đang tích tụ đồ thừa (cruft) rồi. Câu đó gần như tóm gọn phe tối giản (minimalist camp): họ lo Pi đang dần trở thành chính cái harness phình to mà ban đầu nó cố tránh.

## 12. Armin Ronacher trả lời: Codemode không phải bash thêm bước

Ngay cả Armin Ronacher, người George giới thiệu là người tạo ra Pi, cũng nhảy vào phần trả lời để phản bác. Ông nói không có thứ gì được nạp mặc định mà trước đây chưa từng được nạp.

Ông cũng giải thích rằng Codemode không chỉ là bash thêm vài bước. Bash chạy các shell tool, còn Codemode cho model điều phối (orchestrate) các tool ngay bên trong harness.

![Trả lời của Armin Ronacher trên Hacker News về Codemode và bash](https://homus.dev/photos/IrQE95cUiMU-1023.jpg)

Trả lời trên Hacker News: codemode giải một bài toán khác bash, vì bash là cách để agent chạy một tool cụ thể là bash; câu được tô vàng: "Codemode is a way for the LLM to orchestrate harness level tools." Ông nói chuyện này xảy ra lúc này vì các model của những phòng lab ngày càng được train cho việc đó, và lấy ví dụ Codex.

Rồi có một người dùng mà theo George có lẽ tóm gọn cả tình huống hay nhất. Người đó nói: giống như VHS và Betamax, đôi khi bạn phải chấp nhận rằng marketing thắng sự thuần khiết về mặt engineering. Và đó về cơ bản là chỗ mọi chuyện dừng lại: MCP vẫn còn khuyết điểm, nhưng nó đã thắng cuộc chiến về hệ sinh thái và phân phối (distribution).

## 13. Không chỉ Pi: Claude Code, Codex và OpenCode cũng đi hướng này

Pi cũng không đơn độc ở đây. Claude Code và Codex đều đã chuyển sang lazy tool loading, tức là MCP tool được tìm kiếm và kéo vào context chỉ khi cần.

![Tài liệu OpenCode: Code Mode is the default, kèm ví dụ cấu hình MCP server với codemode false](https://homus.dev/photos/IrQE95cUiMU-1103.jpg)

Tài liệu của OpenCode, mục Permissions, câu được tô vàng "Code Mode is the default.": đặt `codemode` thành `false` khi tool của một server phải ở lại danh sách tool thường; phía trên là ví dụ tool được gom theo tên server, kiểu `tools.context_7.resolve_library_id(...)`.

Còn OpenCode thì đi xa hơn nữa: phiên bản mới nhất của nó mặc định chạy MCP qua chính Codemode của nó, rất giống cách tiếp cận của Pi. Trước đó George cũng cho xem trang tài liệu MCP của Claude Code ở mục "Scale with MCP tool search", nơi ghi rằng tool search giữ mức dùng context cho MCP ở mức thấp bằng cách hoãn nạp định nghĩa tool tới khi Claude cần ([code.claude.com/docs/en/mcp](https://code.claude.com/docs/en/mcp)).

Cuối video, George hỏi người xem: Pi có quyết định đúng khi đón nhận MCP cùng Codemode, hay lẽ ra họ nên giữ nguyên các CLI tool của mình? Anh mời mọi người để lại ý kiến ở phần bình luận, và kèm câu kêu gọi like, subscribe quen thuộc. Anh chào bằng câu "my name is kintu, and until next time, keep building".

## Nguồn và liên kết

- Tên gốc: Pi Agent Just Added CODEMODE… and It’s INSANE!
- Sự kiện: [YouTube](https://homus.dev/events/youtube)
- Video gốc: [https://www.youtube.com/watch?v=IrQE95cUiMU](https://www.youtube.com/watch?v=IrQE95cUiMU)

- Kênh YouTube kintu (George Kintu): [youtube.com/channel/UCErxiWgasjxeqJGYiCvBqMw](https://www.youtube.com/channel/UCErxiWgasjxeqJGYiCvBqMw)

- Tài liệu Codemode của Pi (script, globals, gọi tool, models, classify, giới hạn): [pi.dev/docs/latest/codemode](https://pi.dev/docs/latest/codemode)

- Trang chủ Pi, mục "Now with MCP+Codemode": [pi.dev](https://pi.dev/)

- Model Context Protocol: [modelcontextprotocol.io](https://modelcontextprotocol.io/)

- NHTSA vehicle safety MCP server dùng trong test 1: [github.com/cyanheads/nhtsa-vehicle-safety-mcp-server](https://github.com/cyanheads/nhtsa-vehicle-safety-mcp-server)

- Claude Code, tài liệu MCP và tool search: [code.claude.com/docs/en/mcp](https://code.claude.com/docs/en/mcp)

Nguồn: https://homus.dev/talks/pi-agent-just-added-codemode-and-its-insane · cập nhật 2026-10-15
