昨天我們認識了 AI Agent 的基本概念:一個能夠自主規劃與決策的系統,不再只是單純「你問我答」的 LLM 應用。那麼要如何落地實作一個 Agent 呢?這時候 LangGraph 就派上用場了。
LangGraph 是 LangChain 生態系中的一個新框架,專門用來設計基於 圖形(Graph) 的 AI Agent 流程。它讓我們可以用 節點(Node) 與 邊(Edge) 來描述 Agent 的推理與行動邏輯,使得流程清晰、可視化且易於擴充。今天,我們就從零開始帶你快速上手 LangGraph,建立一個最簡單的流程範例。
LangGraph 是一個專為開發者設計的 AI Agent 框架。它不只是單純串接大型語言模型的工具,而是一套能結構化規劃、組織並掌控 AI 邏輯流程的完整解決方案。這讓開發者在建構複雜應用時,能同時兼顧清晰度、可維護性與可控性。
LangGraph 的核心理念是以 圖形化流程(Graph-based workflow) 來建構 AI 應用:
在這樣的架構下,Agent 不再只是被動回應,而是能依據邏輯條件自主判斷,並按照定義的流程逐步完成任務。更重要的是,整個運作過程的每一步都可觀察、可控且可追蹤,讓 Agent 的行為透明化,也讓開發者能更放心地部署在真實應用場景中。
注意:LangGraph 官方已宣布將於 2025 年 10 月 推出
v1.0
版本。由於筆者在撰寫本文時,v1-alpha
文件內容仍未完整,且可能隨時變動。因此,本系列文章將以目前相對穩定的v0.3
版本為主進行說明。待v1.0
正式發佈後,若讀者採用新版本,請務必參考 官方文件 以取得最新資訊。
LangGraph 由 LangChain 團隊開發,並與 LangChain 保持高度相容。換句話說,你在 LangChain 中常用的元件,大多可以直接帶進 LangGraph 的流程中:
ChatOpenAI
、ChatAnthropic
等。PromptTemplate
、OutputParser
、Retriever
等模組,延續既有的設計模式。如果把 LangChain 視為一組打造 LLM 應用的積木元件庫,那麼 LangGraph 就是幫助你把這些積木以更有系統的方式組裝起來,最終構築出一個完整、可運作、且邏輯清晰的智能系統。
LangGraph 可以獨立使用,但它同時也是 LangChain 生態系中的重要一員。你可以將 LangGraph 與其他工具無縫結合,形成一個完整的 LLM 應用開發流程:
Note:LangGraph Studio 是一個視覺化介面,開發者能在其中設計流程圖、即時測試,並追蹤執行狀態。透過圖形化操作,複雜的 Agent 邏輯也能被更直觀地理解與調整,大幅提升開發效率與可維護性。
在 LangGraph 中,整個 AI Agent 的執行流程可以被建模成一張 圖(Graph)。在這個流程圖裡,每個 節點(Node) 代表一個可執行的動作單元,而 邊(Edge) 則負責決定下一步要執行哪個節點。整個過程由共享的 狀態(State) 貫穿始終,因此流程具有可追蹤、可重組、可測試的特性。
透過這種設計,我們能夠建構出可重複使用、能依條件變化、並且方便追蹤的複雜代理流程。同時,因為節點與邊本質上只是普通的 JavaScript/TypeScript 函式,開發者能自由混用 LLM、外部 API 或邏輯運算,而不會受到框架限制。
StateGraph
:定義與管理流程圖的主體在實作上,LangGraph 提供了一個名為 StateGraph
的核心類別,用來定義與管理整張流程圖。你可以透過它註冊節點與邊、管理狀態,並設定流程的起點與終點。
建立 StateGraph
的第一步,就是定義一個 State
結構,通常是用 Annotation
物件來描述。這個結構就是流程的核心資料模型,確保每個節點都能安全地存取和更新狀態。
在 LangGraph 中,State
是一切流程的中心。它就像是一份共享的資料快照,從流程開始建立後,會一直在不同 Node 之間傳遞與更新。
每個 Node 都會接收目前的 State
作為輸入,執行完邏輯後,把結果寫回到 State
的指定欄位。這份狀態的結構與行為,是透過一個叫做 Annotation
的物件來定義的。
Annotation
:定義 State 架構的方式LangGraph 使用 Annotation.Root()
來建立整份狀態的結構。你可以把它想像成一張資料表,其中的每一個欄位都有自己的資料型別與行為描述。
以下是一個簡單的例子,定義了兩個欄位:input
代表使用者輸入,result
則是處理後的輸出:
const State = Annotation.Root({
input: Annotation<string>,
result: Annotation<string>,
});
這樣一來,每個 Node 都能讀取 input
與 result
的值,也能在需要時進行更新。
Note:LangGraph 也支援用 Zod 來定義狀態結構。對習慣 schema 驗證的開發者來說,這會更直覺。例如
MessagesZodState
就是一個內建的 Zod 版本。。
有時候,我們不只是要覆寫欄位,而是需要更靈活的更新方式。這時就可以在狀態欄位上加上 reducer
函數,來決定新值和舊值要怎麼合併。
預設情況下,LangGraph 採用「最後寫入者覆蓋舊值」的規則。但你可以透過自訂 reducer
,實現累加、合併或去重等行為。例如:
const State = Annotation.Root({
foo: Annotation<number>, // 預設行為:直接覆寫
bar: Annotation<string[]>({
reducer: (state, update) => state.concat(update),
default: () => [],
}),
});
在這個例子中:
foo
是單一數字,每次更新都會直接取代舊值。bar
是字串陣列,每次更新會把新資料接在舊陣列後面,適合用來保存訊息或事件紀錄。Tip:如果需要像「聊天歷史」或「任務執行紀錄」這類會持續累積的資料,就很適合透過
reducer
來設計更新邏輯。
MessagesAnnotation
:對話紀錄狀態結構由於對話是最常見的 AI 應用場景之一,LangGraph 內建了一個現成的狀態結構:MessagesAnnotation
。
它包含一個 messages
欄位,並且內建了會自動累加訊息的 reducer,可以直接開箱使用:
import { MessagesAnnotation, StateGraph } from '@langchain/langgraph';
const graph = new StateGraph(MessagesAnnotation)
.addNode(...)
這樣就能立即處理多輪對話,而不用自己手動管理訊息列表。
如果還需要額外的欄位,也可以透過擴充的方式來加入:
const StateWithDocs = Annotation.Root({
...MessagesAnnotation.spec,
documents: Annotation<string[]>,
});
這樣既能保留對話訊息,又能新增自訂欄位,讓 Agent 擁有更彈性的資料處理能力。
在 LangGraph 中,Node 就是流程中每個步驟的執行單位。每一個 Node 通常就是一個 JavaScript/TypeScript 函式,負責接收當前的 State
,執行特定任務,並回傳要更新的結果。
可以把 Node 想像成一個「任務模組」,而整個 LangGraph 流程圖就是由這些任務模組組合起來的自動化工作流程。
每個 Node 都是一個同步的 function
或非同步的 async function
,通常會接收兩個參數:
state
:目前的共享狀態 State
,由前一個 Node 傳遞而來。config
:(可選)包含可設定的參數,例如 thread ID、使用者 ID 或其他自訂參數。LangGraph 預設使用 RunnableConfig
作為標準格式。以下是一個簡單的例子:
const myNode = (state: typeof GraphAnnotation.State, config?: RunnableConfig) => {
console.log('User ID', config?.configurable?.user_id);
return {
results: `Hello, ${state.input}!`
};
};
在這裡,我們從 state
中讀取 input
欄位,並產生一個回應字串寫入 results
欄位。
如果 Node 不需要額外設定,也可以省略第二個參數:
const myOtherNode = (state: typeof GraphAnnotation.State) => {
return state;
};
這些函式在背後會被轉換成 LangChain 的 RunnableLambda
物件,因此不僅能支援批次處理與串流輸出,還能直接使用 LangChain 提供的追蹤與除錯功能。
定義好 Node 函式後,就能透過 StateGraph
的 .addNode()
方法,把它們加到流程圖中:
const builder = new StateGraph(GraphAnnotation)
.addNode('myNode', myNode)
.addNode('myOtherNode', myOtherNode);
每個 Node 都需要設定名稱,例如上例中的 myNode
與 myOtherNode
。這個名稱會在後續定義 Edge 流程連線時被引用,用來決定 Node 之間的連接方式。
START
與 END
LangGraph 預設提供兩個特殊的系統節點,用來標記流程的起點與終點:
START
:流程的起點START
代表流程從哪裡開始,通常連接到第一個實際要執行的 Node:
import { START } from '@langchain/langgraph';
graph.addEdge(START, 'myNode');
END
:流程的終點END
代表流程結束,通常是在沒有下一步要執行時使用:
import { END } from '@langchain/langgraph';
graph.addEdge('myOtherNode', END); // 執行完 myOtherNode 後結束流程
可以把 START
與 END
想像成流程圖上的「開始」與「結束」符號,用來清楚標示整個流程的起點與終點。
在 LangGraph 中,Edge 是 Node 之間的連接線,負責定義流程的走向。換句話說,當一個 Node 執行完後,下一步要接到哪個 Node、流程是否要繼續、甚至是否要同時執行多個 Node,都是由 Edge 來決定的。
精心設計的 Edge 不僅能確保流程順暢推進,還能支援條件式分支、控制流程入口,甚至讓 Agent 能根據當前狀態自主選擇決策路徑,進一步提升系統的靈活性。
LangGraph 提供多種方式來建立 Edge,依照用途可以分為:
另外,一個 Node 並不限於單一路徑,它可以同時擁有多個輸出 Edge。這表示在該 Node 執行完後,可以平行啟動多個 Node,適合於用在需要同時處理多項任務的情境。
如果你希望節點 A 執行完後一定接著執行節點 B,可以使用 .addEdge()
方法直接建立連接:
graph.addEdge('nodeA', 'nodeB');
這是最常見的線性流程設計方式。
若你希望流程依據狀態中的值來決定要走哪條路線,可以使用 .addConditionalEdges()
,搭配一個 路由函式(routing function):
graph.addConditionalEdges('nodeA', routingFunction);
這個 routingFunction
會在 nodeA
執行完後被呼叫,接收目前的 state
作為輸入,並回傳要前往的 Node 名稱(可以是字串或字串陣列,支援平行處理):
const routingFunction = (state) => {
return state.result === 'ok' ? 'nodeB' : 'nodeC';
};
你也可以搭配 對應表(mapping object),把回傳值對應到指定的 Node:
graph.addConditionalEdges('nodeA', routingFunction, {
true: 'nodeB',
false: 'nodeC',
});
這樣的設計很適合應用在流程分支、錯誤處理或動態決策場景。
LangGraph 內建一個虛擬節點 START
,用來表示流程的入口。你可以用 .addEdge()
指定第一步要從哪個 Node 開始:
import { START } from '@langchain/langgraph';
const graph = new StateGraph(...)
.addEdge(START, 'nodeA') // 指定 nodeA 為流程的第一步
.compile();
有些情境下,你可能希望根據使用者輸入或某個狀態的值來決定流程的起點。這時就可以使用 .addConditionalEdges()
從 START
開始做動態路由:
const graph = new StateGraph(...)
.addConditionalEdges(START, routingFunction)
.compile();
同樣地,也可以提供對應表來定義不同條件對應的起點:
const graph = new StateGraph(...)
.addConditionalEdges(START, routingFunction, {
true: 'nodeB',
false: 'nodeC',
})
.compile();
這樣,流程就能根據情境選擇啟動起點,特別適合設計多角色、多模式的 Agent。
透過這些 Edge 的設計方式,你可以把不同的 Node 組合起來,建構出帶有條件邏輯、分支能力與平行處理的完整流程圖。再搭配 State 狀態管理與 Node 的任務執行單元,就能打造出一個 結構清晰、靈活可控、且可持續擴充的 AI Agent 系統。
理解 LangGraph 的基本流程設計後,接下來我們要實際動手操作 LangGraph,體驗如何快速啟動一個可執行的專案。
LangGraph 官方提供了一個 CLI 工具:create-langgraph
,能快速產生一個開箱即用的專案環境,裡面包含範例流程、專案架構、測試腳本與基本設定。對第一次接觸 LangGraph 的開發者來說,非常適合作為起點。
create-langgraph
建立專案首先,請先全域安裝 CLI 工具:
npm install -g create-langgraph
安裝完成後,執行以下指令來建立專案:
create-langgraph
接著,會出現互動式提示,依照指示輸入:
hello-langgraph
)完成後,CLI 會自動建立一個新專案,其中已包含範例流程與狀態管理的程式碼。
然後,進入新專案資料夾並安裝相依套件:
cd hello-langgraph
yarn install
Note:透過
create-langgraph
建立的專案,預設使用 yarn 作為套件管理工具。
安裝完成後,你可以先打開 src/agent/graph.ts
,這是專案的流程定義檔案。以下是其中一小段簡化的範例程式碼:
const callModel = async (state, _config) => {
console.log('Current state:', state);
return {
messages: [
{
role: 'assistant',
content: 'Hi there! How are you?',
},
],
};
};
const route = (state) => {
return state.messages.length > 0 ? '__end__' : 'callModel';
};
const builder = new StateGraph(StateAnnotation)
.addNode('callModel', callModel)
.addEdge('__start__', 'callModel')
.addConditionalEdges('callModel', route);
export const graph = builder.compile();
這段程式碼做了幾件事:
callModel
,它會輸出一段固定訊息。route
函式,根據狀態決定是結束流程還是回到 callModel
再執行一次。StateGraph
把節點和流程組合起來,並用 compile()
轉換為可執行的流程圖。而這個流程所使用的狀態結構,定義在 src/agent/state.ts
:
export const StateAnnotation = Annotation.Root({
messages: Annotation<BaseMessage[], BaseMessageLike[]>({
reducer: messagesStateReducer,
default: () => [],
}),
});
這是一個典型的「對話狀態」設定,利用內建的 messagesStateReducer
自動累加訊息,讓 Agent 能支援多輪對話。
.env
檔案在專案根目錄中會看到一個 .env.example
檔案。請複製它並建立 .env
檔案,然後填入所需的 API 金鑰,例如:
LANGSMITH_API_KEY=lsv2-xxxxxx
Note:LangGraph Studio 會透過 LangSmith 來記錄與追蹤執行流程。你可以回顧 Day 14 中「如何使用 LangSmith?」的內容,申請並取得
LANGSMITH_API_KEY
。
完成專案設定後,我們就可以啟動本地伺服器,來執行流程並進行測試:
npx @langchain/langgraph-cli dev
成功啟動後,終端機會輸出類似以下的訊息:
Welcome to LangGraph.js!
- 🚀 API: http://localhost:2024
- 🎨 Studio UI: https://smith.langchain.com/studio/?baseUrl=http://127.0.0.1:2024
這表示 LangGraph Server 已經在本機運行,並且同時提供一個 REST API 端點,以及一個視覺化的 Studio UI 介面,方便我們互動與除錯。
LangGraph Studio 是一個功能完整的視覺化工具,能幫助你即時觀察流程圖、狀態變化與節點執行歷程。
只要打開啟動指令輸出中提供的網址,例如:
https://smith.langchain.com/studio/?baseUrl=http://127.0.0.1:2024
你就會看到如下畫面:
切換到上方的「Chat」分頁,就能直接與你的 LangGraph Agent 互動:
在互動過程中,LangGraph Studio 會自動追蹤並視覺化顯示整個流程的細節。你可以清楚看到哪些節點被觸發與執行,狀態如何在節點之間流轉與更新,以及每個節點的輸入與輸出資料。
透過這些即時呈現的資訊,開發者能更直觀地理解 Agent 的運作方式,同時快速定位流程中的問題,進而更有效率地進行除錯與調整流程設計。
今天我們快速上手了 LangGraph,學會如何用圖形化流程設計 AI Agent,讓系統的邏輯更清晰、可控與可追蹤:
create-langgraph
CLI 可以快速建立專案,內含範例流程與狀態管理設定。LangGraph 讓我們能將 AI 的思考過程清晰地轉化為圖形化流程,使 Agent 的開發與維護更直觀易懂。接下來,我們將逐步探討各個環節的設計與應用,循序漸進地打造具備智慧決策能力的 AI Agent。