Bài 8 đã nói về subagent: spawn một session riêng, giao task, nhận kết quả về. One-shot, sạch sẽ. Nhưng có một nhược điểm lớn: sau khi subagent báo cáo xong, nó biến mất. Nếu bạn muốn hỏi thêm, muốn giao thêm task liên quan, muốn hai agent nói chuyện với nhau, bạn phải spawn lại từ đầu, agent mới không có memory của lần trước.

Team mode giải quyết bài toán này. Thay vì agent one-shot, bạn tạo một team với các agent có tên, có thể nhận tin nhắn bất cứ lúc nào trong session, giữ được context xuyên lượt.

Bài này đi vào cơ chế, use case, và những điểm cần lưu ý khi dùng team mode trong thực tế.

Vấn đề của one-shot Agent

Khi bạn gọi Agent({subagent_type: "fullstack-engineer", prompt: "..."}), một session mới được spawn, làm xong task, trả kết quả về main session, và kết thúc. Context của agent đó không còn tồn tại.

Main session
    |
    | Agent({prompt: "viết component X"})
    |
    v
Agent session  <-- sống
    - nhận task
    - làm việc
    - trả kết quả
    - kết thúc   <-- chết

Main session nhận kết quả
    |
    | Agent({prompt: "review component X"})  <-- agent mới, không biết về lần trước
    |
    v
Agent session mới  <-- không có memory của agent viết X

Hai điểm yếu:

  1. Không resume được: nếu task của agent chưa đủ, bạn phải spawn agent mới và truyền lại toàn bộ context.
  2. Không phối hợp được: agent A viết code, agent B cần review. Với one-shot, B không biết A đã làm gì trừ khi bạn copy kết quả của A vào prompt của B thủ công.

Team mode: agent có tên, có thể nhắn tin

Team mode thêm hai khái niệm vào tool loop: TeamCreateSendMessage.

TeamCreate

TeamCreate({ team_name: "my-team" })

Lệnh này khởi tạo một team container. Các agent trong team đều alive khi team còn alive. Team tồn tại trong phạm vi session hiện tại.

Spawn agent trong team

Khi spawn agent vào team, bạn truyền thêm name cho agent đó:

Agent({
  subagent_type: "fullstack-engineer",
  name: "alice",
  team_name: "my-team",
  prompt: "Bạn là alice. Nhiệm vụ của bạn là viết feature X theo spec đã cho.",
})

name là định danh để main session (và agent khác) gửi tin nhắn đến agent đó sau này. Tên nên ngắn, lowercase, không space.

SendMessage

SendMessage({
  to: "alice",
  message: "Cập nhật: yêu cầu thêm pagination cho list, implement luôn trong component X đó."
})

Main session gửi tin nhắn đến agent có tên alice. Agent alice nhận tin nhắn, tiếp tục từ context đang có, không mất đi những gì đã làm.

TeamDelete

TeamDelete({ team_name: "my-team" })

Cleanup khi xong. Giải phóng resource. Tốt practice là luôn delete team sau khi không còn cần.

Lifecycle của agent trong team

TeamCreate("my-team")
    |
    +--- Agent(name: "alice", team_name: "my-team") -- alive
    |         |
    |         | (làm việc)
    |         |
    |    SendMessage(to: "alice", "thêm X")
    |         |
    |         | (tiếp tục từ context cũ)
    |         |
    +--- Agent(name: "bob", team_name: "my-team") -- alive
    |         |
    |    SendMessage(to: "bob", "review code của alice")
    |         |
    |         | (làm việc)
    |
TeamDelete("my-team")
    - alice bị terminate
    - bob bị terminate

Cả alice và bob tồn tại đồng thời trong phạm vi team. Mỗi agent giữ context window riêng, không chia sẻ với nhau trực tiếp. Giao tiếp giữa các agent đi qua main session: main nhận kết quả của alice, main chuyển tiếp cho bob qua SendMessage.

Yêu cầu: env var trong settings.json

Team mode là tính năng thực nghiệm. Phải bật explicit:

{
  "env": {
    "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
  }
}

Thêm vào ~/.claude/settings.json (global) hoặc .claude/settings.json trong project. Không có env var này, TeamCreateSendMessage không được CC nhận ra.

Xem bài 10 về settings.json nếu chưa quen với cấu trúc file.

Use case 1: dev workflow alice viết, bob review

Pattern phổ biến nhất. Hai agent phối hợp theo kiểu writer-reviewer:

TeamCreate({ team_name: "feature-team" })

Agent({
  name: "alice",
  team_name: "feature-team",
  subagent_type: "fullstack-engineer",
  prompt: `Bạn là alice, một engineer. Implement pagination component
cho orders list theo spec: max 10 items/page, URL-based state (?page=N),
có prev/next, có jump to page. TypeScript, Tailwind.`,
})

// alice đang làm việc...
// main session nhận kết quả của alice...

SendMessage({
  to: "bob",
  message: `Review code alice vừa viết trong src/components/Pagination.tsx.
Kiểm tra: type safety, edge cases (page 0, page quá lớn), 
accessibility (aria labels), và có bất kỳ performance issue nào không.`,
})

TeamDelete({ team_name: "feature-team" })

Điểm khác biệt so với spawn hai one-shot agent riêng: bob có thể nhận thêm context từ main session sau khi alice đã review, mà không cần spawn agent review mới từ đầu.

// Nếu bob tìm thấy vấn đề, main session nhận report
// Sau đó SendMessage cho alice để fix:

SendMessage({
  to: "alice",
  message: "Bob phát hiện thiếu aria-label trên nút prev/next. Fix luôn đi.",
})

// alice fix, không cần spawn lại, vẫn giữ toàn bộ context về component đó

Use case 2: long-running domain specialist

Khi một phần của task cần expertise sâu trong một domain, bạn muốn giữ một agent “chuyên gia” alive để hỏi nhiều lượt:

TeamCreate({ team_name: "migration-session" })

Agent({
  name: "db-expert",
  team_name: "migration-session",
  subagent_type: "fullstack-engineer",
  prompt: `Bạn là db-expert, chuyên về database migration PostgreSQL.
Bạn sẽ nhận các câu hỏi về kế hoạch migrate schema từ v1 sang v2.
Cung cấp analysis cụ thể, ước tính downtime, rollback strategy.`,
})

SendMessage({
  to: "db-expert",
  message: "Đây là schema hiện tại: [schema v1]. Đây là schema mới: [schema v2]. Đánh giá risk?",
})

// Sau khi nhận đánh giá...
SendMessage({
  to: "db-expert",
  message: "Nếu rollback cần xảy ra sau bước 3, strategy cụ thể là gì?",
})

// Nhiều lượt hỏi, db-expert nhớ hết context về schema đã nói ở trên

Với one-shot agent, mỗi câu hỏi là một session mới. Bạn phải paste lại schema mỗi lần. Với team agent, db-expert giữ context về schema, về risk đã phân tích, về những gì đã thảo luận. Tiết kiệm token đáng kể cho các cuộc conversation nhiều lượt.

Use case 3: human-in-the-loop qua main session

Agent không thể hỏi user trực tiếp. Nhưng agent có thể gửi câu hỏi về main session, và main session forward cho user:

user <--> main session <--> agent
// Agent báo cáo về main:
// "Tôi cần biết: môi trường staging hay production?"

// Main session nhận, thấy câu hỏi, hỏi user
// User trả lời: "staging"

SendMessage({
  to: "alice",
  message: "Deploy target là staging, không phải production.",
})

Pattern này giữ user trong vòng lặp quyết định mà không làm gián đoạn luồng công việc của agent. Alice không cần biết user ở đâu, nó chỉ cần nhận thông tin từ main session.

Khác one-shot Agent ở đây

ĐiểmOne-shot AgentTeam agent
LifetimeKết thúc khi task xongAlive khi team alive
ResumableKhông, phải spawn mớiCó, qua SendMessage
Context xuyên turnKhông
Phối hợp với agent khácThủ công qua promptQua main session làm relay
OverheadThấpCao hơn (team container)
Phù hợp khiTask đơn lẻ, rõ scopeCollaboration, multi-turn, resume

One-shot agent vẫn là lựa chọn tốt khi task rõ ràng, single-pass. Team mode thêm complexity, thêm resource. Đừng tạo team cho task mà một lần spawn là đủ.

Anti-pattern: team cho task one-shot

// ANTI-PATTERN
TeamCreate({ team_name: "quick-task" })
Agent({
  name: "worker",
  team_name: "quick-task",
  prompt: "Đổi màu button từ blue sang green trong file Button.tsx.",
})
// worker làm xong, xong luôn, không cần resume
TeamDelete({ team_name: "quick-task" })

Đây là overhead không cần thiết. Team container, agent có tên, lifecycle management, tất cả chỉ để làm một task một lần. Dùng one-shot Agent call là đủ:

// ĐÚNG
Agent({
  subagent_type: "fullstack-engineer",
  prompt: "Đổi màu button từ blue sang green trong file Button.tsx.",
})

Nguyên tắc: chỉ dùng team khi bạn thực sự cần resume, cần multi-turn conversation với agent, hoặc cần agent A và B trao đổi qua nhiều lượt.

Pitfall: context window của team agent vẫn có giới hạn

Team agent không có bộ nhớ vô hạn. Mỗi agent trong team có context window riêng, finite. Khi bạn SendMessage nhiều lượt, conversation tích lũy trong context window của agent đó. Khi đủ dài, compaction xảy ra.

Sau compaction, agent có thể không còn nhớ chính xác các chi tiết từ đầu conversation. Đây là hành vi bình thường và không thể tránh, giống như main session bị compaction khi conversation dài (xem bài 5).

Implication thực tế: với long-running specialist agent, định kỳ kiểm tra xem agent còn nhớ đúng context không. Nếu cần, truyền lại context key khi SendMessage: “Nhắc lại: schema v2 là […]. Dựa trên đó, câu hỏi tiếp theo là…”

Cấu hình nhanh để thử

Bật team mode:

// ~/.claude/settings.json
{
  "env": {
    "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
  }
}

Restart Claude Code session sau khi sửa settings.json để env var có hiệu lực.

Kiểm tra bằng cách gọi TeamCreate trong một session. Nếu không báo lỗi tool unknown, team mode đã active.

Tóm tắt và bài tiếp theo

  • One-shot Agent call spawn session mới, làm task, kết thúc. Không resume được.
  • Team mode thêm TeamCreate + agent có name + SendMessage + TeamDelete. Agent trong team alive xuyên nhiều lượt SendMessage.
  • Yêu cầu CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 trong settings.json.
  • Use case tốt: writer-reviewer collaboration, long-running domain specialist, human-in-the-loop relay.
  • Anti-pattern: tạo team cho task chỉ cần spawn một lần. Overhead so với one-shot.
  • Pitfall: context window của team agent vẫn finite, compaction vẫn xảy ra khi conversation dài.

Bài 19 sẽ đi vào các pattern phối hợp nhiều agent: làm thế nào để slice task theo file scope để tránh race condition, cách integrate kết quả từ nhiều agent về một branch, và khi nào nên chọn parallel foreground, background, hay team.

Liên quan:

  • Bài how-to standalone Cách start session trong folder cụ thể từ claude agents giải thích cách FleetView dispatch session với cwd cụ thể, hữu ích khi muốn pre-position team members ở thư mục khác nhau hoặc switch nhanh giữa nhiều project.
  • Skill nf-agents là wrapper production-grade cho TeamCreate đề cập ở bài này: pre-flight check (env var, split-pane backend), templated standby/tasks brief, cooperative shutdown protocol. Đọc nếu muốn dùng team mode an toàn không phải nhớ checklist mỗi lần.

Bài thuộc series Claude Code từ zero. Series plan tại bài giới thiệu.