模型 / 資料集
hahhforest/pi-textbook avatar
hahhforest/pi-textbook

動手學 Pi:用 15 個 checkpoint 拆開一個 coding agent

《动手学 Pi》:沿 15 个真实 checkpoint 从零构建 Pi-style Agent

1,319 個 Star82 個 ForkTypeScriptMIT

秒懂

它是什麼?
這是一門把 Agent 執行鏈切成 15 段的中文教材,每段都對應一個可 checkout 的 commit。它教的不是怎麼呼叫模型,而是模型之外那圈東西怎麼接起來。
適合誰用?
如果你已經會寫 TypeScript,也想搞清楚 agent 的狀態、歷史與上下文預算到底怎麼運作,這門課的 checkpoint 00 到 14 值得從頭走一遍,先跑 npm run checkpoint -w @pi/course -- 05 看它定位出的 parent、target 與聚焦測試,再決定要不要 clone 課程分支。如果你要的是拿來就能用的 agent 框架,這裡沒有 npm 套件可以裝,README 也沒有檢索或 RAG 的章節,請直接看上游專案。
可以商用嗎?
可以。MIT 是寬鬆授權:你可以使用、修改並販售以它為基礎的軟體,只需保留著作權與授權聲明。
還在維護嗎?
有在維護。儲存庫最近一次提交在 55 天前。
用什麼語言寫的?
主要是 TypeScript(依據 GitHub 的語言統計)。

以上回答依據專案的 GitHub 資料(最近同步於 2026年9月15日)與我們的分析,不構成法律意見。

開源專案深度解析

它不是框架,是一條可以 checkout 的 Git 歷史

多數 agent 教學停在貼一段迴圈程式碼,讀者抄完仍然不知道工具結果要怎麼配對回模型、歷史要存在哪裡。動手學 Pi 換了一個做法:課程代碼本身就是一條 Git 歷史,從固定的上游 commit 8479bd84 出發,以 course(00) 到 course(14) 排列,每一章對應一個可運行的 checkpoint。README 的說法是「課程代碼不是偽代碼演示,而是一條可以 checkout、運行和驗證的 Git 歷史」。這句話決定了它的受眾。

它的目標讀者是已經寫得動 TypeScript、想理解 agent 內部結構的工程師,而不是想找一個現成 agent 來接進產品的人。課程從一條離線軌跡開始,逐步長出協定、模型、Provider、工具、迴圈、會話樹、上下文壓縮、擴充與評測。每一章由四部分組成:教材正文、真實 commit、聚焦測試、故障實驗。故障實驗這一項值得留意,它意味著課程會刻意讓某個環節壞掉,而不是只展示成功路徑。

需要先講清楚的是,這不是 Pi 官方出品。README 明講這是社區原創的非官方課程,不隸屬於或代表 Pi / Earendil Works。教材正文與原創媒體採 CC BY 4.0,應用與原創代碼採 MIT,Pi 上游代碼沿用其原授權與作者歸屬,細節分別在 LICENSE 與 LICENSE-CONTENT 兩個檔案。教材與課程代碼分屬兩個倉庫:pi-textbook 是 HTML 教材與網站,課程代碼在 pi 倉庫的 course/build-your-own-pi 分支下,實際路徑是 packages/pi-course/。

從一條離線軌跡長出整個 Agent 執行鏈

15 個 checkpoint 不是隨意切分的章節,而是沿同一條執行鏈逐層推進。序章 00 先跟著一次 README 讀取請求走完閉環:使用者訊息、兩次模型呼叫、工具呼叫與結果、最終回答。這一段不解釋抽象概念,只把一次真實往返攤開,讓後面每一章都有可以掛靠的位置。

第一部分處理模型與協定。01 用四個 DemoEvent 串起聯合類型、執行時校驗、Promise 與 ESM 測試;02 實作 EventStream,處理事件先到與消費者先等這兩種時序;03 把文字、工具呼叫與配對結果存成統一訊息;04 的 ScriptedModel 可以重複播放預設回合,並保存請求快照;05 負責在課程協定與 Provider API 之間轉換,把 SSE 回應還原成統一模型事件。這五章合起來解決的是一個很具體的問題:模型輸出是串流的、非同步的、格式還會變,你要用什麼中間表示把它接住。

第二部分是工具與迴圈。06 讓 echo 呼叫經過 schema、Registry 與 executor,回傳沿用原 call id 的工具結果;07 實作兩輪 Agent Loop,模型提出 read、工具結果寫回、再生成最終回答;08 讓 read、write、edit、bash 四個工具在同一個 workspace 內完成受控操作。第三部分轉向狀態:09 讓同一個 Agent 保存跨執行訊息,並管理訂閱、取消、執行中指令、follow-up 與重入;10 把完成訊息追加成帶父指標的 JSONL 記錄,再從指定葉子恢復當前對話路徑;11 按完整工具互動切分歷史,在 token 預算內保留後綴,並用結構化摘要補回早期事實。第四部分是 12 到 14:專案規則、Skill 與模板按需進入上下文,可信擴充原子註冊工具與 hooks,最後把這些接成 Runtime,並用全新 fixture 跑一套獨立評測。

checkpoint 與 practice 兩個指令的分工

閱讀教材本身不需要 clone 任何東西,直接打開線上教材即可。想在本地跑網站,README 給的命令是 git clone https://github.com/hahhforest/pi-textbook.git,接著 cd pi-textbook、npm install、npm run dev。這三步只會起教材網站,不會幫你準備課程代碼。

要動手做練習,得改抓課程分支:git clone --branch course/build-your-own-pi https://github.com/hahhforest/pi.git,cd pi,npm install。之後有兩個 workspace 指令。npm run checkpoint -w @pi/course -- 05 會定位本章的 parent、target 與聚焦測試;npm run practice -w @pi/course -- 05 ../pi-practice-05 則建立一個不含答案與 Git 歷史的練習目錄。兩者的差別在於,checkpoint 讓你站在已知正確的 commit 上看測試怎麼跑,practice 把答案抽掉,逼你自己寫。

README 建議把本章網頁、命令輸出與練習目錄中的 LEARNING.md 一起交給陪學 Agent。這是這門課比較特別的地方:它預設你身邊有一個 agent 可以討論。但如果你的目的是自己搞懂,LEARNING.md 加上聚焦測試其實已經構成一個閉環,陪學 Agent 只是可選項。

還有一個細節容易被忽略。課程分支用 pi-course-v1 與 course-v1/00 到 course-v1/14 這些 tag 固定第一版課程。這表示教材內容之後若修訂,舊版 checkpoint 仍然可以定位回當時的狀態,對於跟著寫到一半被打斷的人來說是必要的設計。

ScriptedModel 與離線軌跡的代價

04 章的 ScriptedModel 可以重複播放預設回合並保存請求快照,序章也從一條離線軌跡開始。這是整個課程能在沒有 API key、沒有網路的情況下穩定跑測試的原因,測試不會因為模型今天心情不同而紅燈。

代價是課程裡看不到真實模型的行為。Provider 轉接在 05 章處理,但那是把課程訊息寫成 Provider 請求、把 SSE 回應還原成統一模型事件,屬於格式轉換層。模型什麼時候會多吐一個工具呼叫、什麼時候會把參數寫成看起來合法但語意錯誤的 JSON、上下文被壓縮之後模型會不會突然忘記任務目標,這些都不在課程的驗證範圍內。14 章的評測用的是全新 fixture,跑的是 Runtime 的活動路徑與檔案結果,仍然是可重現的確定性檢查。

這不是缺陷,是範圍選擇。但如果你打算把課程裡的 Agent Loop 直接搬去接真實 Provider,請預期要自己補上這一段:錯誤重試、串流中斷、工具參數校驗失敗時的降級路徑。課程把協定與狀態機講清楚了,把不確定性留給了你。

上下文壓縮那章解決的是真問題

11 章的標題是「歷史不動,上下文按預算重建」,做法是按完整工具互動切分歷史,在 token 預算內保留後綴,並用結構化摘要補回早期事實。這是整門課裡最接近生產環境痛點的一章。

很多 agent 實作把對話歷史當成一條只增不減的陣列,等到撞上 context window 才開始丟最舊的訊息,結果工具呼叫與它的結果被拆散在不同位置,模型看到一個沒有對應結果的 tool call,行為就開始飄。這門課選擇以完整工具互動為切分單位,等於承認工具呼叫與結果是不可分割的原子。摘要則負責把被切掉那段的關鍵事實以結構化形式補回,而不是讓模型自己從殘骸裡猜。

值得追問的是摘要本身的品質由誰保證。README 沒有說明摘要用什麼產生、失敗時怎麼處理,只知道它是結構化的。如果你在意這條路徑的可靠性,這是要自己驗證的第一個地方。

它不處理的事,以及該看什麼替代品

這門課的範圍到 Runtime 與評測為止。README 列出的 15 章裡沒有檢索、沒有向量存儲、沒有多 agent 協作、沒有部署與可觀測性。它也不提供可以 npm install 的套件,你拿到的是教材與一條 Git 歷史,不是一個能掛進產品的依賴。

如果你的需求是後者,該看的東西不一樣。想直接跑一個現成 coding agent,就去看課程所依據的 Pi 上游專案本身,README 明確標示課程分支從上游 commit 8479bd84 出發,上游有完整的應用程式碼與自己的授權與作者歸屬。想學 agent 的抽象模式而不是某個具體實作的歷史,LangGraph 這類以圖結構描述狀態機的框架走的是另一條路:它把節點與邊當成第一級概念,你宣告流程,框架負責調度與狀態傳遞。動手學 Pi 反過來,它讓你親手寫出 EventStream、訊息中間表示與會話樹,代價是這些東西只存在於課程的型別定義裡,不具備跨專案的可攜性。

判斷標準很簡單:你要的是能用的東西,還是能自己造東西的能力。這門課只給後者。

維護成本與版本固定在誰身上

課程分支從固定上游 commit 8479bd84 出發,這件事同時是優點和負擔。優點是課程內容不會因為上游改動而突然失效;負擔是當上游繼續前進,課程與真實 Pi 的距離會逐漸拉開。pi-course-v1 與 course-v1/00 到 course-v1/14 這些 tag 把第一版課程釘死,等於承認未來會有第二版。

對跟著學的人來說,這意味著你不需要追蹤上游,只要在課程分支上按 checkpoint 走。對想貢獻的人來說,CONTRIBUTING.md 提到建置、測試與跨倉庫歷史校驗,跨倉庫三個字暗示教材倉庫與課程倉庫之間存在需要人工維護的一致性,教材改了而 checkpoint 沒改、或反過來,都是可能的破口。

授權方面,應用與原創代碼是 MIT,教材正文與原創媒體是 CC BY 4.0,兩者要求不同:前者寬鬆,後者要求署名。Pi 上游代碼沿用其原授權與作者歸屬。如果你打算把教材內容放進內部培訓材料,CC BY 4.0 的署名義務要自己確認清楚,這裡不構成法律意見。

編輯結論

如果你已經會寫 TypeScript,也想搞清楚 agent 的狀態、歷史與上下文預算到底怎麼運作,這門課的 checkpoint 00 到 14 值得從頭走一遍,先跑 npm run checkpoint -w @pi/course -- 05 看它定位出的 parent、target 與聚焦測試,再決定要不要 clone 課程分支。如果你要的是拿來就能用的 agent 框架,這裡沒有 npm 套件可以裝,README 也沒有檢索或 RAG 的章節,請直接看上游專案。動手之前先確認課程分支的 commit 8479bd84 是否仍與上游相容,以及 LICENSE 與 LICENSE-CONTENT 兩個檔案對你使用教材正文與程式碼的差別。

官方來源

  1. hahhforest/pi-textbook on GitHub
  2. Issues
  3. License: MIT
  4. Project website
  5. README
社群筆記

社群筆記