2026 年 AI Agent 堆疊:LangGraph vs 自訂 vs DIY

我大多數週期都會把 agent 部署到正式環境,而在每次啟動會議中,框架的選擇總是重複出現。誠實的答案是,「正確」的堆疊取決於你能容忍多少分支、多少狀態,以及多少爆炸半徑。我在去年用三種方式建置了相同的 agent,而這些取捨比框架行銷所呈現的更加明顯。以下是我實際的決策方式。

我經常使用的三種堆疊

當我開始一個新的 agent 時,我會從三個類別中選擇。其他一切都是這些的變體:

  1. DIY loop,意指一個普通的 while loop,圍繞 LLM 呼叫、工具執行和訊息陣列。大約 150 行 Python 或 TypeScript。
  2. 框架,現在幾乎總是 LangGraph,偶爾是 Pydantic AI 或 OpenAI Agents SDK 用於特定案例。
  3. 自訂編排,意指我自己撰寫狀態機,通常建置在訊息佇列或耐久執行器(如 Temporal、Inngest 或 AWS Step Functions)之上。

決策取決於三個問題:有多少步驟、多少並行性,以及當它在凌晨 3 點當機時會發生什麼。其他一切(可觀測性、評估、人機回圈)都可以附加到這三者中的任何一個。

什麼時候 DIY loop 是正確答案

對於任何少於約五個工具且具有線性 think-act-observe loop 的 agent,普通 loop 會勝出。我用這個方式處理我部署的約 40% 的 agent,包括 BizFlowAI ContentStudio 中的大多數子 agent。框架增加了抽象成本,只有在你有真正的分支時才會有回報。

以下是整個內容的樣子,扣除日誌記錄:

def run_agent(task: str, tools: dict, max_steps: int = 12):
    messages = [
        {"role": "system", "content": SYSTEM_PROMPT},
        {"role": "user", "content": task},
    ]
    for step in range(max_steps):
        resp = client.messages.create(
            model="claude-sonnet-4-5",
            messages=messages,
            tools=list(tools.values()),
            max_tokens=4096,
        )
        messages.append({"role": "assistant", "content": resp.content})

        if resp.stop_reason == "end_turn":
            return resp.content[-1].text

        tool_results = []
        for block in resp.content:
            if block.type == "tool_use":
                try:
                    result = tools[block.name]<a href="**block.input">"fn"</a>
                    tool_results.append({
                        "type": "tool_result",
                        "tool_use_id": block.id,
                        "content": str(result),
                    })
                except Exception as e:
                    tool_results.append({
                        "type": "tool_result",
                        "tool_use_id": block.id,
                        "content": f"ERROR: {e}",
                        "is_error": True,
                    })
        messages.append({"role": "user", "content": tool_results})

    raise RuntimeError("Agent exceeded max_steps")

進入全螢幕模式 退出全螢幕模式

就是這樣。優點是真實的:

  • 你在 IDE 中進行除錯。 堆疊追蹤指向你的程式碼,而不是三層框架內部。
  • Token 使用是透明的。 你可以看到並控制每一條發送的訊息。當我上季在一個專案中削減 40% 的 LLM 支出時,大部分都是在此 loop 中修剪訊息陣列。
  • 你擁有重試和錯誤表面。 工具錯誤會以 is_error: true 的形式返回給模型,使其能夠恢復,而如果模型在損壞的工具上迴圈,你會因為自己撰寫了計數器而捕捉到它。

DIY 失效的地方:跨長時間執行的任務進行平行工具執行、多 agent 交接,或任何需要檢查點以在程序重新啟動後倖存的東西。此時你要么正在建置框架,要么正在尋求一個。

什麼時候 LangGraph 值得其複雜性

LangGraph 是我在 2026 年經常使用的框架,主要是因為它將 agent 視為具有型別狀態的節點圖,而這種模型實際上符合複雜 agent 的行為方式。當工作流程有真正的分支(三個或更多有意義的路徑)、需要跨數小時或數天的耐久執行,或有多個 agent 相互通訊時,我會使用它。

價值體現在三個特定功能中:

  1. 型別狀態作為一等物件。 你為狀態定義 TypedDict 或 Pydantic 模型,每個節點返回部分更新。這比聽起來更有價值,因為它強迫你思考狀態轉換,而不是傳遞訊息陣列。
  2. 檢查點。 使用 SqliteSaverPostgresSaver,如果程序當機,圖形會從最後一個節點恢復。對於長時間執行的研究 agent 或人機回圈工作流程,這是不可或缺的。
  3. 用於人工審核的中斷。 你可以在節點處暫停圖形,等待外部輸入(Slack 核准、表單提交),然後恢復而不必重新執行之前的節點。

我被燒傷的地方:LangGraph 對 LLM 呼叫的抽象隱藏了 token 記帳,除非你明確地連接回呼。文件更新很快,有些六個月前有效的模式現在已被不鼓勵。如果你使用它,請固定你的版本並撰寫整合測試,以快照實際發送的 API 呼叫。

根據我部署的內容,大致的經驗法則:

Agent 類型 節點 最佳選擇
單一用途工具呼叫器 1-3 DIY loop
研究 + 撰寫 + 審核 4-8 LangGraph
具有交接的多 agent 8+ LangGraph 或自訂
長時間執行的工作流程(數小時以上) 任何 自訂編排
扇出到 50+ 平行任務 任何 自訂編排

什麼時候自訂編排值得撰寫

自訂編排意味著將 agent 視為分散式系統:耐久執行器(Temporal、Inngest、Step Functions,或在 SQS 上自行建置的東西)驅動工作流程,而每個 LLM 呼叫或工具執行都是該系統中的任務。當我需要倖存機器故障、單一「agent 回合」可能需要一小時,或必須扇出到數百個平行分支時,我會使用此方式。

我為 SLA 合規性建置的無伺服器 AWS + Zendesk 整合是自訂編排。不是因為它確實是「agent」,而是因為相同的推理適用:EventBridge 驅動工作流程,Lambda 函數是任務,DynamoDB 持有狀態。如果 Lambda 當機,EventBridge 會重試。如果工具失敗,狀態機知道從哪裡恢復。一旦你接受 LLM 呼叫只是另一個冪等任務,這種模式就能乾淨地對應到 agentic 工作流程。

自訂編排為你帶來的、框架無法提供的:

  • 真正的耐久性。 LangGraph 的檢查點器適合數小時。Temporal 或 Step Functions 適合數月。
  • 大規模扇出。 當我需要一個 agent 平行審核 500 份文件並彙總結果時,我需要一個真正的佇列和工作池,而不是試圖管理並行性的圖形庫。
  • 爆炸半徑控制。 每個任務都在隔離中執行。有毒的工具回應無法損壞整個執行,因為狀態是在步驟之間具體化的。

成本是真實的。你撰寫更多程式碼,你擁有基礎設施,你必須建置自己的 agent 行為視覺化。對於任何執行時間少於一小時且少於 10 個平行分支的任何內容,這都是過度的。超過此範圍,框架開始感覺像玩具。

我實際選擇的堆疊,一個決策一個決策

以下是我在新的 agent 專案開始時腦海中的流程圖:

  1. 工作流程是否線性且少於五個工具? DIY loop。在一週內部署。加入結構化日誌記錄、token 計數和重試包裝器。
  2. 它是否有真正的分支,或需要暫停以等待人工輸入? LangGraph,使用 PostgresSaver 進行檢查點,並使用 OpenTelemetry 回呼進行可觀測性。
  3. 單一執行是否持續數小時,或扇出到數百個平行分支,或需要倖存基礎設施故障? 在 Temporal 或 Step Functions 上的自訂編排。將每個 LLM 呼叫視為活動。
  4. 多 agent 且有三個或更多不同的 agent 相互通訊? 如果執行時間短則使用 LangGraph,如果執行時間長則使用自訂。絕不使用 DIY,因為 agent 之間的訊息路由是 DIY loop 變成難以維護的義大利麵程式碼的地方。

我比框架行銷所建議的更常傾向 DIY。野外的多數 agent 並不需要圖形。它們需要一個好的 loop、仔細的提示工程、緊密的工具結構描述,以及誠實的評估。當工作流程圖形不再適合單一畫面時,框架就會變得有用。

沒有人會告訴你、直到你部署的事物

一些讓我付出真實時間的經驗教訓:

工具結構描述比模型選擇更重要。 我曾見過相同的任務僅透過重寫工具描述和參數名稱,就從 60% 成功率提升到 95%。在你切換模型或新增框架之前,花一天時間在你的工具結構描述上。模型只能像你的工具允許的那樣聰明。

訊息陣列修剪是 token 節省的關鍵。 在 20 步驟的 agent 中,如果保留所有工具結果,訊息陣列在 token 方面呈平方增長。我保留最後 3-5 個工具結果原文,並摘要其餘部分。在一個內容 agent 上,這將成本削減了 40%,且沒有可衡量的品質損失。

錯誤字串是提示。 當工具失敗時,錯誤訊息會返回到模型的上下文中,並成為下一個提示的一部分。"Database connection failed" 是一個無用的提示。"Database query returned no rows for user_id=42. Try a different user_id or check if the user exists." 讓模型能夠恢復。

沒有冪等性的檢查點是謊言。 如果你的圖形從步驟 7 恢復,而步驟 7 呼叫了支付 API,你就向客戶收取了兩次費用。每個變更狀態的工具都需要冪等性金鑰。這對任何框架都是如此。

評估不是可選的。 我在每次部署之前,針對固定的一組 20-50 個測試案例執行我建置的每個 agent。不是花俏的 LLM-as-judge 東西,只是確定性檢查:它是否呼叫了正確的工具、最終答案是否包含了所需的欄位、它是否保持在 token 預算之內。這是 agent 工作中單一最高的投資報酬率工程實務。

如果我明天要開始一個新的 agent,我會做什麼

從 DIY loop 開始。首先確定工具、系統提示和評估集。從第一天起就對 token 使用和步驟計數進行儀表化。部署它,觀察它在真實輸入上失敗,然後修復它。

只有在工作流程圖形有真正的分支,或你需要耐久的暫停和恢復時,才使用 LangGraph。只有在單一執行超過一小時,或扇出超出單一程序應管理的範圍時,才使用自訂編排。不要跳過 DIY 階段:它會教導你你的 agent 實際在做什麼,而這些知識是讓框架選擇在後續變得明顯的關鍵。

框架辯論大多是噪音。部署且保持部署的 agent 是那些具有緊密工具結構描述、誠實評估,以及讓你能在 10 分鐘內除錯正式環境故障的可觀測性的 agent。其他一切都是支架。

如果你現在正在建置一個 agent 且在這些堆疊之間猶豫,我很樂意查看工作流程圖形並告訴你我會選擇什麼。請聯絡 lazar-milicevic.com/#contact,或閱讀更多關於 blog 的內容,我已在其中撰寫關於 agent 評估、上下文工程以及削減正式環境中的 token 支出。