SSD Nodes Learn 🎉 VPS từ $5.50/tháng
Hướng dẫn Matt ConnorBởi Matt Connor · Cập nhật ngày 2026-08-10

Claude Code: Cách các session nhắn tin cho nhau

Tìm hiểu cách hai session Claude Code trên cùng VPS trao đổi, vai trò của ListAgents và SendMessage, khi nào cần session thứ hai và vì sao tin nhắn bị giữ.

Ý 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à dưới 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ờ phải tự gọi hai tool này. Bạn nêu thông tin mà session còn lại cần biết, 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 trong WSL 2. Tính năng này không hỗ trợ Windows native và không có 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 này, tính năng nhắn tin đã được bật sẵn và không cần enable 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 thường chạy đủ lâu để bạn cần gửi tin cho chúng. Trên laptop, bạn đóng nắp máy. Trên server chạy dưới tmux, một session khởi động vào thứ Hai vẫn 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 bạn chưa thiết lập, hãy bắt đầu với chạy Claude Code trên VPS dưới tmux, trong đó có phần thiết lập session mà hướng dẫn này giả định bạn đã có.

Khi một session thứ hai xứng đáng với chi phí token

Hãy bắt đầu từ chi phí. Mỗi session là một instance Claude riêng, có context window riêng, vì vậy hai session tốn khoảng gấp đôi một session trong cùng 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 như 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 là một chuỗi bước sẽ chậm hơn, tốn kém hơn khi bạn chia chúng ra nhiều session.

Các trường hợp session thứ hai tự bù được chi phí thường có cùng một đặc điểm. Hai phần việc chạy đồng thời mà không phải chờ nhau, và một phần việc phát hiện thông tin mà phần còn lại cần trong lúc đang chạy.

  • Một session phát hiện breaking change trong khi session kia đang xây dựng dựa trên code vừa bị thay đổi. Claude tóm tắt thay đổi và gửi cho session kia, thay vì bạn phải nhập lại trong terminal còn lại.
  • Hai 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 đưa vào.
  • 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 diễn ra tuần tự, hoặc khi cả hai session cùng chỉnh sửa một nhóm file, hãy dùng một session. Khi bạn muốn một nhóm được Claude tạo và giám sát trong một task duy nhất, đó là agent teams, một tính năng riêng vẫn đang ở giai đoạn thử nghiệm. Khi bạn chỉ muốn tiếp tục cùng một cuộc trò chuyện trong terminal khác, hãy resume session đó. Cross-session messaging dành cho các session độc lập mà bạn tự khởi chạy và điều khiển.

Kiểm tra tính năng trước khi xây dựng cấu hình dựa trên nó

Trước tiên, kiểm tra phiên bản:

claude --version

So 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 chấp nhận /peers. Lệnh sẽ in ra mọi agent mà session này có thể truy cập, cùng với tên mà mỗi 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 file settings nào có thể bật tính năng đó. Nhập /status và tìm dòng Peer address: dòng này chứa địa chỉ inbox của chính session hiện tại, với tiền tố uds:.

Có một điểm dễ mắc lỗi, đặc biệt với người dùng VPS. 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ữ nguyên trạng thái mặc định là tắt. DO_NOT_TRACK, DISABLE_TELEMETRY, CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFICDISABLE_GROWTHBOOK đều có tác dụng này. Người dùng thường harden server mới bằng cách dán 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 file settings 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ỏ biến nào đang in ra. Với DISABLE_TELEMETRYCLAUDE_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, hãy bỏ 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 địa chỉ đến session đó

Claude định địa chỉ một message đến session bằng tên. Đặt tên khi bạn bắt đầu session:

claude --name builder-api

Bạ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 sẽ 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 dễ gây nhầm lẫn khi có bốn session. Hai session cũng có thể trùng tên. Output của /list-agents hiển thị working directory của từng session cục bộ, giúp phân biệt các session trùng tên. Danh sách do Claude tạo 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 so với phải đọc các mã định danh.

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, phù hợp với session chỉ đọc thay vì commit.

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 agents

Sau đó, Ctrl+bw 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 với thư mục làm việc ~/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 đó, chuyển việc cần làm bằng ngôn ngữ thông thường:

Tell reviewer-api which files I changed for the rate limiter and what to look at first.

Claude viết summary rồi gửi summary đó. Bạn không tự viết nội dung message; nội dung Claude gửi có thể khác nhau. Trong window reviewer, message xuất hiện trong conversation cùng tên người gửi. Nếu session đó đang idle, Claude lập tức bắt đầu một turn mới trên session đó. Nếu session đang trong một turn, message sẽ chờ đến giữa các lần gọi tool, nên command đang chạy không bị ngắt. Sau khi Claude đọc message, message được thu gọn thành một dòng Message fromCtrl+O sẽ mở rộng. Hai session hoạt động hiệu quả hơn khi builder giữ cho các thay đổi nhỏ, vì diff hẹp giúp hand-off ngắn hơn và để session còn lại hoàn tất review trong một turn. Đây là thói quen mà kỹ năng của senior dev lười được tạo ra để duy trì.

Ai có thể nhìn thấy ai trên cùng một VPS

Việc truyền nội bộ trên cùng một máy không đi qua server của 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 những session khác của bạn. Có 2 hệ quả, và cả hai đều quan trọng trên server.

Socket chỉ cho phép user hệ điều hành của session truy cập. Một session bạn khởi động bằng root và một session bạn khởi động bằng deploy không thể nhìn thấy nhau, ngay cả khi cùng chạy trong một tmux server. Session của user này không thể truy cập socket của user khác. Hãy chạy cả 2 session bằng 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ý. Hai 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, như trong chạy agent lập trình trong một VM dùng tạm, hãy dự kiến messaging chỉ hoạt động bên trong container, 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 ở đây chỉ có thể trả lời một message nhận được từ một trong các session đó. Nó không thể tự bắt đầu cuộc trao đổi đó.

Vì sao message của bạn không bao giờ đến nơi

Nguyên nhân thường gặp không liên quan đến network. Session nhận tự quyết định phải xử lý message thế nào, và quyết định đó là không gửi message đến nơi. Mỗi message đến sẽ kết thúc theo một trong ba trạng thái: đã gửi đến nơi, bị giữ lại (được để riêng và chưa gửi đến nơi cho đến khi bạn approve), hoặc bị từ chối (bị loại bỏ mà không gửi đến nơi).

Khi không có giá trị crossSessionInbound áp dụng, 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òn mọi session khác vào nhóm còn lại. auto, acceptEditsdontAsk được tính là hiển thị prompt. Plan mode được tính là bỏ qua prompt trong một session có sẵn quyền bypass. Quy tắc này có tính đối xứng:

  • Session nhận hiển thị permission prompt sẽ nhận mọi message. Session này chỉ giữ message khi session gửi tự xác định là đang bypass prompt.
  • Session nhận bypass prompt sẽ giữ mọi message để bạn approve. Session này chỉ nhận message khi session gửi cũng đang bypass.

Vì vậy, workflow đầu tiên mà hầu hết mọi người xây dựng lại chính là workflow không hoạt động. Bạn khởi động builder với --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 đề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 sau đó gửi đến nơi, từ chối hoặc để message hết hạn. 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, hãy đặ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 hoặc local settings chỉ được áp dụng khi nó chặt chẽ hơn, theo thứ tự accept < hold < refuse. Một accept trong .claude/settings.json lỏng hơn mọi giá trị khác, nên bị bỏ qua whenever một trusted source đã đặt giá trị. Hãy đặt nó trong ~/.claude/settings.json hoặc truyền giá trị này cho một session:

claude --name runner --settings '{"crossSessionInbound":"accept"}'

Một worker claude -p headless bind vào inbox socket giống session interactive và xuất hiện trong danh sách, nhưng không thể hiển thị approval dialog. Message bị giữ ở đó sẽ tiếp tục được giữ cho đến khi mode hoặc settings thay đổi và cho phép gửi message. Dòng --settings ở trên là cách để cho worker như vậy nhận message. Session được khởi động ở bare mode không bind socket nào, nên không thể nhận message hoặc xuất hiện trong danh sách.

Khi bàn giao bị kẹt

Các vòng lặp tin nhắn đã được xử lý tự động. Claude Code giới hạn tần suất các tin nhắn lặp lại theo từng sender, loại bỏ các tin nhắn trùng hệt đến trong một khoảng thời gian ngắn, và giới hạn số tin nhắn đã nhận nhưng chưa đọc ở mức 50 cho mỗi session. Vì vậy, hai session không thể ping-pong vô hạn. Số tin nhắn đang chờ cũng bị giới hạn ở mức 100; các tin nhắn 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 ít rõ rà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ó câu trả lời trước khi tiếp tục, rồi chuyển sang trạng thái idle. B giữ tin nhắn, hoặc B đang xử lý một lượt chạy dài, hoặc B trả lời một câu hỏi mà A thực ra 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 chưa làm được việc gì.

Hãy viết các tin nhắn bàn giao không cần phản hồi. Tin nhắn tốt truyền đạt một dữ kiện hoặc một quyết định: điều gì đã thay đổi và kết quả là gì. Tin nhắn không tốt yêu cầu session kia cho phép hoặc yêu cầu câu trả lời mà sender đang bị chặn vì chưa có. 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 setting của chính session đó 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 cho các trường hợp khác. 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 đó. Kỷ luật về context cũng hữu ích ở đây, vì một session đã mất mạch thường sẽ viết các tin nhắn mơ hồ; quản lý context trong Claude Code trình bày phần này.

Coi mọi tin nhắn đến là dữ liệu đầu vào không đáng tin cậy

Claude Code cho Claude nhận biết rằng tin nhắn đến từ một session khác, không phải từ bạn, đồng thời giới hạn những gì tin nhắn đó có thể thực hiện. Tin nhắn không thể thay bạn trả lời một permission prompt đang chờ, vì sự đồng ý từ session khác không phải là sự đồng ý của bạn. Tin nhắn cũng không thể thay đổi cài đặt permission, CLAUDE.md hoặc cấu hình khác chỉ vì session khác yêu cầu. Slash command nằm trong nội dung, chẳng hạn /compact, được nhận dưới dạng plain text và không bao giờ được thực thi. Nếu xử lý tin nhắn cần một permission mà session nhận không có, bạn sẽ thấy prompt giống như khi thực hiện bất kỳ tác vụ nào khác. Trong auto mode, một classifier cũng kiểm tra từng tin nhắn trước khi chuyển đến session nhận; tin nhắn bị chặn sẽ không bao giờ đến nơi. Những giới hạn này vẫn có hiệu lực trong các mode nới lỏng permission. Vì vậy, session đang bypass mặc định giữ lại tin nhắn đến thay vì tin tưởng chúng.

Phần trên chỉ nói về permission. Nó không bao quát nội dung. Session gửi có thể đã đọc mô tả pull request, một trang web, README của dependency hoặc comment trong issue do người lạ viết. Bất kỳ nội dung nào nó đọc cũng có thể ảnh hưởng đến văn bản nó gửi sang session khác của bạn. Tin nhắn là dữ liệu. Hãy nghi ngờ nó giống như mọi văn bản khác đi vào session từ bên ngoài. Đây là nguyên tắc được mô tả trong giữ bí mật ngoài các AI agent của bạn: giả định rằng mọi thứ vượt qua 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ỏ các tin nhắn peer đến mà không chuyển chúng đến session nhận. Khi giá trị này được đặt trong project settings hoặc local settings, nó được ưu tiên hơn mọi nguồn khác vì đây là mức nghiêm ngặt nhất trong thứ tự áp dụng. Để ngăn session này gửi hoặc liệt kê, hãy thêm các rule permission deny có tên SendMessageListAgents; cả 2 phải được viết dưới dạng tên tool thuần, 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ỳ tin nhắn 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 có hiệu lực ngay cả trong bypassPermissions mode.

{
  "crossSessionInbound": "refuse",
  "isolatePeerMachines": true
}

Từ chối SendMessage cũng ngăn việc nhắn tin đến subagent, vì cả 2 chức năng dùng chung một tool. Session từ chối không hiển thị thay đổi 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 cài đặt từ cấu hình của session thay vì kiểm tra trên màn hình.

Bridge và MCP server dùng shared memory

Trong cùng giai đoạn đó, một số dự án bên thứ ba cũng xuất hiện với hướng tiếp cận gần kề: bridge agent-to-agent chạy cục bộ để chuyển tiếp văn bản giữa các agent đang chạy, và MCP (model context protocol) server cho phép nhiều agent dùng chung một kho dữ liệu để đọc và ghi. Hãy xem chúng là một mô hình khác thay vì đối thủ cạnh tranh, đồng thời kiểm tra mọi lệnh cài đặt trong README của chính dự án trước khi chạy. Messaging là push vì bên gửi đưa văn bản vào lượt xử lý của bên nhận. Shared store là pull vì không có session nào bị gián đoạn, và session sẽ thấy ghi chú khi lần tiếp theo nó kiểm tra. Pull phù hợp hơn với trạng thái thay đổi chậm vì ít gây xáo trộn, nhưng chỉ hoạt động khi session thực sự kiểm tra.

Nếu chọn hướng này, các câu hỏi cần đặt ra nên tập trung vào quy trình 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ủ? Chạy MCP server trên VPS trình bày cách thiết lập này. Chia sẻ kỹ năng 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 trực tiếp; cách này cũng loại bỏ nhiều message mà nếu không bạn sẽ 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 hay mới hơn không, vì tính năng này cần phiên bản đó hoặc mới hơn. Tiếp theo, kiểm tra nền tảng, vì tính năng chạy trên macOS và Linux nhưng không chạy trên Windows bản native, đồng thời 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 đáp ứng, hãy kiểm tra shell để tìm DO_NOT_TRACK, DISABLE_TELEMETRY, CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC hoặc DISABLE_GROWTHBOOK, vì mỗi mục trong số đó đều chặn việc đánh giá feature flag mà tính năng này phụ thuộc vào và khiến tính năng bị tắt.

Vì sao tin nhắn tôi gửi đến session khác không bao giờ đến nơi?

Nếu /list-agents hoạt động, tính năng nhắn tin đã được bật và một vấn đề cụ thể hơn đã chặn tin nhắn đó. Nguyên nhân thường gặp là permission mode. Session bỏ qua các permission prompt sẽ giữ mọi tin nhắn đến để bạn phê duyệt, trừ khi session gửi cũng bỏ qua các prompt này. Hộp thoại phê duyệt đó sẽ bị hủy sau thời hạn dialogExpiry, mặc định là 5 phút. Hãy kiểm tra session gửi để tìm thông báo cho biết tin nhắn đang được giữ lại. Để 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 cài đặt project hoặc local sẽ bị bỏ qua nếu đó là giá trị ít hạn chế hơn.

Session Claude Code 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 các file đăng ký trên disk và một inbox socket riêng cho từng session. Container có filesystem riêng, nên hai session không thể nhìn thấy cùng các file. Hai session trong cùng một container vẫn có thể nhắn tin cho nhau bình thường. Quy tắc tương tự cũng giải thích vì sao session chạy dưới dạng root và session chạy bằng user thông thường của bạn không thể kết nối với nhau: socket chỉ cho phép user hệ điều hành sở hữu socket đó truy cập.

Tin nhắn từ session Claude Code khác có an toàn để thực hiện không?

Hãy xem nội dung đó là input không đáng tin cậy, vì session gửi có thể đã đọc một trang web, README hoặc issue comment do người khác viết. Claude Code đã ngăn tin nhắn tự thực hiện hành động: nó không thể phê duyệt permission prompt đang chờ, không thể thay đổi cài đặt quyền hoặc CLAUDE.md theo yêu cầu, và slash command trong nội dung chỉ được nhận như plain text nên không bao giờ chạy. Các cơ chế bảo vệ này chỉ áp dụng cho quyền, không thay thế 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.

Nhắn tin giữa các session có gửi code của tôi đến Anthropic không?

Giữa hai session trên cùng một máy, không. Tin nhắn đ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, không bao gồm lịch sử hội thoại hoặc file. Tin nhắn đế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 qua kết nối Remote Control. Theo chiều đó, Claude chỉ có thể trả lời tin nhắn đã nhận, không thể tự bắt đầu gửi tin nhắn. Đặt isolatePeerMachines thành true để yêu cầu bạn phê duyệt trước khi bất kỳ nội dung nào rời khỏi máy.