⚡ KHÓA HỌC HARNESS ENGINEERING & AI CODING AGENT (CLAUDE CODE) BÀI 2 / 4
Harness Engineering Series • Bài 2

Khóa Học Harness Engineering (Phần 2): Quản Trị Ngữ Cảnh, Cô Lập Subagents & Nạp Kỹ Năng Động (Skills)

Trong Phần 1, chúng ta đã nắm vững nguyên tắc cốt lõi: Model là người lái, Harness là cỗ xe và vòng lặp Agent Loop nguyên bản. Tuy nhiên, khi một tác nhân AI bắt đầu làm việc trên một dự án thực tế với hàng nghìn dòng code, nó lập tức đâm sầm vào chướng ngại vật lớn nhất của LLM: Sự Phân Tâm Ngữ Cảnh (Attention Dilution) và Tràn Cửa Sổ Ngữ Cảnh (Context Window Bloat).

Nếu bạn liên tục nhồi hàng chục kết quả lệnh shell, hàng nghìn dòng log và toàn bộ tài liệu API vào cùng một danh sách messages[], mô hình sẽ bắt đầu "quên" mục tiêu ban đầu, suy luận lộn xộn và ảo giác cú pháp. Bài viết này sẽ mổ xẻ 3 vũ khí kỹ thuật tối thượng của Claude Code để giải quyết triệt để bài toán này: Cô lập tác vụ con với Subagents, Nạp kỹ năng động theo chuẩn SKILL.md và Cắt tỉa ngữ cảnh Context Compaction.

1. Hiểm Họa Của "Attention Dilution" & Context Bloat

Mặc dù các mô hình ngôn ngữ lớn hiện nay hỗ trợ cửa sổ ngữ cảnh lên tới 200.000 hoặc 1.000.000 token, nghiên cứu của Anthropic (2025–2026) chỉ ra rằng hiệu quả giải quyết vấn đề của mô hình suy giảm mạnh khi ngữ cảnh bị ô nhiễm:

Căn Bệnh 1: Ô Nhiễm Lịch Sử
Noise-to-Signal Collapse
Các kết quả dump dữ liệu lớn (như lệnh grep tìm thấy 500 dòng hoặc stack trace dài) biến ngữ cảnh thành một đống rác nhiễu, đẩy chỉ dẫn quan trọng của User ra xa.
Căn Bệnh 2: Phân Tâm Cơ Chế Chú Ý
Attention Dilution
Cơ chế tự chú ý (Self-Attention) của Transformer phải chia sẻ trọng số cho quá nhiều token không liên quan, dẫn đến việc bỏ sót các ràng buộc nghiệp vụ then chốt.
Căn Bệnh 3: Bùng Nổ Chi Phí & Độ Trễ
Latency & Token Cost
Mỗi lượt gọi LLM sau đó phải gửi lại toàn bộ lịch sử khổng lồ, khiến thời gian phản hồi tăng từ 2 giây lên 30 giây và tiêu tốn ngân sách API gấp 10-20 lần.

2. Subagents: Cơ Chế Khởi Tạo Ngữ Cảnh Sạch (Context Isolation)

Đột phá kiến trúc lớn nhất của Claude Code để xử lý công việc nặng là Subagents. Thay vì để Agent chính tự mình đọc 20 file và chạy 10 script kiểm thử, Agent chính ủy quyền tác vụ đó cho một Subagent chuyên biệt:

3. Dynamic Skill Loading: Chuẩn Hóa SKILL.md On-Demand

Trong các framework cũ, lập trình viên thường nhồi toàn bộ tài liệu dự án, quy ước code và hướng dẫn công cụ vào System Prompt ngay từ đầu. Điều này làm lãng phí 20.000–30.000 token vô ích trong khi Agent có thể không cần dùng tới.

Claude Code tiên phong phương pháp Dynamic Skill Loading (Nạp kỹ năng động theo nhu cầu):

Bước 1: Khai Báo Danh Mục (Catalog)
Minimal Metadata
Hệ thống chỉ nạp một bảng tóm tắt cực ngắn (Tên kỹ năng + Mô tả 1 dòng) vào System Prompt ban đầu (tiêu tốn chưa tới 200 token).
Bước 2: Kích Hoạt Khi Cần Thiết
On-Demand Injection
Chỉ khi Agent nhận diện thấy bài toán đòi hỏi kỹ năng chuyên sâu (ví dụ: tối ưu SQL hoặc viết test Playwright), Agent mới gọi tool nạp file SKILL.md tương ứng.
Bước 3: Định Dạng Chuẩn SKILL.md
YAML Frontmatter
File SKILL.md chứa metadata ở phần đầu (name, description, required tools) và nội dung Markdown chi tiết gồm hướng dẫn từng bước và code mẫu.
--- name: playwright-testing description: Hướng dẫn viết và chạy kiểm thử giao diện E2E bằng Playwright Chromium tools: [bash, view_file, write_to_file] --- # Playwright Testing Best Practices 1. Luôn sử dụng headless mode khi chạy trong CI/CD. 2. Đặt timeout mặc định 10.000ms cho các thao tác mạng. 3. Chụp ảnh màn hình khi phát hiện lỗi thất bại để debug trực quan.

4. Context Compaction & Quản Trị Bộ Nhớ Dài Hạn (Memory)

Khi phiên làm việc kéo dài hàng giờ với hàng trăm câu hỏi, Claude Code áp dụng kỹ thuật Context Compaction (Cắt tỉa & nén ngữ cảnh):

5. Sơ Đồ Kiến Trúc Phân Lập Ngữ Cảnh & Nạp Kỹ Năng Động

Sơ đồ sau đây mô tả rõ cơ chế phân tách không gian bộ nhớ giữa Orchestrator chính, các Subagents độc lập và kho kỹ năng SKILL.md:

CƠ CHẾ CÔ LẬP SUBAGENTS & NẠP KỸ NĂNG ON-DEMAND Triệt tiêu Attention Dilution bằng Fresh Context và nạp tri thức chuyên sâu khi có yêu cầu ORCHESTRATOR CHÍNH Context Window Tinh Gọn Chỉ giữ mục tiêu cốt lõi & plan Catalog Kỹ Năng (200 tokens) • research-codebase • playwright-testing Ủy Quyền Tác Vụ Con spawn_subagent(task, toolset) Không bị ô nhiễm bởi logs rác Spawn SUBAGENT RIÊNG BIỆT Fresh Messages[] Sạch Khởi tạo riêng · Không mang lịch sử cũ Vòng Lặp Chuyên Biệt: • Đọc 15 file mã nguồn • Chạy 5 script kiểm thử E2E Thu Gọn Kết Quả Trả về 1 đoạn kết luận · Hủy rác Tiết kiệm 80-90% token cho Agent cha DYNAMIC SKILL LOADER skills/database/ SKILL.md · Tối ưu SQL Chỉ đọc khi đụng Database skills/security/ SKILL.md · Quét lỗ hổng Chỉ đọc khi audit bảo mật On-demand Injection Đưa vào ngữ cảnh đúng lúc Quy tắc nạp động thông minh Inject

6. Triển Khai Code Python: SkillLoader & Subagent Spawning

Dưới đây là mã nguồn Python triển khai cơ chế nạp kỹ năng động từ file SKILL.md và khởi tạo Subagent độc lập:

import os import yaml class SkillLoader: """ Bộ nạp kỹ năng động theo chuẩn SKILL.md của Anthropic Claude Code """ def __init__(self, skills_dir: str = ".claude/skills"): self.skills_dir = skills_dir self.catalog = {} self.index_skills() def index_skills(self): """Quét danh mục metadata cực nhẹ (chỉ đọc Frontmatter)""" if not os.path.exists(self.skills_dir): return for root, _, files in os.walk(self.skills_dir): for file in files: if file.lower() == "skill.md": path = os.path.join(root, file) meta, _ = self.parse_skill_file(path) if meta and "name" in meta: self.catalog[meta["name"]] = { "description": meta.get("description", ""), "path": path } def parse_skill_file(self, file_path: str): """Bóc tách YAML frontmatter và phần thân Markdown""" with open(file_path, "r", encoding="utf-8") as f: content = f.read() if content.startswith("---"): parts = content.split("---", 2) if len(parts) >= 3: meta = yaml.safe_load(parts[1]) body = parts[2].strip() return meta, body return {}, content def get_catalog_summary(self) -> str: """Tạo bản tóm tắt danh mục kỹ năng để nạp vào System Prompt ban đầu""" lines = ["KHO KỸ NĂNG KHẢ DỤNG (Gọi tool load_skill để nạp khi cần):"] for name, info in self.catalog.items(): lines.append(f"- {name}: {info['description']}") return "\n".join(lines) def load_skill_content(self, skill_name: str) -> str: """Nạp nội dung chi tiết của kỹ năng vào ngữ cảnh khi Agent yêu cầu""" if skill_name in self.catalog: _, body = self.parse_skill_file(self.catalog[skill_name]["path"]) return body return f"Lỗi: Không tìm thấy kỹ năng '{skill_name}'" def spawn_subagent(llm_client, task_prompt: str, available_tools: list) -> str: """ Khởi tạo Subagent với danh sách tin nhắn hoàn toàn mới (Fresh messages list) """ subagent_messages = [ {"role": "system", "content": "Bạn là một Subagent chuyên trách. Hãy giải quyết tác vụ cụ thể và trả về kết quả tóm tắt súc tích nhất."}, {"role": "user", "content": task_prompt} ] # Chạy vòng lặp nội tại của Subagent while True: resp = llm_client.chat_completion(messages=subagent_messages, tools=available_tools) subagent_messages.append(resp["message"]) tool_calls = resp["message"].get("tool_calls", []) if not tool_calls: # Trả về kết quả cuối cùng cho Agent cha, vứt bỏ toàn bộ lịch sử trung gian return resp["message"]["content"] for tc in tool_calls: # Thực thi công cụ và nạp kết quả vào subagent_messages... pass
💡
TỔNG KẾT BÀI HỌC: Quản trị ngữ cảnh là kỹ năng sống còn của kỹ sư Harness. Bằng cách kết hợp Subagents cô lập và Skill Loading on-demand, bạn giải phóng mô hình khỏi gánh nặng token rác. Trong Phần 3 tiếp theo, chúng ta sẽ bước lên cấp độ quy trình phát triển phần mềm chuẩn mực (Agentic SDLC): Chuyển dịch từ "Vibe Coding" sang "Agentic Engineering", áp dụng mô hình Command → Agent → Skill và kỹ thuật cô lập nhánh lập trình song song bằng Git Worktrees!
⚡

Biên Soạn: Học Viện Giao Dịch — Hàng Hóa Plus

Chuỗi bài giảng Harness Engineering được phát triển dựa trên các nghiên cứu chuyên sâu về kiến trúc tác nhân lập trình AI của Anthropic Claude Code và shareAI-lab.