iT邦幫忙

2025 iThome 鐵人賽

DAY 21
0
生成式 AI

用 Node.js 打造生成式 AI 應用:從 Prompt 到 Agent 開發實戰系列 第 21

Day 21 - LangGraph 快速上手:使用圖形流程打造 AI Agent

  • 分享至 

  • xImage
  •  

昨天我們認識了 AI Agent 的基本概念:一個能夠自主規劃與決策的系統,不再只是單純「你問我答」的 LLM 應用。那麼要如何落地實作一個 Agent 呢?這時候 LangGraph 就派上用場了。

LangGraph 是 LangChain 生態系中的一個新框架,專門用來設計基於 圖形(Graph) 的 AI Agent 流程。它讓我們可以用 節點(Node)邊(Edge) 來描述 Agent 的推理與行動邏輯,使得流程清晰、可視化且易於擴充。今天,我們就從零開始帶你快速上手 LangGraph,建立一個最簡單的流程範例。

什麼是 LangGraph?

LangGraph 是一個專為開發者設計的 AI Agent 框架。它不只是單純串接大型語言模型的工具,而是一套能結構化規劃、組織並掌控 AI 邏輯流程的完整解決方案。這讓開發者在建構複雜應用時,能同時兼顧清晰度、可維護性與可控性。

LangGraph 的核心理念是以 圖形化流程(Graph-based workflow) 來建構 AI 應用:

  • 每個處理步驟是一個 節點(Node),代表 Agent 的一個行為或功能。
  • 節點之間的轉換由 邊(Edge) 定義,決定流程的執行方向。
  • 整個流程的資料與上下文則透過 狀態(State) 在節點之間傳遞與更新。

在這樣的架構下,Agent 不再只是被動回應,而是能依據邏輯條件自主判斷,並按照定義的流程逐步完成任務。更重要的是,整個運作過程的每一步都可觀察、可控且可追蹤,讓 Agent 的行為透明化,也讓開發者能更放心地部署在真實應用場景中。

注意:LangGraph 官方已宣布將於 2025 年 10 月 推出 v1.0 版本。由於筆者在撰寫本文時,v1-alpha 文件內容仍未完整,且可能隨時變動。因此,本系列文章將以目前相對穩定的 v0.3 版本為主進行說明。待 v1.0 正式發佈後,若讀者採用新版本,請務必參考 官方文件 以取得最新資訊。

LangGraph 與 LangChain 的關係

LangGraph 由 LangChain 團隊開發,並與 LangChain 保持高度相容。換句話說,你在 LangChain 中常用的元件,大多可以直接帶進 LangGraph 的流程中:

  • 可以直接使用 LangChain 提供的模型包裝器,如 ChatOpenAIChatAnthropic 等。
  • 可以結合 PromptTemplateOutputParserRetriever 等模組,延續既有的設計模式。
  • 可以把過去以「Chain」為基礎的思維,轉換成更具彈性與可讀性的「Graph」結構,讓流程的決策路徑更清晰直觀。

如果把 LangChain 視為一組打造 LLM 應用的積木元件庫,那麼 LangGraph 就是幫助你把這些積木以更有系統的方式組裝起來,最終構築出一個完整、可運作、且邏輯清晰的智能系統。

LangGraph 與其他開發工具的整合

LangGraph 可以獨立使用,但它同時也是 LangChain 生態系中的重要一員。你可以將 LangGraph 與其他工具無縫結合,形成一個完整的 LLM 應用開發流程:

  • LangSmith:提供追蹤、除錯與評估能力,能記錄 Agent 的執行路徑,協助分析決策邏輯、發現效能瓶頸,讓開發者更容易持續優化。
  • LangGraph Platform:一個專為 Agent 設計的雲端運行環境,支援狀態持久化、長時間運行以及跨團隊協作;同時可搭配 LangGraph Studio 使用,進一步提升開發體驗。

NoteLangGraph Studio 是一個視覺化介面,開發者能在其中設計流程圖、即時測試,並追蹤執行狀態。透過圖形化操作,複雜的 Agent 邏輯也能被更直觀地理解與調整,大幅提升開發效率與可維護性。

LangGraph 的核心概念:用 Graph 設計 Agent 流程

在 LangGraph 中,整個 AI Agent 的執行流程可以被建模成一張 圖(Graph)。在這個流程圖裡,每個 節點(Node) 代表一個可執行的動作單元,而 邊(Edge) 則負責決定下一步要執行哪個節點。整個過程由共享的 狀態(State) 貫穿始終,因此流程具有可追蹤、可重組、可測試的特性。

透過這種設計,我們能夠建構出可重複使用、能依條件變化、並且方便追蹤的複雜代理流程。同時,因為節點與邊本質上只是普通的 JavaScript/TypeScript 函式,開發者能自由混用 LLM、外部 API 或邏輯運算,而不會受到框架限制。

StateGraph:定義與管理流程圖的主體

在實作上,LangGraph 提供了一個名為 StateGraph 的核心類別,用來定義與管理整張流程圖。你可以透過它註冊節點與邊、管理狀態,並設定流程的起點與終點。

建立 StateGraph 的第一步,就是定義一個 State 結構,通常是用 Annotation 物件來描述。這個結構就是流程的核心資料模型,確保每個節點都能安全地存取和更新狀態。

State:LangGraph 的核心資料結構

在 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 都能讀取 inputresult 的值,也能在需要時進行更新。

Note:LangGraph 也支援用 Zod 來定義狀態結構。對習慣 schema 驗證的開發者來說,這會更直覺。例如 MessagesZodState 就是一個內建的 Zod 版本。。

Reducer:控制狀態如何被更新

有時候,我們不只是要覆寫欄位,而是需要更靈活的更新方式。這時就可以在狀態欄位上加上 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 擁有更彈性的資料處理能力。

Nodes:LangGraph 中的任務執行單位

在 LangGraph 中,Node 就是流程中每個步驟的執行單位。每一個 Node 通常就是一個 JavaScript/TypeScript 函式,負責接收當前的 State,執行特定任務,並回傳要更新的結果。

可以把 Node 想像成一個「任務模組」,而整個 LangGraph 流程圖就是由這些任務模組組合起來的自動化工作流程。

Node 的函式定義格式

每個 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 加入流程圖

定義好 Node 函式後,就能透過 StateGraph.addNode() 方法,把它們加到流程圖中:

const builder = new StateGraph(GraphAnnotation)
  .addNode('myNode', myNode)
  .addNode('myOtherNode', myOtherNode);

每個 Node 都需要設定名稱,例如上例中的 myNodemyOtherNode。這個名稱會在後續定義 Edge 流程連線時被引用,用來決定 Node 之間的連接方式。

特殊節點:STARTEND

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 後結束流程

可以把 STARTEND 想像成流程圖上的「開始」與「結束」符號,用來清楚標示整個流程的起點與終點。

Edges:決定流程要怎麼走

在 LangGraph 中,Edge 是 Node 之間的連接線,負責定義流程的走向。換句話說,當一個 Node 執行完後,下一步要接到哪個 Node、流程是否要繼續、甚至是否要同時執行多個 Node,都是由 Edge 來決定的。

精心設計的 Edge 不僅能確保流程順暢推進,還能支援條件式分支、控制流程入口,甚至讓 Agent 能根據當前狀態自主選擇決策路徑,進一步提升系統的靈活性。

Edge 的類型

LangGraph 提供多種方式來建立 Edge,依照用途可以分為:

  • Normal Edge:固定從一個 Node 接到下一個 Node,適合線性流程。
  • Conditional Edge:依照狀態內容動態決定下一步,常用於 if/else 或分支邏輯。
  • Entry Point:指定流程的起點,也就是第一個要執行的 Node。
  • Conditional Entry Point:依照條件動態決定流程從哪個 Node 開始。

另外,一個 Node 並不限於單一路徑,它可以同時擁有多個輸出 Edge。這表示在該 Node 執行完後,可以平行啟動多個 Node,適合於用在需要同時處理多項任務的情境。

Normal Edge:單一路徑

如果你希望節點 A 執行完後一定接著執行節點 B,可以使用 .addEdge() 方法直接建立連接:

graph.addEdge('nodeA', 'nodeB');

這是最常見的線性流程設計方式。

Conditional Edge:條件分支路徑

若你希望流程依據狀態中的值來決定要走哪條路線,可以使用 .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',
});

這樣的設計很適合應用在流程分支、錯誤處理或動態決策場景。

Entry Point:流程的起點

LangGraph 內建一個虛擬節點 START,用來表示流程的入口。你可以用 .addEdge() 指定第一步要從哪個 Node 開始:

import { START } from '@langchain/langgraph';

const graph = new StateGraph(...)
  .addEdge(START, 'nodeA') // 指定 nodeA 為流程的第一步
  .compile();

Conditional Entry Point:依條件決定起點

有些情境下,你可能希望根據使用者輸入或某個狀態的值來決定流程的起點。這時就可以使用 .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,體驗如何快速啟動一個可執行的專案。

LangGraph 官方提供了一個 CLI 工具:create-langgraph,能快速產生一個開箱即用的專案環境,裡面包含範例流程、專案架構、測試腳本與基本設定。對第一次接觸 LangGraph 的開發者來說,非常適合作為起點。

使用 create-langgraph 建立專案

首先,請先全域安裝 CLI 工具:

npm install -g create-langgraph

安裝完成後,執行以下指令來建立專案:

create-langgraph

接著,會出現互動式提示,依照指示輸入:

  • 專案名稱(例如:hello-langgraph
  • 模板類型(選擇 New LangGraph Project

https://ithelp.ithome.com.tw/upload/images/20250921/20150150GjyMXD7Thw.png

完成後,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

在本地啟動 LangGraph Server

完成專案設定後,我們就可以啟動本地伺服器,來執行流程並進行測試:

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 Web UI 進行互動與觀察

LangGraph Studio 是一個功能完整的視覺化工具,能幫助你即時觀察流程圖、狀態變化與節點執行歷程。

只要打開啟動指令輸出中提供的網址,例如:

https://smith.langchain.com/studio/?baseUrl=http://127.0.0.1:2024

你就會看到如下畫面:

https://ithelp.ithome.com.tw/upload/images/20250921/20150150ZvtvVmWvvM.png

切換到上方的「Chat」分頁,就能直接與你的 LangGraph Agent 互動:

https://ithelp.ithome.com.tw/upload/images/20250921/20150150uE45qXCle9.png

在互動過程中,LangGraph Studio 會自動追蹤並視覺化顯示整個流程的細節。你可以清楚看到哪些節點被觸發與執行,狀態如何在節點之間流轉與更新,以及每個節點的輸入與輸出資料。

透過這些即時呈現的資訊,開發者能更直觀地理解 Agent 的運作方式,同時快速定位流程中的問題,進而更有效率地進行除錯與調整流程設計。

小結

今天我們快速上手了 LangGraph,學會如何用圖形化流程設計 AI Agent,讓系統的邏輯更清晰、可控與可追蹤:

  • LangGraph 以 StateNodeEdge 為核心,能把 Agent 的任務切分並組合成一張完整流程圖。
  • State 扮演共享資料中心的角色,透過 Annotation 與 Reducer 控制欄位定義與更新方式。
  • Node 是任務執行單位,可搭配 LangChain 的模型、工具或自訂邏輯來完成不同功能。
  • Edge 負責串接節點並決定流程走向,支援條件式分支與平行處理。
  • LangGraph 與 LangChain 元件相容,能延續既有設計模式並整合 LangSmith、LangGraph Studio 等工具。
  • 透過 create-langgraph CLI 可以快速建立專案,內含範例流程與狀態管理設定。
  • 本地啟動 LangGraph Server 後,可透過 REST API 與 Studio UI 測試與觀察 Agent 的運作細節。

LangGraph 讓我們能將 AI 的思考過程清晰地轉化為圖形化流程,使 Agent 的開發與維護更直觀易懂。接下來,我們將逐步探討各個環節的設計與應用,循序漸進地打造具備智慧決策能力的 AI Agent。


上一篇
Day 20 - 認識 AI Agent:具自主決策與行動能力的智慧代理
下一篇
Day 22 - ReAct 模式實戰:封裝 LLM 建立可推理與行動的 Agent
系列文
用 Node.js 打造生成式 AI 應用:從 Prompt 到 Agent 開發實戰22
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言