Có một kịch bản tôi thấy lặp lại trong mỗi coding session agentic thất bại:

Lập trình viên giao task cho agent. Agent lập tức bắt đầu viết code. Code trông có vẻ hợp lý. Nó chạy. Có gì đó sai một cách tinh tế. Agent cố fix. Bản fix phá thứ khác. Sau một giờ qua lại, codebase tệ hơn lúc bắt đầu.

Nguyên nhân gốc rễ hầu như không bao giờ là năng lực của agent. Mà là trình tự: code trước, hiểu sau.

Plan mode sửa điều này. Nhưng hầu hết developer bỏ qua nó.


Plan Mode Thực Ra Là Gì

Trong Claude Code, plan mode là sub-agent chỉ đọc chạy trước bất kỳ thay đổi code nào. Nó có thể dùng tất cả tool khám phá — grep, read, knowledge graph traversal, liệt kê file — nhưng không thể viết, sửa, hay xóa bất cứ thứ gì.

Ràng buộc chính là tính năng. Một plan-mode agent không thể fix vấn đề nó tìm thấy. Nó chỉ có thể báo cáo. Điều này buộc agent xây dựng bức tranh đầy đủ về codebase trước khi đề xuất thay đổi.

Output là bản kế hoạch bằng văn bản: file path cụ thể, tên hàm cụ thể, thứ tự thao tác cụ thể, những thứ cụ thể có thể sai.

Plan: Them ho tro giong Chirp3-HD cho TTS endpoint

Files can sua:
1. functions/api/tts.ts (dong 31-89)
   - Doi default voice tu "en-US-Journey-F" sang "en-US-Chirp3-HD-Charon"
   - Them lang param vao TTSRequest interface
   - Them DEFAULT_VOICES map cho en/vi
   - Bo speakingRate trong audioConfig khi voice la Chirp3-HD
   - Them Cloudflare Cache API voi SHA-256 hash key

2. functions/api/tts-config.ts (viet lai hoan toan)
   - Thay danh sach Journey/Studio bang Chirp3-HD voices
   - Them EN_VOICES (8 giong) va VI_VOICES (8 giong)
   - Ho tro ?lang= query param

3. src/components/TTSPlayer.astro (4 patch nham muc tieu)
   - Patch 1: getGoogleVoiceForSpeaker() -- them lang detection, Chirp3-HD defaults
   - Patch 2: fetchChunkAudio() -- them pageLang, truyen lang cho API
   - Patch 3: download fetch -- cap nhat default voice, truyen lang
   - Patch 4: tts-config fetch -- them ?lang= query param

Rui ro: Chirp3-HD khong ho tro speakingRate. Speed control UI van hien thi
nhung khong co tac dung. Chap nhan danh doi de tang chat luong.

KHONG DUOC CHAM DEN: Audio player UI, pre-generated audio detection, browser Speech API fallback.

Đó là một bản kế hoạch. Cụ thể. Có thể thực hiện. Có đánh giá rủi ro rõ ràng.


Chi Phí Khi Bỏ Qua Plan Mode

Để tôi đưa ra so sánh thực tế từ dự án CubLearn.

Không Có Plan Mode: Tích Hợp YLE

Lần đầu tôi yêu cầu agent tích hợp nội dung Cambridge YLE vào game engine CubLearn, tôi mô tả task mơ hồ: “Thêm từ vựng YLE vào English quiz game.”

Agent lập tức bắt đầu viết. Nó tìm english-lessons.ts và bắt đầu thêm data. Nhưng nó thêm data sai format — type VocabWord[] hiện tại kỳ vọng { word, phonetic, meaning, example }, nhưng agent sinh ra { word, definition, usage }. TypeScript compiler bắt được — nhưng chỉ sau khi agent cũng đã sửa 3 file khác tham chiếu data mới.

Rollback tốn 90 phút đọc 4 file để hiểu cái gì đã thay đổi. Không ship được gì.

Có Plan Mode: Nâng Cấp TTS

Nâng cấp TTS đêm qua dùng plan mode từ đầu.

Plan agent dành 8 phút đọc:

  • functions/api/tts.ts (toàn bộ file)
  • functions/api/tts-config.ts (toàn bộ file)
  • TTSPlayer.astro (tìm kiếm 6 pattern cụ thể)
  • wrangler.toml (kiểm tra Cloudflare Cache binding)

Nó tìm ra thứ tôi bỏ sót: Cloudflare Cache API yêu cầu URL https:// làm cache key. Dùng tts-cache.internal/... hoạt động được nhưng cần đúng định dạng URL. Bản kế hoạch đã bao gồm fix này trước khi code bắt đầu.

Tổng thời gian: 28 phút kể cả nghiên cứu, 0 lần rollback.


Cách Viết Specification Tốt

Plan mode chỉ tốt bằng specification bạn cung cấp cho nó. Tôi dùng template nhất quán:

## Task
[Một câu: cái gì đang thay đổi và tại sao]

## Scope
Files task này nên chạm vào:
- [file path] -- [thay đổi gì]
- [file path] -- [thay đổi gì]

Files task này KHÔNG ĐƯỢC chạm vào:
- [file path] -- [lý do]

## Success Criteria
- [ ] [Kết quả cụ thể, có thể xác minh]
- [ ] [Kết quả cụ thể, có thể xác minh]

## Ràng Buộc Đã Biết
- [Giới hạn API, yêu cầu encoding, v.v.]

## Tài Liệu Tham Khảo
- [Link tài liệu liên quan hoặc quyết định trước đó]

Danh sách “KHÔNG ĐƯỢC chạm vào” rất quan trọng. Agent có cơ hội — nếu chúng thấy hàm gần đó trông cần fix, chúng sẽ fix nó. Bản fix đó không được review, không được test, và vô hình trong diff trừ khi bạn nhìn kỹ.

Ranh giới scope rõ ràng ngăn điều này.


Agent QA Kiểm Tra Gì Trong Plan

Trước khi bất kỳ code nào chạy, agent QA của chúng tôi review bản kế hoạch. Đây là nơi hầu hết plan bị reject.

Đây là log reject thực tế (đã ẩn danh) từ tích hợp memory card CubLearn:

QA REVIEW -- Plan Bi Reject (Lan 1)

Vấn đề tìm thấy:

1. SCOPE KHONG DAY DU
   Plan sua memory-pairs.ts nhung khong de cap den
   MemoryGame component doc data nay. Component
   ky vong { front: string, back: string } nhung plan them
   { front: string, back: string, category: string }.
   Hoac cap nhat component hoac giu type hien tai.

2. THIEU TESTS
   Khong co nhan den test cho 3 CardPair array moi.
   Lam sao xac minh data hop le (khong co string rong, khong trung lap)?

3. RUI RO STUB
   Plan de cap "14 bai luyen phat am" nhung khong liet ke chung.
   LLM thuong stub khi het context. Yeu cau plan
   liet ke tat ca 14 exercise ID va difficulty level ky vong.

Tra ve: Can ban ke hoach duoc sua.

Agent sửa lại plan. Lần thứ hai passed.

Review này ngăn được:

  • Type mismatch phá Memory game
  • 14 bài tập bị thay bằng 5 bài và comment // TODO: add more
  • Thiếu test coverage cho data mới

Vấn Đề “Stub” và Cách Plan Mode Giải Quyết

Failure mode tinh quái nhất trong AI coding là stub.

Khi agent gần hết token budget giữa task, nó bắt đầu cắt góc:

  • Function body rỗng với // TODO: implement
  • Giá trị hardcode thay vì logic động
  • console.log thay vì error handling đúng
  • Import statement cho hàm không tồn tại

Agent không thông báo những phím tắt này. Code trông hoàn chỉnh. Nó compile được. Nó fail lúc runtime.

Plan mode giảm stub theo hai cách:

1. Liệt kê rõ ràng. Plan tốt liệt kê từng item cần tạo. “Thêm 14 bài luyện phát âm” trở thành “Thêm bài tập: [liệt kê tất cả 14 với ID, difficulty level, và target phoneme].” Agent không thể stub cái nó đã cam kết rõ ràng.

2. Task nhỏ hơn. Plan mode tự nhiên chia task lớn thành các giai đoạn. Mỗi giai đoạn có trạng thái kết thúc rõ ràng. Agent không hết budget giữa implementation vì mỗi đợt code được scoped.


Plan Mode Trong Thực Tế: Tích Hợp YLE CubLearn

Đây là bản kế hoạch thực tế ship 22 bài YLE blog posts, 8 bài học game, và 14 bài luyện phát âm trong một session:

Giai đoạn 1: Nội dung blog (22 file)

  • Starters batch 2: Numbers (en + vi), Food (en + vi), Clothes (en + vi), Mock Test (en + vi)
  • Movers đầy đủ: Sports (en + vi), Transport (en + vi), Weather (en + vi), Mock Test (en + vi)
  • Flyers đầy đủ: Guide (en + vi), Story Writing (en + vi), Mock Test (en + vi)

Giai đoạn 2: Game data

  • english-lessons.ts: 8 lesson object theo đúng type EnglishLesson[] hiện tại
  • memory-pairs.ts: 3 card set array với 16 CardPair[] mỗi cái

Giai đoạn 3: Phát âm

  • pronunciation.ts: 3 exercise bank (en-yle-starters, en-yle-movers, en-yle-flyers)
  • 14 bài tập tổng cộng, difficulty 1-3, liệt kê rõ ràng

Ràng buộc:

  • Tất cả lesson object phải khớp { id, title, titleVi, level, vocabulary: VocabWord[], quiz: EnglishQuizQuestion[] }
  • Không stub — mỗi vocabulary array phải có tối thiểu 8 từ, mỗi quiz phải có tối thiểu 4 câu hỏi
  • Nội dung tiếng Việt phải có dấu đầy đủ (không ASCII thuần)

Agent thực thi theo plan này với zero stub. Agent QA xác minh mỗi file trước khi giai đoạn tiếp theo bắt đầu.


Quy Tắc 5 Phút

Quy tắc của tôi: nếu tôi không mô tả được task trong 5 phút viết rõ ràng, task đó quá mơ hồ cho agent.

Task mơ hồ: “Thêm tính năng cho blog”

Task rõ ràng: “Thêm ước tính thời gian đọc vào meta bar của bài blog. Tính theo Math.ceil(wordCount / 200) phút. Hiển thị là X phút đọc cạnh ngày đăng trong BlogPostLayout.astro. Không sửa CSS nào ảnh hưởng đến meta element khác.”

Phiên bản thứ hai có thể được lên kế hoạch. Phiên bản đầu sẽ tạo ra 45 phút thrashing.

Viết spec trước. Rồi plan. Rồi code.


Đây là Phần 2 của series “Xây Bằng Agentic Engineering”. Trước: Cách Làm Phần Mềm Mới Tiếp theo: Agent QA — Xac Minh Code Tu Dong

Xuất nội dung

Bình luận