Tôi đọc source code bị leak của Claude Code — và nhận ra mình đang build agent sai từ đầu

Khi Claude Code bị leak, mọi người chú ý đến drama xung quanh vụ leak. Mình chú ý đến harness. Đọc kỹ phần đó, mình thấy mình đang nhìn vào một production agentic system thật sự được vận hành ở scale lớn — và hầu hết những thứ mình tự làm từ trước đến nay đều thiếu những thành phần quan trọng.

$ git log --oneline --stat
✍️ author: duthaho 📅 date: 25/04/2026 ⏱️ read: ...
agentic-patterns.md readonly

Trong năm qua mình đã build một số agent — tool nội bộ, automation workflow, chatbot gọi API. Không phải scale lớn, nhưng đủ để gặp những vấn đề quen thuộc: agent quên context giữa session, thực hiện hành động nguy hiểm mà không hỏi, chạy tuần tự những việc hoàn toàn có thể song song, và hành vi không nhất quán tuỳ theo độ dài conversation. Mỗi lần gặp mình fix theo kiểu ad-hoc. Chưa bao giờ nghĩ đến chúng như một hệ thống có cấu trúc.

Khi source code Claude Code bị leak, mình dành một buổi tối đọc phần harness. Và cái mình thấy ở đó không phải là code thần kỳ hay thuật toán phức tạp — mà là một tập hợp các quyết định kiến trúc rất có chủ đích, giải quyết đúng những vấn đề mình đã gặp, theo cách mình chưa từng nghĩ đến. Mình ngồi formulate chúng thành 12 patterns để dễ nhớ và dễ áp dụng.

Tại sao source code nói được những thứ documentation không nói

Anthropic có documentation về Claude Code. Có blog posts, có hướng dẫn. Nhưng documentation nói về cách dùng — không phải cách nó được xây dựng bên trong. Đây là khoảng cách mà mọi production system đều có giữa public narrative và private reality.

Claude Code được dùng bởi hàng triệu developer. Những quyết định architecture trong harness của nó đã trải qua kiểm chứng thực tế ở scale mà hầu hết các agent framework chưa bao giờ đạt đến. Khi nhìn vào source code thật, bạn đang nhìn vào những gì thực sự work — không phải những gì ai đó nghĩ sẽ work trong lúc viết blog post.

Cách mình đọc code này

Mình không đọc theo kiểu "Claude Code làm gì." Mình đọc theo kiểu "vấn đề nào đây đang giải quyết, và tại sao họ chọn giải pháp này chứ không phải giải pháp khác." Pattern không phải implementation — pattern là tên gọi cho một solution đã được kiểm chứng cho một vấn đề tái diễn. Khi bạn có tên, bạn nhận ra vấn đề nhanh hơn khi nó xuất hiện lần sau.

Mình chia 12 patterns thành 4 nhóm theo loại vấn đề chúng giải quyết: memory & context, workflow & orchestration, tools & permissions, và automation. Cùng nhau, chúng không phải là một framework — chúng là một bộ công cụ tư duy để nhận diện và xử lý các vấn đề tái diễn của agentic systems.

Nhóm 1 — Memory & Context

Pattern 01
Persistent Instruction File

File config project-level (CLAUDE.md) được load tự động mỗi session. Chứa build commands, naming conventions, architecture rules. Đi kèm với repo. Không có file này, mỗi session bắt đầu từ đầu — agent lặp lại cùng sai lầm từ session trước. Trade-off: file stale có thể tệ hơn không có file — agent học quy tắc cũ và apply nhầm.

Pattern 02
Scoped Context Assembly

Instructions được load từ nhiều files theo scope lồng nhau: organization → user → project root → parent dirs → current dir. Agent thấy rules khác nhau tuỳ vào nó đang làm việc ở đâu trong codebase. Phù hợp với monorepo hay codebase đa ngôn ngữ. Trade-off: rules từ nhiều scope có thể conflict, gây behavior khó predict và debug.

Pattern 03
Tiered Memory

Memory chia ba tầng với cách load khác nhau: compact index (capped 200 lines) luôn trong context; topic-specific files load on demand khi task liên quan; full session transcripts chỉ được search khi cần. Không phải nhớ nhiều hơn — mà nhớ đúng thứ đúng lúc. Trade-off: cần logic để quyết định thông tin nào thuộc tầng nào, và khi nào promote hoặc demote.

Pattern 04
Dream Consolidation

Background process chạy lúc agent idle: merge duplicates, prune contradictions, reorganize memory index. Code gọi là autoDream — 8 phases memory management, 5 types context compaction. Garbage collection cho agent state, không phải cho data. Trade-off: consolidation dùng token và có thể prune thứ user vẫn cần nếu quá aggressive.

Pattern 05
Progressive Context Compaction

Khi context window gần full, áp dụng nhiều tầng compression theo độ tuổi: recent turns giữ nguyên, older turns summarize nhẹ, rất cũ thì collapse aggressively. Harness dùng bốn tầng: HISTORY_SNIPMicrocompactCONTEXT_COLLAPSEAutocompact. Trade-off: lossy — agent có thể hallucinate khi cần thứ đã bị collapse thay vì thừa nhận nó quên.

Nhóm 2 — Workflow & Orchestration

Pattern 06
Explore-Plan-Act Loop

Ba phases với write permissions tăng dần. Explore: chỉ read, search, map codebase — không được edit. Plan: thảo luận approach với user. Act: full tool access. System prompt chủ động ngăn agent edit file khi chưa hiểu đủ context. Trade-off: thêm turns trước khi có output — cảm giác chậm với task nhỏ, nhưng cần thiết với task lớn.

Pattern 07
Context-Isolated Subagents

Các agent riêng biệt với context window, system prompt, và tool access riêng. Research agent không thể edit code. Planning agent không thể execute commands. Mỗi subagent chỉ thấy thứ nó cần — context không bị ô nhiễm bởi output của phase khác. Trade-off: coordination overhead, và nuance từ phase trước có thể mất trong handoff.

Pattern 08
Fork-Join Parallelism

Spawn nhiều subagents song song, mỗi cái trong git worktree riêng. Parent's cached context được reuse bởi mỗi fork — parallel branching gần như free về token cost. Merge khi tất cả branches xong. Task 20 files độc lập không cần chạy 20 steps tuần tự. Trade-off: khi parallel branches đụng cùng files, merge conflict phức tạp hơn sequential work nhiều.

Nhóm 3 — Tools & Permissions

Pattern 09
Progressive Tool Expansion

Default tool set nhỏ hơn 20 tools — Read, Edit, Write, Bash, Grep, Glob và một số nữa. MCP tools, remote tools, custom skills chỉ activate khi cần. Ít tools hơn nghĩa là model chọn đúng hơn, ít bị overwhelmed bởi tool selection problem. Trade-off: expansion logic phức tạp — activate quá muộn khiến agent waste turns không có đúng tool.

Pattern 10
Command Risk Classification

Deterministic pre-parsing trước khi execute shell command: phân tích verb, flags, target để assess risk. Low-risk actions auto-approve. Dangerous actions qua safety classifier. Per-tool permission rules với allow/ask/deny pattern matching — không phải approval fatigue, không phải blind trust. Trade-off: classifier cứng nhắc, không anticipate được mọi edge case — cần tune liên tục.

Pattern 11
Single-Purpose Tool Design

Thay vì dùng general shell cho mọi file operation, xây purpose-built tools riêng: FileReadTool, FileEditTool, GrepTool, GlobTool. Mỗi tool có typed inputs, constrained scope, permission rules riêng. Dễ review, dễ permission, model dùng đúng hơn, và dễ restrict hơn khi cần. Trade-off: không cover hết edge cases, vẫn cần general shell làm fallback cho những thứ không fit vào tool nào.

Nhóm 4 — Automation

Pattern 12
Deterministic Lifecycle Hooks

Shell commands chạy tự động tại các điểm xác định trong agent lifecycle — hoàn toàn ngoài prompt. Harness có 25+ hook points: PreToolUse, PostToolUse, SessionStart, CwdChanged và nhiều nữa. Thứ gì phải xảy ra mỗi lần không có ngoại lệ — đặt vào hook, không đặt trong instruction. Trade-off: debug hooks khó hơn prompt instructions vì chúng chạy ngoài conversation flow.

Ba cái làm mình ngừng đọc và suy nghĩ lại

Không phải tất cả 12 patterns đều gây cho mình cùng một phản ứng. Có những cái mình đọc và nghĩ "ừ hợp lý, mình cũng làm gần giống vậy." Nhưng có ba cái khiến mình phải dừng lại thật sự.

Dream Consolidation là cái mình chưa bao giờ nghĩ đến, dù vấn đề nó giải quyết thì mình đã gặp. Memory của agent tích lũy mà không có cơ chế dọn dẹp — entries trùng lặp, facts cũ mâu thuẫn với facts mới, index phình to đến mức không còn compact nữa. Mình fix bằng cách reset memory thủ công. autoDream giải quyết vấn đề đó tự động, trong idle time, với 8 phases và 5 types compaction. Tên cũng khá hay — ẩn dụ về cách não người consolidate memory lúc ngủ là accurate hơn mình nghĩ.

Explore-Plan-Act Loop là cái mình đồng ý mạnh nhất từ kinh nghiệm thực tế. Lỗi phổ biến nhất mình thấy trong các agent mình build là agent nhảy vào edit file trước khi đọc đủ context — sửa đúng vấn đề nhưng sai file, hoặc đúng file nhưng sai pattern vì không biết codebase hiện tại đang làm gì. Tách phase explore khỏi act, và enforce điều đó qua system prompt và tool permissions, không phải qua lời nhắc — đó là thứ mình cần làm từ lâu mà chưa làm.

Model không "quên" procedural steps. Nó không nhất quán dưới load. Hooks loại bỏ sự không nhất quán đó — vì chúng không nằm trong prompt, chúng không bị ảnh hưởng bởi context pressure.

Lifecycle Hooks là cái có impact thực tế lớn nhất với mình và cũng là cái mình hiểu sai lâu nhất. Mình hay viết instruction "sau mỗi lần edit file, chạy formatter." Model nghe lời — đôi khi. Dưới context pressure, trong session dài, nó skip. Không phải vì nó "quên" — mà vì khi probabilistic system xử lý nhiều thứ cùng lúc, nó có thể bỏ qua thứ mà trong điều kiện bình thường nó nhớ. Hook là cơ chế deterministic đặt ngoài probabilistic model. Formatter chạy sau mỗi edit không phải vì model nhớ phải chạy — mà vì có code được gọi ở PostToolUse hook, và code đó không quan tâm đến context window.

Chỗ mình vẫn chưa có câu trả lời rõ

Hai câu hỏi mình chưa giải quyết được

Với Dream Consolidation: Làm sao biết consolidation đang hoạt động đúng? Nếu nó prune thứ quan trọng, mình có biết không? Không có metric rõ ràng thì khó đánh giá chất lượng của quá trình đó. Mình chưa tìm được cách evaluate điều này một cách systematic.

Với Fork-Join Parallelism: Pattern đẹp trên lý thuyết — nhưng quyết định "task này có thể chia song song không?" là phần khó nhất, và đó là phần con người phải làm, không phải agent. Bao nhiêu phần trăm real coding tasks thực sự independent hoàn toàn? Trong kinh nghiệm của mình, con số đó ít hơn nhiều so với vẻ ngoài.

Những thứ mình sẽ làm khác từ bây giờ

Đọc hết 12 patterns này, mình không nghĩ "cần implement tất cả ngay." Hầu hết trong số chúng có độ phức tạp implementation cao hơn nhiều so với value mà mình sẽ nhận được ở scale hiện tại. Nhưng có ba thứ cụ thể mình sẽ làm khác ngay hôm nay:

Persistent Instruction File — không có lý do gì không làm. Chi phí gần như bằng không, benefit rõ ràng. Mỗi project từ bây giờ có một CLAUDE.md đi kèm repo.

Lifecycle Hooks cho formatter và linter — đây là invariant behavior quan trọng nhất với user của mình. Formatter phải chạy sau mỗi edit, không có ngoại lệ. Đặt vào hook, bỏ ra khỏi instruction.

Explore trước Act — không phải kiến trúc phức tạp, chỉ cần thay đổi cách mình prompt agent trong giai đoạn đầu của task. Trước khi agent được phép edit bất cứ thứ gì, nó phải report lại codebase map và approach. Đây là thứ mình có thể làm ngay hôm nay mà không cần build gì thêm.

Phần còn lại — Tiered Memory, Dream Consolidation, Fork-Join — sẽ đến khi mình có vấn đề cụ thể mà chúng giải quyết. Pattern là menu, không phải checklist bắt buộc. Điều quan trọng là biết chúng tồn tại, biết tên gọi của chúng, để khi vấn đề xuất hiện mình không phải mò tìm giải pháp từ đầu.

Source code Claude Code sẽ không bị leak mãi. Anthropic sẽ obfuscate lại, hay đổi kiến trúc, hay làm gì đó. Nhưng 12 patterns này không phải sản phẩm của một implementation cụ thể — chúng là giải pháp cho những vấn đề cơ bản của agentic systems. Những vấn đề đó sẽ không biến mất khi Anthropic patch source code của họ.

Pattern không phải implementation. Pattern là tên gọi cho một solution đã được kiểm chứng cho một vấn đề tái diễn. Khi bạn có tên, bạn nhận ra vấn đề nhanh hơn khi nó xuất hiện lần sau.