Bối cảnh: Lúc 2 giờ sáng và Claude Code bắt đầu “lẫn lộn”
Hôm đó mình đang refactor một codebase Python khá lớn — khoảng 40 file, mix giữa FastAPI, Celery worker và một mớ business logic. Mình nhờ Claude Code làm một tác vụ tổng hợp: vừa đọc toàn bộ schema, vừa viết unit test, vừa cập nhật docs, vừa check circular import.
Kết quả? Claude bắt đầu hallucinate tên hàm. Nó đề xuất test cho một function không tồn tại. Docs thì copy-paste sai từ file khác. Context window đã đầy — và model bắt đầu “quên” những gì nó đọc trước đó.
Đó là lúc mình tìm hiểu về sub-agents. Tính năng này cho phép Claude Code giao việc xuống các agent con chuyên biệt, mỗi agent xử lý một nhiệm vụ cụ thể với context riêng — không bị nhiễu bởi thông tin của task khác.
Tại sao cần sub-agents thay vì chạy một agent duy nhất?
LLM có một giới hạn rất thực tế: context window. Nhồi quá nhiều thứ vào một agent — đọc 40 file, viết test, cập nhật docs, check import — và nó sẽ bắt đầu nhầm lẫn ở đâu đó giữa chừng. Không phải model kém, mà là sai cách dùng.
Sub-agents giải quyết vấn đề này theo cách khá thực dụng:
- Isolation: Mỗi sub-agent có context riêng, không bị ô nhiễm bởi task khác
- Song song hóa: Nhiều sub-agent chạy đồng thời, giảm thời gian tổng thể
- Chuyên biệt hóa: Agent A chỉ đọc code, agent B chỉ viết test, agent C chỉ viết docs — mỗi con làm đúng một việc, làm tốt hơn
- Fault isolation: Một sub-agent fail không kéo cả pipeline sập
Trên thực tế, mình dùng pattern này cho codebase ~40 file và thấy tỉ lệ hallucination giảm rõ rệt — từ chỗ phải sửa 3-4 lỗi sai mỗi lần chạy xuống còn gần như không có. Thời gian tổng thể cũng nhanh hơn khoảng 30-40% nhờ chạy song song.
Cài đặt Claude Code và điều kiện để dùng sub-agents
Sub-agents là tính năng built-in của Claude Code, không cần cài thêm gì. Chỉ cần đảm bảo một số điều kiện:
Yêu cầu tối thiểu
- Claude Code phiên bản mới nhất (cài qua npm)
- Tài khoản Claude với plan Pro hoặc Max (sub-agents tiêu tốn nhiều token hơn)
- Node.js 18+
# Cài hoặc update Claude Code
npm install -g @anthropic-ai/claude-code
# Kiểm tra version
claude --version
# Khởi động trong project directory
cd /path/to/your/project
claude
Cấu trúc CLAUDE.md — nền tảng để sub-agents hiểu nhau
Đây là điểm nhiều người hay bỏ qua. Khi parent agent spawn ra sub-agent, sub-agent đó cũng đọc file CLAUDE.md trong project — giống như một nhân viên mới vào việc, đọc onboarding doc trước khi làm bất cứ thứ gì. File này phải đủ rõ để agent hiểu project ngay lập tức, không cần hỏi lại.
# CLAUDE.md
## Project structure
- src/api/ — FastAPI routers
- src/workers/ — Celery tasks
- src/models/ — SQLAlchemy models
- tests/ — pytest test suite
## Rules
- Always use absolute imports
- Test files mirror src/ structure: src/api/users.py → tests/api/test_users.py
- Never modify migration files directly
Càng rõ ràng, sub-agent càng ít hỏi lại và ít sai. Mình thường dành 15 phút viết kỹ CLAUDE.md trước khi chạy bất kỳ tác vụ phức tạp nào.
Cấu hình chi tiết: Cách giao việc cho sub-agents
Cách 1: Claude Code tự spawn sub-agent (tự động)
Với tác vụ đủ phức tạp, Claude Code sẽ tự nhận ra và spawn sub-agents mà không cần bạn ra lệnh gì thêm. Output trong terminal sẽ trông như thế này:
# Claude Code tự phân chia task
> Refactor authentication module and write tests for all edge cases
# Output trong terminal:
[Agent] Spawning sub-agent: code-explorer (reading auth module)
[Agent] Spawning sub-agent: test-writer (writing unit tests)
[Agent] Running in parallel...
[code-explorer] Read src/auth/jwt.py, src/auth/oauth.py
[test-writer] Writing tests/auth/test_jwt.py
Cách 2: Dùng Agent tool trong custom workflow (SDK)
Nếu bạn đang xây dựng workflow tự động với Claude Agent SDK, đây là cách gọi sub-agent programmatically:
import anthropic
client = anthropic.Anthropic()
# Parent agent nhận task lớn
def run_parent_agent(task: str):
response = client.messages.create(
model="claude-opus-4-6",
max_tokens=4096,
tools=[
{
"name": "spawn_subagent",
"description": "Spawn a specialized sub-agent for a specific subtask",
"input_schema": {
"type": "object",
"properties": {
"task": {"type": "string"},
"context": {"type": "string"}
},
"required": ["task"]
}
}
],
messages=[{"role": "user", "content": task}]
)
return response
Cách 3: Chạy song song nhiều agent độc lập từ CLI
Pattern này mình dùng nhiều nhất khi cần xử lý nhiều file song song. Ý tưởng đơn giản: fork ra nhiều process, để shell tự quản lý song song, rồi wait:
#!/bin/bash
# Agent 1: Review security issues
claude --print "Review src/api/ for SQL injection and XSS vulnerabilities. Output findings as JSON." \
> security_report.json &
PID1=$!
# Agent 2: Generate API docs
claude --print "Read all FastAPI routers in src/api/ and generate OpenAPI-compatible docs." \
> api_docs.md &
PID2=$!
# Agent 3: Find dead code
claude --print "Find unused functions and imports in src/. List file:line for each." \
> dead_code.txt &
PID3=$!
# Chờ tất cả hoàn thành
wait $PID1 $PID2 $PID3
echo "All agents done. Check security_report.json, api_docs.md, dead_code.txt"
Truyền context giữa parent và sub-agent
Vấn đề thực tế hay gặp: sub-agent cần biết output của agent trước để làm bước tiếp theo. Cách đơn giản nhất là ghi ra file trung gian — agent sau đọc file tóm tắt thay vì phải crawl lại toàn bộ codebase:
# Bước 1: Agent phân tích schema
claude --print "Read all SQLAlchemy models in src/models/, output a JSON summary of each table: name, columns, relationships." \
> schema_summary.json
# Bước 2: Agent viết migration dựa trên summary
claude --print "$(cat schema_summary.json)
Based on the schema above, write an Alembic migration to add 'updated_at' timestamp to all tables that don't have it. Output only the Python migration file content." \
> migrations/add_updated_at.py
echo "Migration file ready: migrations/add_updated_at.py"
File schema_summary.json ở đây đóng vai trò “bộ nhớ chung” — nhỏ gọn, rõ ràng, agent sau không cần đọc lại 40 file gốc.
Kiểm tra & Monitoring: Biết khi nào sub-agent đang hoạt động đúng
Xem log của từng sub-agent
Claude Code ghi log chi tiết về mọi tool call. Bật verbose mode để theo dõi từng bước:
# Chạy với verbose để thấy mọi tool call
claude --verbose
# Hoặc set env var
export CLAUDE_LOG_LEVEL=debug
claude "refactor auth module"
Trong output verbose, bạn thấy rõ mỗi sub-agent đọc file nào, gọi tool gì, trả về kết quả ra sao. Khi sub-agent làm sai, đây là nơi đầu tiên cần nhìn vào.
Luôn thêm một agent review độc lập ở cuối
Bước này hay bị bỏ qua nhưng thực sự quan trọng. Sau khi các sub-agent chạy xong, spawn thêm một agent review — agent này không biết gì về quá trình trước, chỉ đọc output và đánh giá:
claude --print "
Review the following files that were just auto-generated:
- tests/auth/test_jwt.py
- tests/auth/test_oauth.py
Check:
1. Do tests actually cover edge cases or just happy paths?
2. Are there any tests that test implementation details instead of behavior?
3. Will these tests break if we refactor internals?
Output a score 1-10 and specific issues found."
Các dấu hiệu cho thấy sub-agent đang gặp vấn đề
- Hallucinate function name: Agent viết test cho hàm không tồn tại → cần cung cấp schema rõ hơn trong prompt
- Timeout hoặc chạy quá lâu: Task scope quá lớn, cần chia nhỏ hơn
- Output trống hoặc “I cannot”: Agent không có đủ permission đọc file → kiểm tra working directory
- Kết quả mâu thuẫn giữa các agent: Hai agent song song đọc file đang bị agent khác modify → dùng read-only locks hoặc chạy tuần tự
Bốn rule mình học được sau vài lần cháy
- Một sub-agent, một mục tiêu: Đừng để một agent vừa đọc vừa viết vừa validate — tách ra ba agent riêng
- Định nghĩa output format rõ ràng: Yêu cầu agent trả về JSON hoặc markdown cụ thể, không phải text tự do
- Giới hạn scope bằng path:
"Only look at files in src/api/, do not touch other directories"giúp agent tập trung và nhanh hơn - Idempotent operations: Thiết kế task sao cho chạy lại nhiều lần không gây hại — tránh các task như “delete all temp files” trong sub-agent tự động
Sub-agents không giải quyết được mọi thứ. Với task đơn giản, một agent là đủ — thêm sub-agent chỉ tốn thêm token mà không được gì. Nhưng khi codebase lớn dần, khi một tác vụ đòi hỏi nhiều bước độc lập, hoặc khi bạn bắt đầu thấy agent “quên” thông tin ở cuối context — đó là lúc chia nhỏ ra. Thay vì một agent đa năng dễ bị overwhelm, bạn có một nhóm nhỏ mỗi con chuyên một việc, làm đúng việc đó.

