設計避免重複訊息的子代理

僅適用於:標準線束

重複訊息來自上下文缺口。 代理設計必須在每個步驟都考量情境。

次級代理,不論是子代理或連接代理,都會在父代理計畫中的獨立協調層上執行。 它會收到父方的請求並完成任務。 子代理產生三種輸出類型:向使用者展示的內容、透過定義輸出回傳的值,以及向呼叫代理發送的隱含回應。 家長無法看到子代理人與使用者的互動,只能透過定義的輸出和隱含回應得知結果。 這種有限的可見範圍常會導致重複訊息和漏掉回覆。

Tip

如需何時將工作分攤於多個代理人之間,以及多代理人的一般最佳實務,請參閱 多代理人協調模式與最佳實務 及 多代理人模式。 本文說明輸入與輸出如何使子代理人的回答與父代理人的情境對齊。

本文是以 標準框架中的內容脈絡分佈 所述的內容脈絡模型,以及 避免重複訊息的設計最佳實務 中的設計決策為基礎。

關閉已連線代理程式的父層內容

接收父母對話上下文的子代理可以對此採取行動。 如果該情境包含父版尚未回應的請求,子代理可能會回應、重複父版已處理的事項,或扮演錯誤的角色。 這些行為常導致重複訊息。

連接的代理有一個設定「 將對話歷史傳給此代理」,用以控制是否接收父代理的對話上下文。 此設定預設為啟用狀態。 取消選取,讓已連接的代理程式僅根據父層傳送的輸入運作,而不是根據整段對話內容。

「將對話紀錄傳給此客服人員」選項的截圖,請注意取消選擇會阻止客服人員間的歷史分享。

子代理則沒有對應的設定。 它運行在父節點內部,並且總是接收父節點的對話上下文。

對於需要保留其被指派工作上下文的已連線代理,以及預設就具有上下文的子代理,請使用範圍限定輸入來保護子代理的作用域。

使用限定範圍的輸入

有時子代理需要父代理的上下文來完成其任務。 當你傳遞該上下文時,請一併提供範疇輸入——它會明確告訴子代理程式確切要處理的內容,以免上下文中那些懸而未決、尚未回應的請求讓它偏離當前任務。 如果你不傳遞上下文,就不需要範圍輸入,因為子代理只有父代理轉發給它的請求。

為了保護子代理的範圍,請新增一個名為 scopedRequest 的輸入,描述如下: The specific request this agent should fulfill。 編排層在呼叫子代理時會填補輸入。 父代理會識別請求中相關的部分,並只傳遞該部分,即使其上下文中包含另一個未回應的請求。

即使不保留父上下文,範圍輸入仍是一個穩健的設計。 輸入讓製作者對送給子代理的請求內容有更多控制權。

將子代理的指令固定於該輸入,使其根據限定範圍的請求運作,並忽略任何其他看似初始請求的內容。

子代理指令範例:

Fulfill the request in the scopedRequest input. 
Treat it as your initial request and ignore any other initial requests in the conversation.

設定輸入和輸出

輸入與輸出是父體與子代理人之間的契約。 輸入會範圍子代理的工作範圍,輸出則告訴父代理發生了什麼,讓它能協調剩下的對話。 家長無法看到子代理與用戶的交流,因此這份合約是它唯一可靠的訊號。

Important

如果子代理未回傳任何結果,就是一個警訊。 沒有輸出,父方無法記錄子代理的回應或剩餘內容。 它可以重複子代理已經給出的答案,或刪除代理未處理的請求部分。

配置以下輸入與輸出,並為父編排層撰寫每個輸入的描述供讀取:

輸入或輸出 Description 使用方式
scopedRequest (輸入) 該代理人應滿足的特定需求。 父方只會填寫使用者請求中相關的部分。 它可防止子代理在父代理的上下文中仍包含其他尚未回答的請求時,回答錯誤的問題。 將子代理人的指令錨定在這個輸入上。
answered (輸出) 當使用者已經收到 scopedRequest 的回應時,這才是正確的。 為每個子代理程式都進行這項設定,無論它是否會向使用者傳送訊息,或是保持靜默。 如下所示的頂層指令會讀取該請求,讓父層不會再次回應相同的請求。
scopedRequest (輸出) 此代理程式處理的請求。 重複這個具範圍限制的請求,讓它傳遞到頂層編排層;該層無法可靠地將其建立的輸入保留在自己的上下文中。 在需要多重意向回合且需多個子代理人時,此功能能讓頂層人員正確規劃,避免將錯誤的子代理人導向錯誤的問題。
interactionSummary (輸出) 這是對用戶回應的簡短摘要。 當子代理直接向使用者傳送訊息時,請將其回傳,讓父代理知道已傳達了哪些內容,避免重複傳達。
findings (輸出) scopedRequest 的回應,供父層交付給使用者。 當子代理保持沉默時,請將其傳回,讓父代理有內容可傳遞。
openQuestions (輸出) 使用者請求中任何未被回應的部分。 由任何只能完成部分請求的子代理程式將其返回,或是在子代理程式的對話中出現了新的請求時將其返回,讓父代理程式完成其餘部分並繼續串接工具呼叫。 次代理不應該猜哪個代理負責剩餘部分。

選擇哪個元件與使用者通訊

決定是父代理還是子代理與使用者溝通。 大多數情況下,讓父代理與使用者溝通,以便將結果合併成一個回應。 當子代理需要提供長篇回應或進行多回合對話時,讓其直接溝通。 回傳足夠的資訊,讓家長能帶著上下文處理剩下的對話。

無論哪個元件進行通訊,都加入一條頂層指令,讓編排層在回應前檢查每個子代理的輸出。

這條範例頂層指令在所有情況下都適用,無論是子代理直接訊息給使用者還是保持靜默。 根據需要編輯和自訂。

每當呼叫任何主題或代理程式時,務必先查看名為「answered」的布林值輸出,再決定要如何回覆。 主題與代理人都有與使用者的專屬溝通管道。 如果「answered」為真,請始終假設請求已用至少一個輸出變數被適當回應,並根據輸出描述檢查是哪些變數。 不要尷尬地回應已回答的內容。 只提供尚未回覆的輸出內容,並自然地接續對話,進行下一步。

「 通道 」這個詞並不指整合通道。 它是一個提示裝置,告訴協調層使用者可能已經透過其他元件看到答案。

為父編排層撰寫子代理的描述,讓它知道何時使用子代理以及如何讀取其輸出。 例如:

Handles payroll questions. 
If its answered output is true, the user has already received their response and it should not be answered again.

在每個子代理上設定回應狀態和值輸出,無論子代理是否向使用者發送訊息或保持靜默,並給父代理一個讀取指令。 透過這種方法,代理可以混合使用靜默子代理與直接向使用者傳送訊息的子代理,兩者的差別僅在於其輸出。 在 「設計一個強健的頂層指令以避免重複訊息」中了解更多。

將使用者溝通委派給家長

考慮將所有使用者通訊路由至父代理,而非子代理。 在開始前收集子代理所需的輸入,完成後讀取它產生的輸出,並指示它不要直接訊息使用者。 一個從不向使用者回覆的子代理,無法再回答父代理已經回答過的內容。

告訴次級代理人保持沉默,並回報調查結果。 例如:

Do NOT reply or communicate with the user directly. 
Only fulfill the scopedRequest provided in the input and respond with the result.

靜默的子代理回傳 findings 和 openQuestions,兩者皆在 配置輸入與輸出中描述,將答案交給父代理並標記剩餘工作。

回傳一個 openQuestions 的輸出。 它允許編排層完成使用者剩餘的請求,並在子代理只能完成部分請求時繼續工具鏈。

要讓子代理人保持沉默,需要明確的指令。 預設情況下,子代理可以在執行時自行訊息使用者。 執行 完成 後設定不會阻止這些訊息,因為它只會在子代理完成後告訴父程式該怎麼做。

備註

告訴母代理「你是唯一能和使用者對話的代理」是行不通的。 父代理無法停止正在執行的子代理,且子代理仍可自行向使用者發送訊息。 相反地,指示次級代理人保持沉默,然後再測試確認。

有些子代理必須直接溝通

直接向使用者發送訊息的子代理是有效的選擇,並非違反規則,但需要刻意設計以避免父方重複訊息。

某些使用情境要求子代理直接回應使用者,無論是提供冗長回應而不複製到父上下文,或進行對話。 為避免重複訊息與上下文遺失,請在輸出中將上下文傳給父節點。

讓次級代理人給出長篇回覆並回傳摘要

子代理直接向使用者提供完整回應,並僅回傳簡短摘要或已交付答案的備註。 對於長篇回應(如詳細分析)請使用此方法,並將回傳資訊限制在家長的情境中。 目標是讓父層脈絡保持精簡,但仍具備足夠的資訊。

返回 answered 與 interactionSummary,兩者皆在 「配置輸入與輸出」中描述。

讓次級代理人與使用者進行對話

子代理會與使用者交換多個訊息,跨越多個步驟以完成範圍請求。 主要風險是家長不知道中間的對話步驟、次級代理人的工作和任何回答,或是任何新出現的請求。 因此,家長無法對新請求採取行動,也無法在後續步驟正確回應。

返回 answered、 scopedRequest、和 interactionSummary,如同配置 輸入與輸出所述。

頂層指令也涵蓋了此使用情境。