讓我們逐步構建 Claude Code 的開發框架

@akshay_pachaar
英語5 天前 · 2026年7月15日
202K
841
122
29
1.9K

TL;DR

這是一份關於使用 CrewAI 構建程式設計 Agent 開發框架的完整教學。內容涵蓋核心執行迴圈、層級化委派、沙盒執行環境以及持久化記憶,協助您實現 Claude Code 等級的可靠性。

我們將涵蓋建構編碼工具的所有環節,包括 Agent 迴圈、規劃、子代理、沙盒、記憶和檢查點,會一步一步地建立起來。

如果你曾經嘗試過建構自己的編碼 Agent,你就知道事情是怎麼發展的。你把模型連接到檔案工具和 Shell,指向一個真實的程式碼庫,然後它通常在十幾次工具呼叫內就崩潰了。

它讀錯檔案,半途偏離目標,然後把上下文塞滿了它不再需要的輸出。

接著,同樣的任務交給 Claude Code 卻能乾淨俐落地完成。一個簡單的結論是:Anthropic 只是擁有更好的模型,而這個結論忽略了真正關鍵的工作在哪裡。

差異在於工具(Harness)。工具是包裹在模型周圍的普通程式碼,它負責處理規劃、工具執行、記憶和安全性,而模型只負責決定下一步要做什麼。

以下是當你把一個完整的工具 Agent 畫出來時的樣子:

Akshay 🚀 - inline image

GIF

這張圖看起來很複雜,但它可以分成四組:

  • 記憶 提供模型工作上下文,以及它在跨工作階段中學到的事實。
  • 技能 編碼了 Agent 應如何運作,也就是它遵循的程序、約束和啟發式規則。
  • 協議 將 Agent 連接到使用者、工具和其他 Agent。
  • 工具核心 透過子代理協調、沙盒、評估器、審批迴圈、可觀測性和上下文壓縮,將所有東西整合在一起。

Anthropic 將這種劃分描述為大腦和雙手。模型是選擇每個動作的大腦,而工具是執行這些動作並確保任務順利進行的雙手。

所以,你的 Agent 和 Claude Code 之間的差距不在於模型,而在於模型周圍的機制。

Claude Code 是當今生產環境中最強大的工具之一,而且它是由圖中那層層架構中,出奇地少的一部分所構建而成。為了了解你需要自己建構多少這樣的機制,我在 CrewAI 中重建了它,這是一個用於編排 Agent 的開源框架。

比我預期中更多的部分能對應到內建功能,而無法對應的部分,正是真正工程工作的所在。

讓我們一層層地建構它,從核心迴圈開始,然後疊上規劃、子代理、沙盒和記憶。在每一步,我們都會標記框架的極限在哪裡,以及你的工作從哪裡開始。

Claude Code 的工具如何運作

Claude Code 的核心是一個簡單的 Agent 迴圈。你發送一條訊息給它,模型決定下一步要做什麼,然後它要麼直接回應,要麼請求一個工具。如果它請求了工具,工具就會執行,結果會回傳到對話中,然後模型再次決定。

這個過程會重複,直到模型回傳一個最終答案,且不再有進一步的工具呼叫。

在該迴圈內部,模型會讀取檔案、編輯程式碼、執行 Shell 命令和執行測試。這些不是不同的模式。它們只是在同一個迴圈內的不同工具呼叫。

然而,僅靠迴圈並不足以構成一個可靠的編碼 Agent。Claude Code 在此基礎上增加了規劃、檔案工具、子代理、記憶,以及權限和沙盒系統。這些層次並不會取代迴圈,而是讓它變得足夠安全且可靠,以勝任實際工作。

Akshay 🚀 - inline image

這就是我們將要重建的架構,首先是核心迴圈,然後是上層的每一層,並將每一層對應到負責處理它的 CrewAI 功能。

核心 Agent 迴圈

這個迴圈會執行相同的序列,直到任務完成:

  1. 要求模型執行任務。
  2. 模型直接回應,或請求一個或多個工具。
  3. 如果請求了工具,就執行這些工具並將結果回傳給模型。
  4. 使用更新後的對話重複步驟。
  5. 當模型回應時沒有請求任何工具,任務即完成。
Akshay 🚀 - inline image
python
1while True:
2 reply = model(messages, tools)
3 calls = [b for b in reply if b.type == "tool_use"]
4 if not calls: # 純文字,沒有工具呼叫:工作完成
5 return reply.text
6 messages += [reply, run_all(calls)]

每次工具呼叫都完成一個步驟,為模型提供新資訊,並進入下一個決策。一個簡單的問題可能在一次迭代中完成,而修復一個複雜的錯誤或重構一個大型程式碼庫,則可能需要數十次迭代,模型才能擁有足夠的資訊來產出最終答案。

一旦你建立了一個 Agent,CrewAI 會自動提供這個執行迴圈。你不需要自己實作 while 迴圈,你只需要定義 Agent 並為它指派一個任務。

建立第一個 Agent

讓我們建立一個簡單的 Bug 修復 Agent。

python
1from crewai import LLM, Agent, Crew, Task
2
3bug_fixer = Agent(
4 role="Bug 修復者",
5 goal="在程式碼庫中找出報告的錯誤,並描述修復方法。",
6 backstory="你透過讀取目錄和檔案來建立對程式碼的準確理解。",
7 llm="claude-sonnet-4-6",
8)
9
10task = Task(
11 description="找出 {objective} 的修復方法。",
12 expected_output="一段簡短的修復說明,以及它所屬的檔案。",
13)
14
15result = Crew(agents=[bug_fixer], tasks=[task]).kickoff(
16 inputs={"objective": "account.py 中的超額透支錯誤"}
17)

這裡需要理解三個概念:

  • Agent 透過其角色、目標、LLM 和工具來定義誰來執行工作。
  • Task 描述任務指派。
  • Crew 將 Agent 和任務結合在一起。呼叫 kickoff() 會執行上述相同的執行迴圈,無論底層模型是 Anthropic、OpenAI、Google 或其他。

為 Agent 提供工具

工具是讓一個只能產生文字的模型能夠實際在程式碼庫上工作的關鍵。它們可以讀取檔案、寫入檔案、執行 Shell 命令以及呼叫外部 API。

CrewAI 內建了檔案系統工具:

  • FileReadTool 讀取檔案。
  • DirectoryReadTool 列出目錄。
  • FileWriterTool 寫入檔案。
python
1from crewai_tools import DirectoryReadTool, FileReadTool, FileWriterTool
2
3read_file = FileReadTool()
4write_file = FileWriterTool()
5list_dir = DirectoryReadTool()
6
7filesystem_tools = [read_file, write_file, list_dir]

這些工具也同時作為外部記憶。Agent 可以將大型搜尋結果寫入檔案,只保留檔名,並在需要時重新讀取,而不是將結果保留在模型的上下文視窗中。

這樣可以讓上下文視窗保持較小,讓模型更專注,這就是 Anthropic 所稱的上下文工程。

Akshay 🚀 - inline image

內建工具只涵蓋常見的工作流程。對於任何更特定的需求,你可以使用 @tool 裝飾器將 Python 函數公開為工具。

Docstring 充當了說明手冊,告知模型該工具的功能、何時使用以及它期望的輸入是什麼。

python
1from crewai.tools import tool
2import subprocess
3
4@tool("run_tests")
5def run_tests(path: str = "tests/") -> str:
6 """在給定路徑下執行 pytest 測試套件並回傳結果。"""
7 result = subprocess.run(
8 ["pytest", path, "-q"], capture_output=True, text=True, timeout=120
9 )
10 output = result.stdout + result.stderr
11 return output[-4000:] if len(output) > 4000 else output

規劃長期運行的任務

隨著任務變得越來越複雜,單純的執行迴圈開始偏離最初的目標。在足夠多的工具呼叫、檔案讀取和中間結果之後,上下文會被填滿,目標也會被後續發生的所有事情擠壓殆盡。

這種緩慢的退化現象,人們稱之為上下文腐化。

規劃直接解決了這個問題。Agent 在執行任何工作之前,會先建立一個逐步的計畫,並在整個執行過程中將該計畫保留在上下文中。

這個計畫本身並不執行工作。它是一張路線圖,讓模型與最初的目標保持連結,這與 Claude Code 的待辦事項清單所扮演的角色相同。

Akshay 🚀 - inline image

CrewAI 透過在 crew 層級設定 planning=True 來加入這個功能。它會在執行前產生一個計畫,並在任務進行過程中保持可用。

python
1from crewai import Crew, LLM
2
3crew = Crew(
4 agents=self.agents,
5 tasks=self.tasks,
6 planning=True,
7 planning_llm=LLM(model="gpt-4o-mini"),
8)

注意:預設情況下,CrewAI 使用 gpt-4o-mini 進行規劃,你可以替換成任何你偏好的 LLM 來執行此步驟。

個別 Agent 也可以透過設定 reasoning=True 來推理自己的工作:

python
1from crewai import Agent
2
3bug_fixer = Agent(
4 role="Bug 修復者",
5 goal="在程式碼庫中找出報告的錯誤,並描述修復方法。",
6 backstory="你透過讀取目錄和檔案來建立對程式碼的準確理解。",
7 tools=[FileReadTool()],
8 reasoning=True,
9 max_reasoning_attempts=3 # 可選:設定最大推理嘗試次數
10)

規劃和推理解決的是不同的問題。規劃為整體任務建立一個高層次的路線圖,而推理則給予單個 Agent 時間來思考自己的方法,然後再行動。

當啟用推理時,Agent 會:

  1. 反思任務並草擬執行計畫。
  2. 評估計畫是否準備就緒。
  3. 如有必要,完善計畫,直到滿意或達到 max_reasoning_attempts。
  4. 在執行前將最終確定的推理計畫注入任務中。
Akshay 🚀 - inline image

兩者結合,能讓 Agent 在長期運行的任務中保持專注,並減少偏離原始目標的情況。

透過子代理進行委派

規劃能讓 Agent 保持專注,但它並不能減少模型必須持有的資訊量。在大型程式碼庫上,即使是一個規劃良好的任務,也可能超出單個上下文視窗的容量。

找出一個錯誤可能需要讀取數十個檔案,而主 Agent 不需要將所有這些檔案都保留在記憶體中。

子代理透過委派解決了這個問題。主 Agent 將一個特定任務交給一個輔助 Agent,輔助 Agent 在自己的上下文中工作,並回傳一個簡短的摘要。主 Agent 看到的是結論,而不是中間步驟。

Akshay 🚀 - inline image

CrewAI 透過階層式工作流程來支援這一點,其中一個管理員 Agent 將任務委派給專業 Agent,並組合它們的結果。

在我們之前的設定中,一個 Bug 修復者 Agent 完成了所有繁重的工作。現在讓我們將工作分配給一個管理員和三個專業 Agent:

  • 程式碼庫探索者 探索程式碼並繪製儲存庫地圖。
  • 軟體工程師 實作請求的變更。
  • 測試執行者 在沙盒中執行測試並報告通過或失敗。
  • 工程主管 監督這三個專業 Agent。
Akshay 🚀 - inline image
python
1from crewai import Crew, Agent, Task, Process
2
3explorer = Agent(
4 role="程式碼庫探索者",
5 goal="繪製儲存庫地圖,並找出與任務相關的檔案。",
6 backstory="你透過讀取目錄和檔案來建立對程式碼的理解。",
7 tools=[read_file, list_dir],
8 llm=llm,
9) # 其他兩個專業 Agent 設定相同
10
11manager = Agent(
12 role="工程主管",
13 goal="將請求分解為步驟,並將每個步驟委派給合適的專業人員。",
14 backstory="你決定誰做什麼,審查測試,並在變更完成後結束任務。",
15 llm=llm,
16 allow_delegation=True,
17)
18
19crew = Crew(
20 agents=[explorer, coder, tester],
21 tasks=[task],
22 manager_agent=manager,
23 process=Process.hierarchical,
24)

需要注意的一點是,allow_delegation 預設是停用的,因此必須在管理員 Agent 上明確啟用。

沙盒化:確保 Agent 執行的安全

一個具有 Shell 存取權限的 Agent 可以執行破壞性指令,而告訴模型不要做某件事並不是一個安全措施。

真正的保護來自兩個層次:

  1. 一個權限系統,要求對敏感操作進行審批。
  2. 一個沙盒,隔離執行環境,使得即使經過批准的指令也無法觸及主機。

Anthropic 使用相同的方法。將程式碼執行移到沙盒中,可以減少使用者需要審批操作的頻率,同時仍然保護主機系統。

Akshay 🚀 - inline image

在 CrewAI 中進行沙盒化

在沙盒內而不是在主機上執行程式碼,就是應用第二層保護。在此設定中,程式碼在 E2B 內部執行,它會為每個工作階段啟動一個全新的虛擬機器,並在之後銷毀它。

Shell 命令和 Python 程式碼完全在該隔離環境中執行。

Akshay 🚀 - inline image
python
1from crewai_tools import E2BExecTool, E2BPythonTool
2sandbox_tools = [E2BExecTool(), E2BPythonTool()] # 執行測試 / 執行程式碼

人機迴圈審批

在 Task 上設定 human_input=True 會讓 crew 在產生答案後暫停。你審查輸出,然後批准它或將其送回進行另一次迭代。

當執行到達該任務時,CrewAI 會透過標準輸入等待你的回饋。

python
1from crewai import Task
2
3task = Task(
4 description=(
5 "在工作目錄 ./workspace 中,{objective}。"
6 "先探索程式碼,進行變更,然後執行測試並報告。"
7 ),
8 expected_output="一份關於已變更檔案和最終測試輸出的摘要。",
9 human_input=True,
10)

如果你的 crew 在 Web 應用程式或聊天介面(而非終端機)背後運行,CrewAI 基於 webhook 的人機迴圈系統會處理相同的審查步驟。

記憶與檢查點

預設情況下,Agent 在一個運行結束後會忘記所有事情。明天回來修復同一個專案的另一個錯誤時,它會從零開始。

有兩種機制可以讓 Agent 跨運行攜帶資訊,每種機制都有不同的用途:

  • 檢查點 在運行期間保存 Agent 的狀態,以便它在中斷後可以恢復,或者從同一點沿著不同的路徑繼續。
  • 持久化記憶 跨不同的對話儲存事實,包括像是「總是在完成前格式化最終程式碼」這類的專案偏好。
Akshay 🚀 - inline image

CrewAI 中的記憶

CrewAI 提供了一個統一的 Memory 介面,而不是分開的短期、長期、實體和外部記憶類型。在儲存時,它會使用 LLM 來識別重要細節、組織它們,並使其在之後可以檢索。

在 crew 上設定 memory=True 會賦予其跨運行的記憶能力。在每個任務之後,CrewAI 會從輸出中提取有用的事實並儲存起來;在未來的運行中,它會檢索相關的記憶並將其添加到任務提示中。

Akshay 🚀 - inline image
python
1from crewai import Crew
2
3crew = Crew(
4 agents=[explorer, coder, tester],
5 tasks=[task],
6 memory=True,
7)

一個 crew 中的所有 Agent 共享其記憶,除非某個 Agent 被賦予自己的記憶。

CrewAI 中的檢查點

檢查點是 Agent 進度的快照,包括其配置、任務狀態、記憶、中間結果、輸入和執行歷史。

預設情況下,CrewAI 會在每個任務完成時建立一個檢查點,允許工作流程在發生中斷時從該點恢復。

檢查點可以存放在兩個內建的儲存中:

  • JsonProvider 將每個檢查點儲存為單獨的 JSON 檔案,易於閱讀和手動檢查。
  • SqliteProvider 將所有檢查點儲存在單個 SQLite 資料庫中,在高頻檢查點和較大工作負載下表現更好。
Akshay 🚀 - inline image
python
1from crewai import Crew
2
3crew = Crew(
4 agents=[explorer, coder, tester],
5 tasks=[task],
6 checkpoint=True,
7)

Crew、Flow 和 Agent 都接受一個 checkpoint 參數,並且子項會從其父項繼承,除非它們設定自己的值。

整合在一起

以下是完整工具在一個任務上的運作方式,結合了執行迴圈、工具、規劃、子代理、沙盒化和記憶:

python
1from crewai import Agent, Crew, LLM, Process, Task
2from crewai.tools import tool
3from crewai_tools import (DirectoryReadTool, FileReadTool, FileWriterTool,
4E2BExecTool, E2BPythonTool)
5
6llm = LLM(model="anthropic/claude-sonnet-4.6")
7
8list_dir = DirectoryReadTool(directory="./workspace")
9filesystem_tools = [FileReadTool(), FileWriterTool(), list_dir]
10sandbox_tools = [exec_tool, E2BPythonTool()]
11
12@tool("run_tests")
13def run_tests(path: str = "tests/") -> str:
14 """將 ./workspace 同步到沙盒,然後在那裡執行 pytest。"""
15 return E2BExecTool().run(command=sync_and_test_command(path))
16
17explorer = Agent(role="程式碼庫探索者", goal="繪製儲存庫地圖,找出相關檔案。",
18 tools=[read_file, list_dir], llm=llm)
19coder = Agent(role="軟體工程師", goal="實作請求的變更。",
20 tools=filesystem_tools, reasoning=True, llm=llm)
21tester = Agent(role="測試執行者", goal="在沙盒中執行測試,報告通過/失敗。",
22 tools=sandbox_tools + [read_file] + [run_tests], llm=llm)
23manager = Agent(role="工程主管", goal="委派步驟,測試通過後結束。",
24 allow_delegation=True, llm=llm)
25
26task = Task(
27 description="在 ./workspace 中,{objective}。探索、編輯、測試、報告。",
28 expected_output="變更摘要和測試輸出。", human_input=True,
29)
30crew = Crew(
31 agents=[explorer, coder, tester], tasks=[task],
32 manager_agent=manager, process=Process.hierarchical,
33 planning=True, memory=True, checkpoint=True,
34)
35result = crew.kickoff(inputs={"objective": "修復 account.py 中失敗的測試"})

當成功可以被自動檢查時,評估 Agent 工具是最容易的。測試套件為 Agent 提供了一個具體的目標,讓它可以規劃、編輯、測試和重複,直到所有測試都通過。

因此,我們針對一個小型程式碼庫進行了測試,該程式碼庫包含一個帶有兩個真實錯誤和五個測試的 BankAccount 類別,其中三個測試失敗。規則規定只能修復實作,不能修改測試。

這反映了 Anthropic 內部評估編碼 Agent 的方式。一個已發布的範例中,Claude 針對一個大型失敗測試套件,重建了 claude.ai 介面的克隆。

在這裡,該工具將專案從 3 個失敗、2 個通過,推進到全部 5 個通過,而「僅限實作」的規則堵住了編輯或刪除失敗測試的捷徑。

Akshay 🚀 - inline image

仍然需要你負責的部分

系統的某些部分並非框架為你建構的:

  • 提示詞。 每個 Agent 的行為來自其角色、目標和背景故事。要讓這些設定正確,需要測試和迭代,沒有任何配置標誌可以替代這項工作。
  • 執行環境。 沙盒,無論是 E2B 還是自行管理的 VM,都必須進行設定和連接。
  • 工具選擇。 每個 Agent 獲得哪些工具,以及哪些 Agent 應該有權存取什麼,是一個框架不會為你做出的設計決策。

工具本身也帶有成本。規劃、子代理和迴圈都會增加 API 呼叫,因此一個複雜的 Agent 設定最終可能比一個單一模型呼叫就能直接解決的任務更加昂貴。

還有一個長期的限制值得牢記。隨著模型改進,一些支架變得不再必要,因為今天建構到工具中的一些東西,是為了應對當前模型限制的權宜之計,而不是永久性的需求。

Anthropic 最初使用上下文重置來防止 Claude Sonnet 4.5 過早結束任務,而功能更強大的 Claude Opus 4.5 不再需要這個功能。

Akshay 🚀 - inline image

總結

這就是整個發現。編碼 Agent 的能力主要存在於工具中,而一個編排框架提供給你的工具比你預想的要多。

迴圈、規劃、委派、沙盒化和記憶都以配置的形式提供,而提示詞、執行環境和工具選擇則仍然是你需要負責的部分。

如果你想在自己的程式碼庫上運行這個,CrewAI 文件涵蓋了此處使用的每個功能,而且該框架是完全開源的。

查看 CrewAI 文件 →

在此處找到所有程式碼 →

感謝閱讀!

乾杯! :)

一鍵儲存

使用 YouMind AI 深度閱讀爆款文章

保存原文、追問細節、總結觀點,並在一個 AI 工作空間裡把爆款文章沉澱成可複用筆記。

了解 YouMind
寫給創作者

把你的 Markdown 變成乾淨的 𝕏 文章

圖片上傳、表格、程式碼區塊,往 𝕏 上手動重排太痛苦。YouMind 把整篇 Markdown 一鍵轉成乾淨、可直接發佈的 𝕏 文章草稿。

試試 Markdown 轉 𝕏

更多可拆解樣本

近期爆款文章

探索更多爆款文章