Claude Code: Cách các session nhắn tin cho nhau
Tìm hiểu ListAgents và SendMessage trong Claude Code, yêu cầu v2.1.224+, khi nào session thứ hai hữu ích và vì sao tin nhắn bị giữ trên cùng VPS.
Ý nghĩa của việc các session Claude Code nhắn tin cho nhau
Hai session Claude Code có thể nhắn tin cho nhau khi chạy trên cùng một máy và cùng một user của hệ điều hành. Một tin nhắn là một đoạn văn bản thuần túy do một Claude viết cho Claude khác. Tin nhắn không chứa lịch sử hội thoại hoặc file. Claude tìm session còn lại bằng tool ListAgents và gửi văn bản bằng SendMessage, nên bạn không bao giờ gọi trực tiếp hai tool này. Bạn chỉ cần nói session kia cần biết gì, rồi Claude tự viết tin nhắn.
Tính năng này được gọi là nhắn tin giữa các session. Tính đến tháng 8 năm 2026, tính năng này yêu cầu Claude Code v2.1.224 trở lên và chạy trên macOS và Linux, bao gồm Linux bên trong WSL 2. Tính năng này không có hỗ trợ Windows native và không khả dụng trên Amazon Bedrock, Claude Platform on AWS, Google Cloud's Agent Platform hoặc Microsoft Foundry. Khi session đáp ứng các yêu cầu đó, tính năng nhắn tin đã được bật sẵn và không cần cấu hình gì thêm. Hành vi được mô tả bên dưới dựa trên tài liệu Anthropic về nhắn tin giữa các session.
VPS là nơi tính năng này thực sự hữu ích, vì session trên VPS có thể chạy đủ lâu để bạn cần liên lạc với chúng. Trên laptop, bạn thường đóng nắp máy. Trên server chạy trong tmux, session khởi động từ thứ Hai vẫn có thể còn chạy vào thứ Năm và vẫn giữ context của một repository. Khi có hai session như vậy, cách chúng trao đổi không còn là vấn đề lý thuyết. Nếu chưa thiết lập, hãy bắt đầu với chạy Claude Code trên VPS bên trong tmux, phần này trình bày cách quản lý session mà hướng dẫn này giả định.
Khi một session thứ hai đáng với số token bỏ ra
Hãy bắt đầu từ chi phí. Mỗi session là một instance Claude riêng với context window riêng, vì vậy 2 session có chi phí gần gấp đôi 1 session trong cùng một khoảng thời gian. Một message được gửi cũng được tính vào mức sử dụng giống hệt prompt bạn tự nhập. Việc phối hợp không miễn phí, và những công việc thực chất chỉ là một chuỗi bước sẽ chậm hơn, tốn kém hơn khi bạn chia chúng qua nhiều session.
Các trường hợp session thứ hai mang lại hiệu quả đều có cùng một đặc điểm. 2 phần việc chạy đồng thời mà không phải chờ nhau, và trong quá trình thực hiện, một phần biết được thông tin mà phần còn lại cần.
- Một session phát hiện breaking change trong khi session kia đang xây dựng dựa trên code đã bị thay đổi. Claude tóm tắt thay đổi và gửi cho session kia, thay vì để bạn nhập lại trong terminal khác.
- 2 session làm việc trên cùng một repository trong các git worktree riêng, và một session cần biết thay đổi nào đã được tích hợp.
- Một migration hoặc test run kéo dài gửi kết quả về session mà bạn đang theo dõi.
- Một session builder và một session reviewer, trong đó reviewer đọc sản phẩm do builder tạo ra rồi gửi lại các phát hiện.
Khi công việc có tính tuần tự, hoặc khi cả 2 session sẽ chỉnh sửa cùng một file, hãy dùng 1 session. Khi bạn muốn một nhóm được Claude tạo và giám sát trong cùng một task, đó là agent teams, một tính năng riêng vẫn đang ở giai đoạn experimental. Khi bạn chỉ muốn mở cùng cuộc trò chuyện trong một terminal khác, hãy resume session thay vì tạo session mới. Cross-session messaging dành cho các session độc lập mà bạn tự khởi động và điều khiển.
Kiểm tra tính năng trước khi thiết kế dựa trên nó
Trước hết, kiểm tra phiên bản:
claude --versionSo sánh số phiên bản với 2.1.224. Sau đó, trong một session, nhập /list-agents; lệnh này cũng được gọi bằng /peers. Lệnh in ra mọi agent mà session này có thể truy cập, cùng với tên mà từng agent phản hồi. Nếu lệnh hoàn toàn không được nhận diện, session này không hỗ trợ nhắn tin giữa các session và không settings file nào có thể bật tính năng đó. Nhập /status rồi tìm dòng Peer address: dòng này chứa địa chỉ inbox của chính session hiện tại, có tiền tố uds:.
Người dùng VPS đặc biệt dễ gặp một vấn đề. Nhắn tin giữa các session phụ thuộc vào việc đánh giá feature flag. Một số biến privacy sẽ tắt việc đánh giá này, khiến tính năng giữ trạng thái mặc định là tắt. DO_NOT_TRACK, DISABLE_TELEMETRY, CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC và DISABLE_GROWTHBOOK đều có tác dụng này. Nhiều người harden server mới bằng cách thêm các biến đó vào ~/.bashrc, rồi thắc mắc vì sao /list-agents không tồn tại. Các giá trị tương tự cũng có thể đến từ map env trong settings file hoặc từ managed settings, vì vậy hãy kiểm tra shell trước.
env | grep -E 'DO_NOT_TRACK|DISABLE_TELEMETRY|DISABLE_GROWTHBOOK|NONESSENTIAL'Bỏ giá trị biến nào đang được in ra. Với DISABLE_TELEMETRY và CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, mọi giá trị không rỗng đều bật hành vi này, kể cả chuỗi 0, vì vậy DISABLE_TELEMETRY=0 không có tác dụng như vẻ ngoài của nó. Để tắt tính năng, hãy unset biến hoặc đặt biến thành chuỗi rỗng.
Đặt tên cho session, nếu không Claude không thể định tuyến message đến đúng session
Claude định tuyến message đến một session bằng tên của session đó. Đặt tên khi bạn khởi động session:
claude --name builder-apiBạn cũng có thể đặt tên bằng /rename trong một session đang chạy. Nếu không đặt tên, Claude Code lấy tên từ tên thư mục của working directory, chẳng hạn như myapp-3f. Cách này phù hợp với một session, nhưng sẽ khó phân biệt khi có bốn session; hai session cũng có thể nhận cùng một tên. Output của /list-agents hiển thị working directory của từng session local, giúp phân biệt các session trùng tên. Danh sách của Claude cũng thêm một mã định danh ngắn vào địa chỉ khi tên bị trùng. Tự đặt tên sẽ nhanh hơn việc phải đọc các mã định danh.
Một bố cục tmux gồm hai session có thể tái tạo
Đây là một session builder và một session reviewer trên cùng một repository. Reviewer làm việc trong một git worktree riêng, nên hai session không bao giờ ghi vào cùng một file. git worktree add cùng với HEAD tạo một checkout detached. Đây là lựa chọn phù hợp cho session chỉ đọc thay vì commit. Vì hai session đảm nhiệm các công việc khác nhau, bạn nên đặt cho reviewer một kiểu đầu ra riêng. Kiểu này thay đổi system prompt của session đó và được áp dụng trong mọi lượt, thay vì mất tác dụng như một instruction bạn chỉ nhập một lần.
cd ~/src/api
git worktree add ../api-review HEAD
tmux new-session -d -s agents -n builder -c ~/src/api
tmux new-window -t agents -n reviewer -c ~/src/api-review
tmux send-keys -t agents:builder 'claude --name builder-api' C-m
tmux send-keys -t agents:reviewer 'claude --name reviewer-api' C-m
tmux attach -t agentsCtrl+b rồi w liệt kê các window theo tên để bạn chọn một window. Trong window builder, chạy /list-agents. Bạn sẽ thấy reviewer-api cùng thư mục làm việc là ~/src/api-review. Nếu không thấy, session reviewer chưa khởi động xong hoặc một trong hai vấn đề ở phần tiếp theo đang xảy ra. Sau đó, bàn giao công việc bằng ngôn ngữ tự nhiên:
Tell reviewer-api which files I changed for the rate limiter and what to look at first.Claude viết phần tóm tắt và gửi đi. Bạn không tự viết nội dung message, và nội dung Claude gửi sẽ thay đổi. Trong window reviewer, message xuất hiện trong cuộc hội thoại cùng tên người gửi. Nếu session đó đang idle, Claude bắt đầu ngay một lượt mới trên session đó. Nếu session đang trong một lượt, message sẽ chờ đến giữa các lần gọi tool, nên command đang chạy không bị gián đoạn. Sau khi Claude đọc message, message được thu gọn thành một dòng Message from mà Ctrl+O sẽ mở rộng. Cặp session này hoạt động hiệu quả hơn khi builder giữ các thay đổi ở phạm vi nhỏ, vì diff hẹp tạo ra phần bàn giao ngắn hơn và một lượt review mà session còn lại có thể hoàn tất trong một lượt. Đây là thói quen mà kỹ năng lazy senior dev được tạo ra để duy trì.
Ai có thể nhìn thấy ai trên cùng một VPS
Việc chuyển tin giữa các session trên cùng một máy không bao giờ đi qua server Anthropic. Mỗi session ghi các file đăng ký vào disk và bind socket inbox riêng. Claude Code đọc các file đó để tìm các session khác của bạn. Điều này dẫn đến 2 hệ quả, và cả 2 đều đáng lưu ý trên server.
Socket chỉ cho phép user hệ điều hành tương ứng truy cập. Một session bạn khởi động dưới dạng root và một session bạn khởi động dưới dạng deploy không thể nhìn thấy nhau, dù chạy cạnh nhau trong cùng một tmux server, vì session của user này không thể truy cập socket của user kia. Hãy chạy cả 2 session dưới cùng một user.
Container có filesystem riêng. Một session bên trong Docker và một session trên host không thể truy cập lẫn nhau, vì chúng không đọc cùng các file đăng ký. 2 session bên trong cùng một container có thể nhắn tin cho nhau bình thường. Nếu bạn giữ các agent trong container để cô lập chúng, như trong chạy coding agent trong một VM tạm thời, hãy dự kiến messaging sẽ hoạt động bên trong container nhưng không hoạt động qua ranh giới container.
Các session của bạn trên máy khác và trên web chỉ xuất hiện trong danh sách khi Remote Control đang kết nối, và được gắn nhãn tương ứng. Claude tại đây chỉ có thể trả lời message đến từ một trong các session đó. Nó không thể tự bắt đầu trao đổi.
Tại sao message của bạn không bao giờ được gửi đến
Lý do thường gặp không liên quan đến network. Session nhận quyết định phải xử lý message như thế nào, và quyết định đó là không gửi đến. Mỗi message đến sẽ kết thúc theo một trong ba trạng thái: đã gửi đến, được giữ lại (tạm để đó, chưa gửi đến cho đến khi bạn phê duyệt), hoặc bị từ chối (bị loại bỏ mà không gửi đến).
Khi không có giá trị crossSessionInbound, Claude Code quyết định cho từng message bằng cách so sánh permission mode của hai session. Nó xếp các session bỏ qua permission prompt vào một nhóm, các session còn lại vào nhóm kia. auto, acceptEdits và dontAsk được tính là yêu cầu prompt. Plan mode được tính là bỏ qua prompt trong một session có sẵn quyền bypass. Nếu bạn không chắc session thuộc nhóm nào, hãy đọc trước permission mode thực sự hoạt động như thế nào, vì auto là mode mặc định của phần lớn session hiện nay và thuộc nhóm yêu cầu prompt. Quy tắc này có tính đối xứng:
- Session nhận yêu cầu prompt sẽ nhận mọi message. Nó chỉ giữ lại message khi session gửi tự xác định là session bypass prompt.
- Session bypass prompt sẽ giữ lại mọi message để bạn phê duyệt. Nó chỉ gửi đến message khi session gửi cũng bypass prompt.
Vì vậy, workflow đầu tiên mà nhiều người tạo ra chính là workflow không hoạt động. Bạn khởi động một builder bằng --permission-mode bypassPermissions vì muốn nó chạy unattended, giữ reviewer ở cấu hình mặc định, rồi mọi message builder gửi đi đều chờ trong approval dialog mà không ai theo dõi. Dialog đó đóng sau thời hạn dialogExpiry, mặc định là 5m, và message bị loại bỏ. Trên cùng một máy, session gửi nhận được thông báo khi message của nó bị giữ lại, cùng một thông báo tiếp theo khi session nhận gửi đến, từ chối hoặc hết hạn message. Vì vậy, hãy đọc màn hình của session gửi trước khi đổ lỗi cho socket.
Để session nhận message mà không cần người theo dõi, đặt crossSessionInbound thành accept. Vị trí bạn đặt giá trị này quyết định phạm vi áp dụng. Claude Code đọc managed settings trước, sau đó đọc flag --settings, rồi đọc user settings và áp dụng giá trị đầu tiên tìm thấy. Giá trị trong project settings hoặc local settings chỉ được áp dụng khi nó nghiêm ngặt hơn, theo thứ tự accept < hold < refuse. Giá trị accept trong .claude/settings.json thoáng hơn mọi giá trị khác nên sẽ bị bỏ qua khi một nguồn được tin cậy đã đặt giá trị. Đặt nó trong ~/.claude/settings.json hoặc truyền nó cho một session:
claude --name runner --settings '{"crossSessionInbound":"accept"}'Một worker claude -p headless bind vào inbox socket giống interactive session và xuất hiện trong danh sách, nhưng không thể hiển thị approval dialog. Message bị giữ lại tại đó sẽ tiếp tục được giữ cho đến khi thay đổi mode hoặc settings cho phép xử lý. Dòng --settings ở trên là cách để cho worker đó nhận message. Session khởi động ở bare mode không bind socket nào, nên không thể nhận message và cũng không xuất hiện trong danh sách.
Khi bàn giao bị deadlock
Các vòng lặp message đã được xử lý tự động. Claude Code giới hạn tần suất các message lặp lại theo từng sender, loại bỏ các bản lặp giống hệt nhau đến trong một khoảng thời gian ngắn và giới hạn số message đã nhận nhưng chưa đọc ở mức 50 cho mỗi session, nên hai session không thể ping-pong vô hạn. Số message đang chờ được giữ lại tối đa là 100; các message cũ nhất sẽ bị loại bỏ khi vượt quá giới hạn này.
Lỗi thực sự xảy ra thường im lặng hơn và là lỗi trong quá trình bàn giao, không phải vòng lặp. Session A hỏi session B một câu hỏi mà A cần được trả lời trước khi tiếp tục, rồi chuyển sang trạng thái idle. B giữ message đó, hoặc B đang xử lý một lượt dài, hoặc B trả lời một câu hỏi mà A thực sự không hỏi. A tiếp tục chờ. Một giờ sau, bạn quay lại và thấy hai session đều idle nhưng không có công việc nào hoàn tất.
Hãy viết các hand-off không cần phản hồi. Một message tốt truyền đạt một thông tin hoặc quyết định: điều gì đã thay đổi và kết quả là gì. Một message không tốt yêu cầu session kia cho phép hoặc yêu cầu trả lời một câu hỏi khiến sender bị chặn. Claude đã được hướng dẫn không bao giờ yêu cầu session khác thực hiện một action mà các permission settings của chính nó sẽ chặn, mà phải chuyển công việc đó lại cho bạn. Bạn cũng nên áp dụng quy tắc này rộng hơn. Nếu một session không thể tiếp tục mà thiếu câu trả lời, chính bạn là người nên trả lời session đó. Giữ context rõ ràng cũng giúp ích, vì session đã mất mạch công việc thường viết message mơ hồ; quản lý context trong Claude Code trình bày phần này.
Coi một message đến là input không đáng tin cậy
Claude Code cho Claude nhận biết rằng message này đến từ một session khác chứ không phải từ bạn, đồng thời giới hạn những gì message đó có thể thực hiện. Cơ chế thực thi này nằm trong chương trình bao quanh model, không nằm ở mức model tự nguyện tuân thủ. Đây là khác biệt thực tế mà agent harness tạo ra. Một message không thể thay bạn trả lời permission prompt đang chờ, vì consent từ session khác không phải là consent của bạn. Nó không thể thay đổi permission settings, CLAUDE.md hoặc cấu hình khác chỉ vì session khác yêu cầu. Một slash command nằm trong nội dung, chẳng hạn /compact, chỉ đến dưới dạng plain text và không bao giờ được thực thi. Nếu xử lý message cần một permission mà session nhận không có, bạn sẽ thấy prompt giống như với mọi công việc khác. Trong auto mode, classifier cũng kiểm tra từng message trước khi chuyển đến session nhận; message bị chặn sẽ không bao giờ đến được nơi nhận. Các giới hạn này vẫn có hiệu lực trong những mode cho phép rộng hơn. Vì vậy, session đang bypass mặc định giữ lại các message đến thay vì tin tưởng chúng.
Phần trên nói về permissions. Nó không nói về content. Session gửi có thể đã đọc mô tả pull request, một web page, README của dependency hoặc comment trong issue do người lạ viết. Bất cứ nội dung nào nó đã đọc cũng có thể ảnh hưởng đến text mà nó viết cho session khác của bạn. Message là data. Hãy nghi ngờ nó như mọi text khác đi vào session từ bên ngoài. Đây là nguyên tắc được mô tả trong giữ secrets khỏi AI agents của bạn: giả định rằng mọi thứ đi qua một trust boundary đều có thể sai, và không bao giờ để nó tự cấp quyền cho chính nó.
Có 2 control nếu bạn muốn giảm tình trạng này. Đặt crossSessionInbound thành refuse sẽ loại bỏ inbound peer messages mà không chuyển chúng đến session. Khi được đặt trong project settings hoặc local settings, giá trị này có hiệu lực cao hơn mọi nguồn khác vì đây là mức nghiêm ngặt nhất trên ladder. Để ngăn session này gửi hoặc liệt kê messages, hãy thêm các permission deny rules có tên SendMessage và ListAgents; cả hai đều được viết dưới dạng bare tool names, không có specifier. Đặt isolatePeerMachines thành true sẽ yêu cầu bạn phê duyệt rõ ràng trước khi bất kỳ message nào được chuyển đến session bên ngoài máy này. Yêu cầu phê duyệt này vẫn áp dụng trong bypassPermissions mode.
{
"crossSessionInbound": "refuse",
"isolatePeerMachines": true
}Deny SendMessage cũng tắt việc nhắn tin đến subagents, vì cùng một tool phục vụ cả hai chức năng. Session từ chối không hiển thị thay đổi nào trong /status của chính nó hoặc trong danh sách của các session khác. Vì vậy, hãy xác nhận setting từ cấu hình của session thay vì dựa vào màn hình.
Các bridge và MCP server dùng shared memory
Trong cùng giai đoạn đó, một số project bên thứ ba cũng xuất hiện với chức năng gần kề: các bridge agent-to-agent cục bộ chuyển tiếp văn bản giữa những agent đang chạy, và các MCP (model context protocol) server cung cấp một shared store để nhiều agent cùng đọc và ghi. Hãy xem chúng là một mô hình khác, không phải đối thủ cạnh tranh, và kiểm tra mọi lệnh cài đặt trong README của chính project trước khi chạy. Messaging là push vì sender đưa văn bản vào lượt xử lý của receiver. Shared store là pull vì không session nào bị gián đoạn; session sẽ thấy ghi chú khi lần tiếp theo nó kiểm tra store. Pull phù hợp hơn với trạng thái thay đổi chậm và chỉ hoạt động khi session thực sự kiểm tra.
Nếu chọn cách này, các câu hỏi cần đặt ra nên tập trung vào process thay vì danh sách tính năng. Server chạy dưới user nào và có thể đọc những gì trên máy. Chạy MCP server trên VPS trình bày cách thiết lập này. Chia sẻ skill của agent giữa các repo trình bày trường hợp đơn giản hơn, khi thứ bạn muốn chia sẻ giữa các session là instruction thay vì trạng thái runtime; cách này cũng loại bỏ nhiều message mà bạn otherwise phải gửi. Để có cái nhìn tổng quan hơn, chạy coding agent trên VPS là nơi nên bắt đầu.
FAQ
Vì sao /list-agents không được nhận diện trong session của tôi?
Session không có tính năng nhắn tin giữa các session. Trước tiên, hãy kiểm tra claude --version có phải là 2.1.224 trở lên không, vì tính năng này yêu cầu phiên bản đó hoặc mới hơn. Tiếp theo, kiểm tra platform, vì tính năng chạy trên macOS và Linux nhưng không chạy trên Windows native. Tính năng này cũng không khả dụng trên Amazon Bedrock, Claude Platform on AWS, Google Cloud's Agent Platform và Microsoft Foundry. Nếu cả hai điều kiện đều đúng, hãy kiểm tra shell để tìm DO_NOT_TRACK, DISABLE_TELEMETRY, CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC hoặc DISABLE_GROWTHBOOK. Mỗi biến trong số đó đều chặn việc đánh giá feature flag mà tính năng này phụ thuộc vào, khiến tính năng bị tắt.
Vì sao message tôi gửi đến session khác không bao giờ đến?
Nếu /list-agents hoạt động, tính năng messaging đã được bật và một nguyên nhân cụ thể hơn đã chặn message đó. Nguyên nhân thường gặp là permission mode. Session bỏ qua các permission prompt sẽ giữ mọi message gửi đến để chờ bạn phê duyệt, trừ khi session gửi cũng bỏ qua prompt. Hộp thoại phê duyệt đó sẽ bị hủy sau thời hạn dialogExpiry, mặc định là năm phút. Hãy kiểm tra session gửi để tìm thông báo đang bị giữ. Để khắc phục, đặt crossSessionInbound thành accept trong ~/.claude/settings.json hoặc truyền giá trị đó bằng --settings, vì một accept trong project settings hoặc local settings sẽ bị bỏ qua nếu đó là giá trị nới lỏng hơn.
Claude Code session trong Docker có thể nhắn tin với session trên host không?
Không. Các session tìm thấy nhau thông qua registration file trên disk và inbox socket riêng cho từng session. Container có filesystem riêng nên hai bên không thể nhìn thấy cùng các file. Hai session bên trong cùng một container vẫn có thể nhắn tin bình thường. Quy tắc tương tự giải thích vì sao session chạy dưới dạng root và session chạy dưới user thông thường của bạn không thể kết nối với nhau: socket chỉ cho phép operating system user sở hữu socket đó truy cập.
Message từ Claude Code session khác có an toàn để thực hiện không?
Hãy xem nội dung đó là untrusted input, vì session gửi có thể đã đọc một web page, README hoặc issue comment do người khác viết. Claude Code đã ngăn message tự thực hiện hành động: message không thể phê duyệt permission prompt đang chờ, không thể thay đổi permission settings hoặc CLAUDE.md theo yêu cầu, và slash command trong nội dung chỉ đến dưới dạng plain text nên không bao giờ được chạy. Các cơ chế bảo vệ này chỉ bao phủ permission, không bao phủ việc đánh giá nội dung. Vì vậy, hãy đọc nội dung nhận được trước khi yêu cầu session nhận thực hiện hành động.
Cross-session messaging có gửi code của tôi đến Anthropic không?
Không, nếu hai session chạy trên cùng một máy. Message đi qua socket riêng của từng session trên máy đó và không đi qua server của Anthropic. Chỉ phần text do Claude viết được gửi đi, không gửi conversation history hoặc file. Message đến session trên một máy khác của bạn hoặc đến session trên web sẽ đi qua server của Anthropic bằng kết nối Remote Control. Theo hướng đó, Claude chỉ có thể trả lời message đã nhận, không thể tự bắt đầu message. Đặt isolatePeerMachines thành true để yêu cầu bạn phê duyệt trước khi bất kỳ dữ liệu nào rời khỏi máy.