跳至內容

實作課程 05 — 工作階段

目標: 持久保存並繼續 Copilot SDK 交談,這是「代理程式隨處可用」背後的建構基礎。

時間: 約 20 分鐘

必要條件: 實作課程 04 已完成。

步驟 1 — 瞭解持久化的重要性

若沒有工作階段持久化,每次處理程序重新啟動都會失去記憶。助理只能看到目前處理程序中傳送的訊息,因此 CLI 當機、瀏覽器重新整理或伺服器回收都會導致交談遺失。

有了已儲存的工作階段,交談便具有身分。您可以在 CLI 中開始、從 Web 應用程式繼續,之後再從手機接續。這就是「代理程式隨處可用」背後的核心模式:用戶端會改變,但工作階段歷程始終與同一個識別碼關聯。

此範例會先示範較有限的證明:在相同處理程序與相同的 CopilotClient。它也支援 --resume <id> ,因此當您的環境使用相同的工作階段持久化存放區與執行階段時,可以嘗試第二個獨立處理程序。

步驟 2 — 使用已知識別碼建立工作階段

開啟 SessionsSample.cs 並找到工作階段識別碼:

var sessionId = $"sdklabs-{Guid.NewGuid():N}"[..24];

接著找出它傳入 SDK 的位置:

await using var session = await client.CreateSessionAsync(new SessionConfig
{
    SessionId = sessionId,
    Model = modelId,
    Streaming = false
});

SessionConfig.SessionId 可讓您提供自己的識別碼。若省略,SDK 會代為產生,但應用程式必須擷取並儲存該產生值,之後才能繼續工作階段。

在實際應用程式中,請使用對領域具有意義且唯一的識別碼,例如交談識別碼或支援案例識別碼。請勿在識別碼中放入機密資訊:識別碼經常會出現在記錄、診斷資訊與 URL 中。

步驟 3 — 執行範例

dotnet run --project src/AgentOrchestrator/samples/SdkLabs -- sessions

預期輸出:

== Lab 05: sessions ==

Model: claude-haiku-4.5
Session id: sdklabs-7946e93975844b2e

--- Turn 1 (new session) ---
You: Remember this: my favourite retail segment is 'At Risk'. Reply with just OK.
Assistant: OK.

Session disposed.

--- Turn 2 (resumed session) ---
You: Which retail segment did I say was my favourite?
Assistant: 'At Risk'.

--- Session metadata ---
  id=sdklabs-7946e93975844b2e metadata retrieved

每次執行的工作階段識別碼都是隨機產生,因此您的值會不同。重要的證明不是識別碼值,而是第二回合記得 'At Risk' ,而且第一個工作階段已遭處置。

這次執行證明在單一處理程序中,物件處置後仍可繼續工作階段;但它本身無法證明跨裝置交接或重新啟動復原。

步驟 4 — 繼續工作階段

第二個回合使用相同識別碼,但呼叫不同的 SDK 方法:

await using var resumed = await client.ResumeSessionAsync(
    sessionId,
    new ResumeSessionConfig
    {
        Model = modelId,
        Streaming = false
    });

⚠️ 設定參數為必填。 在 SDK v1.0.9 中,以下程式碼無法編譯:

await client.ResumeSessionAsync(sessionId);

編譯器會回報 CS7036 ,因為必填設定參數沒有對應引數。

⚠️ 請使用 ResumeSessionConfig,而不是 SessionConfig. 建立新工作階段時使用 SessionConfig;繼續現有工作階段則使用 ResumeSessionConfig。繼續工作階段設定包含此處使用的同類設定,包括 Model 以及 Streaming,但型別不同。

為了讓證明更有力,請使用第一次執行所列印的工作階段識別碼,在第二個處理程序中執行繼續路徑:

dotnet run --project src/AgentOrchestrator/samples/SdkLabs -- sessions --resume sdklabs-7946e93975844b2e

第二次呼叫的已驗證輸出:

== Lab 05: sessions ==

Model: claude-haiku-4.5
Session id: sdklabs-7946e93975844b2e

--- Resumed existing session ---
You: Which retail segment did I say was my favourite?
Assistant: 'At Risk'.

--- Session metadata ---
  id=sdklabs-7946e93975844b2e metadata retrieved

第二個命令確實會跨越處理程序邊界。若要從另一台電腦繼續,還必須能存取相同的工作階段持久化存放區、使用相容的執行階段,並具備適當授權。

步驟 5 — 探索已儲存的工作階段

範例也會向 SDK 要求中繼資料:

var metadata = await client.GetSessionMetadataAsync(sessionId);

該呼叫會傳回已儲存工作階段的中繼資料。若要瀏覽可用的已儲存工作階段,而不是從已知識別碼開始,請使用 ListSessionsAsync(...):

var sessions = await client.ListSessionsAsync(...);

常見模式如下:

  1. 列出已登入使用者的工作階段
  2. 讓使用者選擇一個,或選取最新項目
  3. 將該識別碼傳入 ResumeSessionAsync(id, config)

步驟 6 — 連結至架構

工作階段持久化可支援:

  • 跨裝置與用戶端交接 — 從一處開始,再到另一處繼續
  • 當機復原 — 在處理程序重新啟動後繼續,而不是從頭重建內容
  • 可稽核性 — 穩定的識別碼讓交談更容易檢視、整理及追蹤

目前的示範應用程式透過以下項目,將聊天歷程保留在瀏覽器 localStorage 中: StorageService。這適用於單一裝置上的單一瀏覽器,但無法將交談移至另一部裝置。如果您在手機或另一台電腦上開啟應用程式,歷程記錄便不存在。

SDK 工作階段正是解決方案。UI 可以儲存工作階段識別碼,而不是整段交談內容;經授權且使用相同工作階段存放區的用戶端,就能繼續同一個伺服器端工作階段。

⚠️ 工作階段識別碼不是存取控制機制。 請將識別碼視為識別用途,而不是機密資訊或能力權杖。應用程式在繼續已儲存的交談前,仍需執行一般使用者驗證與授權。

⚠️ 常見陷阱

  • 識別碼衝突: 工作階段識別碼就是您的索引鍵。重複使用識別碼會繼續舊交談,而不是建立全新的交談。
  • 不透明識別碼: 隨機識別碼適合示範,但實際系統應能將識別碼對應回使用者、案例或工作流程。
  • 識別碼不是權限: 只知道或猜到識別碼,不應足以存取交談;請另外強制執行授權。
  • 識別碼中的機密資訊: 絕不要在工作階段識別碼中包含權杖、電子郵件地址、客戶機密或機密資料。
  • 錯誤的繼續多載: ResumeSessionAsync(sessionId) 會失敗並顯示 CS7036;請傳入 ResumeSessionConfig.
  • 錯誤的設定型別: SessionConfig 用於建立; ResumeSessionConfig 用於繼續。

💡 延伸練習

繼續同一工作階段兩次:

  1. 在中繼資料呼叫後新增第三個回合
  2. 繼續同一個 sessionId 再次
  3. 針對原本的內容再問一個問題: 'At Risk' 訊息

或者,列出已儲存的工作階段,並繼續最近的一個:

var sessions = await client.ListSessionsAsync(...);

接著將選取的識別碼傳入:

await client.ResumeSessionAsync(id, new ResumeSessionConfig
{
    Model = modelId,
    Streaming = false
});

✅ 檢查點

您現在可以說明:

  • [x] 瞭解為何沒有持久化時,處理程序重新啟動會遺失內容
  • [x] 如何 SessionConfig.SessionId 會為應用程式提供穩定的交談索引鍵
  • [x] 為何 ResumeSessionAsync(id, config) 需要 ResumeSessionConfig
  • [x] 如何 GetSessionMetadataAsync 以及 ListSessionsAsync(...) 協助探索已儲存的工作階段
  • [x] 瞭解為何 SDK 工作階段是跨裝置聊天歷程的正確基礎
  • [x] 瞭解跨處理程序與跨裝置繼續工作階段,還仰賴共用儲存空間、相容的執行階段行為與授權