iT邦幫忙

2026 iThome 鐵人賽

DAY 5
0

從今天開始動手

前四天都在講「為什麼」:agent loop 是什麼、harness 有哪些元件、為什麼選 Pi。今天開始動手——在 Windows 上把 Pi 裝起來、登入、交給它第一個真實任務,並且確認這台電腦的環境乾淨到可以拿來做實驗。

最後一點很容易被跳過,但後面三十天的數字能不能信,就看這一步。

我的環境

項目 版本
作業系統 Windows 11
Node.js 24.18
Pi Coding Agent 0.84.3
Shell Git Bash(Pi 在 Windows 上預設用它執行 bash 工具)
Python 3.13(受測專案用)

Pi 在 Windows 上會依序找自訂路徑、C:\Program Files\Git\bin\bash.exe、PATH 上的 bash.exe。多數人裝好 Git for Windows 就夠了。

安裝

Pi 是一個 npm 套件,官方文件(pi.dev)的 Quick start 第一行就是安裝指令:

Pi 官方文件的安裝指令

npm install -g --ignore-scripts @earendil-works/pi-coding-agent
pi --version

--ignore-scripts 會關掉相依套件的安裝腳本。Pi 正常安裝不需要這些腳本,關掉可以少一個被供應鏈攻擊的入口,順手加上就好。

安裝本身很快,十幾秒就結束了:

npm 安裝完成

那行 node-domexception 的 deprecated 警告來自相依套件,不影響使用,可以忽略。

先把 Pi 的家目錄搬離 C 槽

Pi 會把登入憑證、設定、所有 session 記錄放在自己的家目錄(預設是 ~/.pi/agent)。這個系列會跑上百次實驗,session 記錄會越堆越多,我的 C 槽空間又很緊,所以一開始就用環境變數 PI_CODING_AGENT_DIR 把它指到 D 槽:

[Environment]::SetEnvironmentVariable("PI_CODING_AGENT_DIR", "D:\pi-agent", "User")

設定完重開終端機,用過一次之後,這個目錄會長這樣:

D:\pi-agent\
├─ auth.json          登入憑證(千萬不要 commit 或外流)
├─ settings.json      預設 provider、預設模型
├─ models-store.json  模型清單快取
├─ bin\               Pi 自己下載的 rg.exe、fd.exe(下一節說明)
└─ sessions\          每個專案一個資料夾,每次對話一個 .jsonl

第一次啟動:Pi 自己把搜尋工具裝好了

進到專案目錄執行 pi,第一次啟動的畫面有兩件事值得注意:

第一次啟動 Pi

第一件是中間那四行:

fd not found. Downloading...
ripgrep not found. Downloading...
ripgrep installed to D:\pi-agent\bin\rg.exe
fd installed to D:\pi-agent\bin\fd.exe

Pi 發現電腦上沒有 ripgreprg)和 fd 這兩個搜尋工具,自己下載到它的家目錄裡。這是一個很典型的 harness 設計:agent 的效率很依賴「找檔案、搜內容」這兩件事,與其賭使用者的電腦上有沒有裝,不如自己準備好。這個細節在 Day13 會變得很重要——那天量「開不開搜尋工具有沒有差」時,agent 手上一直都有 rg 可以用,而那正是 Pi 在這一刻替它裝好的。

第二件是那段黃色警告:「No models available」。剛裝好的 Pi 還沒有任何可以呼叫的模型,得先登入。

登入

在輸入框打 /login,Pi 會讓你選登入方式——用帳號(訂閱方案)或用 API key——以及要登入哪一家服務商。

選擇登入方式

Pi 內建支援的訂閱方案有 Claude Pro/Max、ChatGPT Plus/Pro(Codex)和 GitHub Copilot。我選「Sign in with an account」用 ChatGPT 訂閱登入,照畫面指示完成授權後,回到終端機就能用了。

登入完成後,隨便打一句話測試:

登入完成後的第一次對話

幾個看得出來的資訊:

  • 最下面的狀態列寫著 (openai-codex) gpt-5.5 • medium:走的是 ChatGPT 訂閱(Codex),模型是 gpt-5.5,thinking level 是預設的 medium(Day16 會講這是什麼)。
  • 左下角的 $0.006 (sub) 是這次對話換算的費用,(sub) 代表是從訂閱額度扣,不是另外刷卡。
  • 中間那行黃色警告「Anthropic subscription auth is active」需要解釋一下:我之前也用 Claude 帳號登入過 Pi,Pi 偵測到之後提醒——透過 Pi 這種第三方 harness 使用 Claude 訂閱,用量會從 extra usage 扣、按 token 計費,而不是算在 Claude 方案的額度裡。這次實際用的是 ChatGPT,所以不受影響;但如果你打算用 Claude 訂閱跑 Pi,這行警告值得認真看。

登入後 settings.json 會記下預設值。我後來把預設模型改成 gpt-5.6-luna,這個系列的實驗全部用它:

{
  "defaultProvider": "openai-codex",
  "defaultModel": "gpt-5.6-luna"
}

想知道能用哪些模型:

pi --list-models codex
provider      model                context  max-out  thinking  images
openai-codex  gpt-5.3-codex-spark  128K     128K     yes       no
openai-codex  gpt-5.4              272K     128K     yes       yes
openai-codex  gpt-5.4-mini         272K     128K     yes       yes
openai-codex  gpt-5.5              272K     128K     yes       yes
openai-codex  gpt-5.6-luna         272K     128K     yes       yes
openai-codex  gpt-5.6-sol          272K     128K     yes       yes
openai-codex  gpt-5.6-terra        272K     128K     yes       yes
openai-codex  gpt-6-astra          272K     128K     yes       yes

我先用 gpt-5.6-luna:夠便宜(每百萬 input tokens 0.2 美元),而且刻意不是最強的模型。為什麼實驗要故意挑「不是最強」的模型,會在校準那篇講清楚。

第一個 session:修兩個 bug

我準備了一個很小的 Python 專案:一個 calc.py,裡面刻意埋了兩個 bug——apply_discount 回傳的是折扣金額而不是折後價,moving_average 少算了最後一個視窗。docstring 也刻意寫得很薄,bug 只能從測試失敗反推。

在專案目錄交代任務:

這個專案的測試沒過。請找出原因、修好,然後跑 python -m pytest 確認全部通過。

Pi 做了這些事:

bash(ls + pytest) → read × 3 → edit(一次修掉兩個 bug)→ bash(pytest) → 回答

第一次跑 pytest 是 3 過 2 失敗(這正是任務本身),讀完三個檔案後一次改好兩個地方,再跑一次 pytest 變成 5 個全過,然後回報。整個 session 5 輪模型呼叫、6 次工具呼叫、總共約 11,249 tokens,成本大約 0.002 美元

第一個 session 每一輪送出的 context

這張圖是從 session 記錄畫出來的:每根柱子是那一輪送給模型的 input tokens,下面標的是那一輪模型決定呼叫的工具。你可以看到 Day2 講的「每一輪都把目前為止的事整包重送」——柱子一輪比一輪高;從第四輪開始,前面重複的部分命中了 prompt cache(橘色),這部分的計價便宜很多。明天會把這份記錄一行一行拆開來看。

開始量測之前:先量環境

在裝好 Pi 的頭幾天,我遇到一個很難認的問題:請求間歇性失敗,但重試就會成功。因為 Pi 會自動重試,表面上看起來只是「有點慢」,很容易以為是服務商不穩定。

最後查出來跟 Pi、跟模型都無關:這台電腦上 VPN 軟體和虛擬機軟體裝的虛擬網卡,Windows 分給它們的優先權比 Wi-Fi 還高,而它們掛著一台解析不了外網的 DNS。所有對外請求都先去問那台 DNS、逾時、再退回正常的解析器。

診斷時有兩個指令很好用。先分段計時,看時間是不是卡在 DNS:

curl -s -o /dev/null -m 20 -w "dns=%{time_namelookup}s connect=%{time_connect}s total=%{time_total}s\n" https://目標網域

再看 Windows 先問哪張網卡(InterfaceMetric 越小越優先)、每張網卡各掛哪台 DNS:

Get-NetIPInterface -AddressFamily IPv4 | Sort-Object InterfaceMetric |
  Select-Object InterfaceAlias, InterfaceMetric, ConnectionState
Get-DnsClientServerAddress -AddressFamily IPv4 |
  Select-Object InterfaceAlias, InterfaceIndex, ServerAddresses

一般開發時,這種問題只是「慢一點」。但這個系列要量的指標裡就有「重試次數」和「成本」,如果環境每個請求都偷偷製造一次重試,這些數字就全變成雜訊。

所以我給自己訂了一條規則:**先量環境,再量系統。**修好 DNS 之後,我也在每次實驗的記錄裡保留 Pi 回報的傳輸層錯誤次數(session 裡的 provider_transport_failure)。它現在偶爾還是會出現一次,但至少會被記下來,而不是被自動重試悄悄吃掉。

明天

第一個 session 跑完了,Pi 在 sessions\ 底下留下一個 .jsonl 檔。Day6 會打開這個檔案,一行一行對照 Day2 的「看現況、想下一步、動手做、看結果」,看 agent loop 在真實記錄裡長什麼樣子,以及怎麼從裡面算出 tokens、成本和工具呼叫次數。


上一篇
Day4:為什麼選 Pi ? 啥都沒有為啥選它 ?
系列文
Harness Engineering × Pi Agent 實戰:打造可觀測、可評估的 AI Coding Agent5
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
lin1015
iT邦新手 5 級 ‧ 2026-09-19 18:29:27

把 session 拆成角色、stopReason、usage 之後,Agent loop 真的從黑盒子變成可量測資料了。我特別好奇 metrics.py 區分「工具本身失敗」和「傳輸層失敗」的規則:遇到 timeout 或非零 exit code 時,會怎麼避免誤分類?

謝謝提問!metrics.py 是 Day 6 拆解的,Day 5 只提到會保留 provider_transport_failure。

我沒有用規則去猜,是靠 Pi 在 session 記錄裡本來就分開的兩個來源:工具失敗來自 toolResult 的 isError,傳輸層失敗來自 assistant 訊息 diagnostics 裡的 provider_transport_failure。一個發生在「執行工具」、一個發生在「呼叫模型」,所以 timeout 算哪邊,取決於是哪一層逾時:模型自己帶的 timeout: 120 算工具失敗,Pi 的 HTTP 閒置逾時算傳輸層。

不過你點到一個真實的限制:非零 exit code 也會被計進 tool_errors(例如 agent 跑一次失敗的 pytest),所以它代表「工具回報了錯誤」,不是「工具壞了」。整次執行卡住的情況,則是在 runner 層另外判成基礎設施失敗,重跑而不計分。

我要留言

立即登入留言