子系統傳出去的訊息,對方的回覆進了父系統的收件匣

子系統傳出去的訊息,對方的回覆進了父系統的收件匣

兩個人共用一個 LINE 帳號,你從辦公室傳了訊息出去,對方的回覆卻送到家裡那台手機,你爸先看到了。你等不到回覆,以為對方已讀不回,其實回覆早就在,只是進了別人的畫面。

這是台灣用戶滲透率超過九成的即時通訊工具裡常見的狀況。也是我最近在一個多代理系統裡遇到的問題——只是把 LINE 換成 API token,把家人換成父系統和子系統。

同一個 token,兩個收件匣

問題長這樣:一個自動化的子系統繼承了父系統的外部通訊憑證。對外部服務而言,這兩個系統是同一個身份——token 登記的擁有者是父系統。子系統傳出去的訊息確實送達了,但對方的回覆卻送進了父系統的收件匣。父系統會攔截這些回覆,子系統完全不知道有人回應。

這不是 token 失效。不是網路中斷。日誌裡所有 HTTP status 都是 200,訊息都有送達回條,外部服務也正常運作。問題在於「能用同一個 token 傳訊息」和「有獨立的通訊身份」被混為一談。

子系統以為自己有完整的對話脈絡,實際上只有發送權限,沒有接收管道。它像個在便利商店角落用筆電工作的工程師——全台每 2,213 人就有一家便利商店,但訊號再好也收不到別人家路由器的封包。

繼承不是複製

很多多代理架構會讓子系統繼承父系統的資源——包括憑證、設定檔、通訊管道。這在單向操作時沒問題:寫入資料庫、發送通知、記錄日誌。但只要涉及雙向互動,繼承就會出事。

因為繼承的是「使用權」,不是「所有權」。子系統可以用父系統的身份發言,但回覆的路由規則仍然指向原擁有者。外部服務看到的 sender ID 是父系統,webhook callback 自然也送回父系統註冊的 endpoint。

子系統在自己的 log 裡看到「message sent successfully」,卻永遠等不到 reply。它不知道父系統那邊已經收到三封回覆,還在納悶為什麼子系統一直重發同樣的請求。

修正方式:直接傳送,不依賴繼承設定

解法是讓子系統在每次任務結束前,主動用直接傳送機制送出訊息,而不是依賴繼承自父系統的投遞設定。具體做法是明確指定 reply endpoint,或者乾脆讓子系統註冊自己的 webhook,不要共用父系統的回呼路徑。

這不是 token 的問題,所以換 token 沒用。這是路由的問題——訊息的「去」和「回」走的不是同一條路。父系統可以把 token 借給子系統用,但不能把收件匣也一起借出去。

在多代理架構裡,身份認證和通訊路由是兩件事。前者可以共用,後者必須獨立。否則你會在日誌裡看到一切正常,但系統行為就是不對——因為對話的另一半在別人的螢幕上。

— 邱柏宇

延伸閱讀


Inheritance Breaks Identity

Two people share one messaging account. You send a message from the office. The reply goes to the phone at home. Your dad sees it first. You wait for a response that never comes, thinking the other person is ignoring you. The reply is already there — just in someone else’s inbox.

This is what happened in a multi-agent system I worked on recently. Replace the messaging app with API tokens, and family members with parent and child processes.

Same Token, Two Inboxes

The setup: an automated subsystem inherited the parent system’s external communication credentials. To the external service, these two systems share a single identity — the token is registered to the parent. The subsystem’s outgoing messages are delivered successfully. But replies route back to the parent’s inbox. The parent intercepts them. The subsystem never knows anyone responded.

This isn’t token expiry. Not network failure. All HTTP statuses are 200. Delivery receipts confirm arrival. External services operate normally. The problem is conflating “can send messages using the same token” with “has an independent communication identity.”

The subsystem thinks it has full conversational context. It actually only has sending privileges, not a receiving channel.

Inheritance Is Not Duplication

Many multi-agent architectures let subsystems inherit parent resources — credentials, config files, communication channels. This works fine for one-way operations: database writes, notifications, logging. But any bidirectional interaction breaks under inheritance.

Because what’s inherited is “usage rights,” not “ownership.” The subsystem can speak using the parent’s identity, but routing rules still point to the original owner. External services see the sender ID as the parent system. Webhook callbacks naturally return to the parent’s registered endpoint.

The subsystem’s logs show “message sent successfully.” It never receives replies. Meanwhile, the parent has received three responses and wonders why the subsystem keeps resending identical requests.

The Fix: Direct Transmission

The solution: have the subsystem explicitly specify its reply endpoint before each task completes, rather than relying on inherited delivery settings. Or register its own webhook entirely. Don’t share the parent’s callback path.

This isn’t a token issue, so rotating tokens doesn’t help. It’s a routing issue — the outbound and inbound paths are different roads. The parent can lend the token. It cannot lend the inbox.

In multi-agent architectures, authentication and communication routing are separate concerns. The former can be shared. The latter must be independent. Otherwise your logs will show everything working while system behavior stays broken — because the other half of the conversation lives on someone else’s screen.

— 邱柏宇

Related Posts