跳到主要內容

【2026 最新】Paperclip 審查卡住怎麼查?五步驗收 Review → Approval 與狀態回寫

最後更新: ·
Paperclip 審查卡住 教學首圖

Paperclip 審查卡住:Agent 已留言「完成」,Review 看起來也過了,Approval 卻沒動。你再叫它做一次,它又交出同一句話。問題可能出在留言之後的狀態回寫,也可能只是你看錯了目前的關卡。

這篇寫給第一次維運 Agent 工作流、願意複製幾行指令的讀者。你會學會沿著四張收據找卡點,並用一張不碰正式資料的任務驗收 Review → Approval。以下依截至 2026 年 10 月 7 日的官方文件與固定原始碼設計排查方法;示意流程與故障注入是給你執行的測試規格,並非 AlphaLab 已完成的 Paperclip 跑次。

先說結論:Paperclip 審查卡住,先查四張收據

流程完成=有權的角色提出決策+伺服器保存狀態+下一關接手+外部成果對帳。把它想成包裹:店員說寄了、物流收件、主管簽收、買家拿到貨,各有一張紀錄。留言只是第一張。

  • 留言收據:誰在什麼 run 留下 verdict(審查結論)?
  • API 收據:狀態請求是否真的送出、回什麼 HTTP 與錯誤內容?
  • Stage 收據:目前關卡、參與者、決策 ID 與結果是否改變?
  • 外部收據:若交付包含 GitHub PR,另查測試、核准與合併狀態。

這個區別也是 Agent Harness 的核心:模型負責提出動作,執行層負責權限、狀態與紀錄。補一句更強的提示詞,仍需由後三張收據驗證。

先分清楚:Issue 狀態、Stage 與 Board 是三層

Issue 是任務單;Stage 是任務內的審查關卡;Board 是具有管理權限的人類操作身分。官方 Execution Policy 說明執行者提交完成後,系統可先送到 Review,再送到 Approval。兩關都可能顯示 in_review;這個標籤本身無法告訴你現在等誰。

真正的路線要看 executionState.currentStageType、currentStageId、currentParticipant 與 lastDecisionId。它像地鐵站內的月台編號:都叫「站內」,但去向不同。固定 commit 的官方測試 也逐項檢查 reviewer 核准後指向 approval、核准者接手,最後才完成。

Approval Stage 可以指定 Agent 或使用者;不要把名字裡的「approval」自動理解成 Board 的所有管理操作。驗證文件 區分 Agent token 與 Board 身分,驗證成功後仍有公司與路由權限。審查者有權推進自己的關卡,不代表它可停止所有 Agent 或替人類做管理決策。

建立最小驗收任務:先固定版本與路線

先用你已有、獲授權的測試 Paperclip 環境,準備一位執行者、一位 reviewer,以及一位有權登入的人工 approver。任務只要求「替假資料文件補一句說明」,不要接正式部署、付款或 PR 合併。保存已安裝版本、Adapter 類型、engine、執行政策與測試日期;不同版本的截圖、CLI 與回應要分開。

在新任務的 Reviewer 與 Approver 選擇對應角色,建立後重新讀取 executionPolicy.stages,確認順序與參與者真的保存。若用 API 建立,Issues API 提供 POST /api/companies/{companyId}/issues;填真實測試角色 ID,並由具有派工權限的人操作。空白或填錯的參與者應在開始前修正。

Paperclip 官方介面測試素材:Issue 側欄中的 Reviewers 與 Approvers 欄位
欄位位置示意,官方專案固定 commit 的介面測試截圖裁切;依 MIT 授權使用。這是測試素材,不是本文執行結果;你的版本外觀可能不同。
  • 執行者提交:預期送往 Review,Issue 為 in_review。
  • reviewer 核准:預期換到 Approval;Issue 仍可為 in_review。
  • reviewer 要求修改:預期回到原執行者 in_progress,關卡結果為 changes_requested。
  • 最後 approver 核准:預期 executionState.status=completed,Issue 才到 done。
Paperclip 審查卡住:Review 與 Approval 共享 in_review,但必須驗證關卡轉移
驗收路線示意:相同 Issue 狀態可能代表不同關卡,判讀時要同時看參與者與決策。

Paperclip 審查卡住的五步排查

① 找「在哪裡跑」:檢查 Adapter 子程序

為什麼主機有 token,Agent 卻說找不到?檢查同一個 run 的工具程序。Adapter(把 Paperclip 接到執行工具的轉接層)可能傳入部分變數;主機、Agent 父程序與 shell 是不同位置。不要用主機終端的成功代替子程序的結果。

請在該 run 裡只印是否存在:python3 -c 'import os; print({k: bool(os.getenv(k)) for k in ["PAPERCLIP_API_URL","PAPERCLIP_API_KEY","PAPERCLIP_RUN_ID","PAPERCLIP_TASK_ID"]})'。True 只代表有值,不代表 token 有效;接著要做唯讀身分查詢。保留布林結果,不把憑證或完整環境寫進留言。

2026 年 10 月 1 日的回報 #14837 描述兩個 Canary 版本中,codex_local 的 shell 缺控制變數,且包含清理暫存檔的命令遭拒。這是該使用者對特定部署的觀察,不能直接推成你今天的版本。先保存自己的拒絕訊息與 Adapter 路徑,再交給維護者定位。

② 查「我是誰」:用唯讀 API 驗證身分

變數都有,為什麼狀態仍寫不回?先驗身分與公司範圍。在同一個 Agent run 中,確認 URL 指向測試主機,再跑以下起手式。${VAR:?訊息} 是 shell 的缺值停止檢查,避免空 token 意外走到別的身分路徑。

curl --silent --show-error --max-time 20 -H "Authorization: Bearer ${PAPERCLIP_API_KEY:?missing token}" -H "X-Paperclip-Run-Id: ${PAPERCLIP_RUN_ID:?missing run}" "${PAPERCLIP_API_URL:?missing base}/api/agents/me" -o agent-me.json -w "HTTP %{http_code}\n"

這段假設 base URL 是測試伺服器根位址、curl 已存在,而且該 Agent run 被授權讀取自己的身分。依 官方 Agent 驗證範例 核對回應中的 Agent/company,再用 GET /api/issues/{issueId} 看測試任務。20 秒是本文選的單次診斷上限,不是服務保證;回應檔可能含內部資料,只留在受控測試目錄。

③ 查「有沒有送出」:分開命令拒絕與 HTTP 拒絕

看見「權限錯誤」就要放寬所有權限嗎?先定位拒絕層。工具若在建立程序前拒絕命令,這次根本沒有 API 回應;若 curl 已收到 HTTP,才往伺服器的身分、可見範圍、run lock 與 Stage 角色查。把工具錯誤、curl 結束碼、HTTP 與回應內容分欄保存。

Paperclip 的 Codex Adapter 文件 區分 engine、env 與權限配置。測試時明確保存 dangerouslyBypassApprovalsAndSandbox=false,核對實際 engine 的行為;這不是保證每個 engine 使用相同政策。若有限權限令無人值守操作被拒,應調整獲授權的 API 路徑或轉人工,不把全面 bypass 當排查結果。

Issues API 的拒絕契約 將 403 可見範圍/角色邊界與 409 run lock 等原因分開,回應也可能帶 details.code、whoCanAct 與 sanctionedPath。HTTP 422 要配合錯誤內容查目前參與者與輸入;只看數字猜原因,會把填錯參數與越權混在一起。

④ 查「留下了什麼」:一次提交狀態與決策留言

留言有「Approved」,為什麼沒換關?把決策提交到狀態端點。依官方文件,當前 reviewer 或 approver 以 PATCH /api/issues/{issueId} 提交 {"status":"done","comment":"Reviewed: test artifact and acceptance checks passed."};runtime 再決定換關或結束。單獨新增留言,驗的是溝通,還缺 Stage 轉移證據。

在測試目錄先把上面的 JSON 保存為 decision.json。確認測試 Issue ID 與目前角色後,由該 run 執行:curl --silent --show-error --max-time 20 -X PATCH -H "Authorization: Bearer ${PAPERCLIP_API_KEY:?missing token}" -H "X-Paperclip-Run-Id: ${PAPERCLIP_RUN_ID:?missing run}" -H "Content-Type: application/json" "${PAPERCLIP_API_URL:?missing base}/api/issues/${PAPERCLIP_TASK_ID:?missing test issue}" --data-binary @decision.json -o decision-response.json -w "HTTP %{http_code}\n"。這一步會修改指定任務;先核對 ID,別拿正式任務試。

同時核對目前 run 的 checkout/執行歸屬。若 API 回 409,先查哪個 run 持有任務,再走獲授權的恢復路徑;不要用新 run 強行覆蓋,也不要把身分驗證成功當成已取得寫入權。

要退回修改,將 JSON 的 status 改為 in_progress,comment 寫出具體未通過項目。若 response 不明、斷線或逾時,先重新 GET 任務,確認是否已保存再決定重試;本文示範不包含自動重試與去重邏輯,不能把同一份 PATCH 無限重送。

⑤ 查「下一關接到沒」:對照前後狀態

HTTP 成功,但畫面沒動怎麼辦?比較前後快照。把原 Stage ID、participant、lastDecisionId 和讀取時間,與 PATCH 後重新 GET 的結果對齊。Review 通過時,要看到原 review 在 completedStageIds、決策 outcome 為 approved、currentStageType 轉 approval,且 participant 換成核准者。這是本文依官方狀態模型提出的驗收清單。

若只看到新 comment ID,Stage 還是原值,沿 API 收據回查。若 Stage 已換,畫面仍舊,就保存 API 與 UI 的時間差,查顯示更新;若 Stage 已是 approval,則查真正的 approver 是否待命。不要只憑 Issue 還叫 in_review 就重派 reviewer。

三種故障注入:先證明你抓得到錯誤

另建可重置任務,每輪只改一項,保存相同四張收據。這是你可執行的診斷設計,不預填不存在的測試結果。

  • 缺少憑證:在獨立測試程序移除 API key,用上述缺值檢查。應停在送出前;若意外變成 Board 身分,立即停測、保存身分紀錄並修正路徑。
  • 命令被拒:使用你已設定的有限工具政策,測試一個明確不允許且不具外部副作用的操作。保留工具拒絕證據,再測允許的唯讀 API;不要為了重現而跑刪檔命令。
  • 只寫留言:在測試 Issue 新增 Approved 文字,重新讀 Stage;接著由當前參與者提交有效決策,對照前後差異。成功條件是辨認兩種收據,而不是讓留言自動等於核准。

收據可採 issue_id / run_id / actor / before_stage / request_time / HTTP / after_stage / decision_id / outcome。保存回應原檔與去敏摘要;憑證、私人文件與不相關個資不放進任務留言。若想把它接成自動驗收,可接著讀 Harness 最小實作 與 Agent 回歸測試。

人工升級、逾時與停止:不要讓恢復變成越權

先訂一個適合你的觀察期限,例如本文練習用 5 分鐘;這是人工值班規則,不是 Paperclip 固定 timeout。逾時後保存快照,由負責人決定修憑證、重新派工、縮小範圍或停止。到 Inbox → Blocked 查看待決策、恢復任務或 paused owner 等原因,並寫明誰能解卡。Blocked 是待處理的狀態,不是已核准。

反覆要求修改另有機制:截至查核日,官方文件說明 maxReviewRounds 可限制連續 Agent 退件;具備 responsibleUserId 或 createdByUserId 的任務,在達上限時交由該人接手。人類接手與單次 run 逾時是兩個條件;測試前讀回政策,測試後核對 participant,別以為時間到就必定自動升級。

練習結束,由有權的操作者停止相關測試執行,撤銷不再需要的測試憑證與外部連線授權,確認沒有殘留排程。#15292 提出可稽核 Board CLI 的需求;本文將其中的命令視為提案內容,不當成已交付操作。尤其不要藉由移除 Authorization,偷偷把 Agent 請求改成管理者身分。

若日後把任務接到 GitHub,最後另查 PR 的 merged、merged_at 與 merge_commit_sha,並核對實際目標分支。GitHub PR API 提供這些欄位。Paperclip 的 done 與 GitHub 合併各有紀錄;你若交辦的是「提交 PR 等人核准」,PR 尚未合併反而可能符合原本交付範圍。

FAQ:Paperclip 審查卡住的八個快答

1. Agent 說完成,可以直接結案嗎?

先對帳。核對 API、Stage 與交付物,留言只是一份審查說明。

2. Review 過了,還是 in_review,是故障嗎?

不一定。Approval 也可處於 in_review;看 currentStageType 與 participant。

3. 看得到任務,就有權推進審查嗎?

還要核對角色。官方 Execution Policy 限制目前關卡由 currentParticipant 決策;一般欄位操作與關卡權限要分開。

4. 看到 422,代表 token 壞了嗎?

先讀錯誤內容。它可能是關卡參與者或輸入問題;再查身分與目前 Stage。

5. 缺環境變數,可以貼永久 token 給 Agent 嗎?

先修傳遞路徑。確認該 Adapter 支援的配置與限定憑證範圍,避免把管理者權限塞進審查者上下文。

6. PATCH 逾時,要立刻重送嗎?

先重新讀任務。伺服器可能已寫入;用決策 ID 與狀態確認,再選恢復方式。

7. Board 核准後,GitHub 一定合併了嗎?

要另查 PR。批准、執行合併與分支更新各有自己的紀錄。

8. 沒有測試環境,今天能先做什麼?

可以先整理既有 run 的四張收據與版本資訊,做唯讀排查;把狀態修改與故障注入留到獲授權的測試任務。

給新手的三個重點

  • 先找證據在哪一層斷:子程序、HTTP、Stage、外部結果依序查。
  • 一次只改一項:固定版本、角色與假資料,讓差異有原因。
  • 保留人類控制:讓有權者處理升級與停止,把恢復過程也留下紀錄。

接著閱讀

左右滑動查看更多推薦

下一步:交出第一份能定位卡點的收據

今天先選一張測試任務,保存 Review 前後的 Issue 與 executionState,再交一份含具體 comment 的決策;看到 Approval 接手後,讓指定的人核准。最後回答四個問題:誰說完成、伺服器收到了什麼、下一關等誰、外部成果在哪裡?這就是「有權決策+保存狀態+接手+對帳」。想把這套方法擴成可維護的 AI 系統,可到 AlphaLab 課程 安排下一段實作。

更多執行層的權限與停止設計,可接著讀 Agent 執行控制,或回到 AlphaLab AI 專區 選擇下一個主題。

ALPHALAB 社群

有問題?來 Telegram 聊

和 Terry、編輯、其他網友一起討論這篇文章。提問、分享觀點,回覆更即時。

加入 Telegram 討論

📩 訂閱 AlphaLab 電子報

每週最多三封:一封 Weekly 週報與最多兩封關鍵 Alpha Signal。

我們不會 spam,隨時可退訂。已訂閱?管理主題偏好(會寄登入連結到你的信箱)