<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Human-in-the-Loop on YennJ12 Engineering Blog</title><link>https://yennj12.js.org/yennj12_blog_V4/tags/human-in-the-loop/</link><description>Recent content in Human-in-the-Loop on YennJ12 Engineering Blog</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Thu, 15 Oct 2026 09:00:00 +0800</lastBuildDate><atom:link href="https://yennj12.js.org/yennj12_blog_V4/tags/human-in-the-loop/feed.xml" rel="self" type="application/rss+xml"/><item><title>LangGraph 客服工單後端：從狀態設計到可恢復的執行</title><link>https://yennj12.js.org/yennj12_blog_V4/posts/langgraph-ai-customer-ticket-system-zh/</link><pubDate>Thu, 15 Oct 2026 09:00:00 +0800</pubDate><guid>https://yennj12.js.org/yennj12_blog_V4/posts/langgraph-ai-customer-ticket-system-zh/</guid><description>第一版客服工單 Agent 通常長這樣：一個 prompt 做分類、一個 prompt 寫回覆、一個 prompt 打分數，不及格就再寫一次。 Demo 很好看；上線第三天就出現三種事故：重寫迴圈跑到 GraphRecursionError、退款工單被模型自己核准、Pod 重啟後 200 張處理中的工單全部從頭開始。 三件事故的共同點是：工單不是一次呼叫，它是一段會中斷、會等人、會跨越部署的執行。 LangGraph 的價值不在「多 Agent」，在於把這段執行變成 checkpoint 上一步一步可恢復的狀態轉移。
這篇文章的主張：客服工單後端的核心設計不是 prompt，而是「執行的生命週期」——哪些狀態要存、在哪裡暫停、失敗怎麼回頭、重啟後從哪接續。 下面用一條流程貫穿全文：接收（intake）→ 分類（classify）→ 路由（route）→ 解決（resolve）或升級（escalate）→ 結案（close），每一節解決這條流程上的一個設計決定，並說明替代方案在什麼條件下反而更對。
讀者預設是寫過後端 API、讀過〈LangGraph + LangChain 入門 〉知道 StateGraph、reducer、interrupt 是什麼的人。本文不重講這些基礎，直接進入「後端怎麼接」。
程式碼對照 LangGraph 1.x / LangChain 1.x 公開 API 撰寫，為示意用途、未在本文內執行；每段 ≤ 25 行，刻意省略 import 重複與錯誤處理樣板。模型 ID 從環境變數 LLM_MODEL 讀取。
一、工單不是一次呼叫 一張工單從進來到結案，典型的時間跨度與失敗點如下（以一個 SaaS 客服為例，數字是設計假設，不是量測值）：
階段 典型耗時 可能失敗的方式 分類 1–3 秒 模型回傳的 JSON 壞掉；API 429 查資料、擬回覆 5–30 秒（2–4 次工具呼叫） 工具逾時；模型編造訂單號 人工審核（約 15–25% 的工單） 10 分鐘到 2 天 服務在等待期間重新部署 結案與通知 &amp;lt; 1 秒 寄信成功但狀態沒寫回 → 重跑時寄第二封 把這張表讀成需求，就是四件事：狀態要存（不然重啟就丟）、流程要能暫停（等人兩天不能占著一個 request）、失敗要能局部重試（API 429 不該從分類重來）、副作用要冪等（重跑不能寄兩封信）。這四件事剛好對應 LangGraph 的 checkpointer、interrupt、節點級 RetryPolicy、以及「節點從頭重跑」的語意——接下來逐一接上。</description></item></channel></rss>