監控裝滿卻沒人讀:human-in-the-loop 怎麼做才有效
《Agentic Design Patterns》第 13 章講人在迴路(Human-in-the-Loop)。核心一句話:不是每個決策都該自動化,要把人留在那些機器不該獨自拍板的點上。但這一章真正的門檻,藏在一個容易被跳過的地方:你為「人」準備的那個介面,人真的會讀嗎。
我們讀完,點頭。我們有護欄的軟警告 log、語意心跳的分數、錯誤分類、每筆呼叫的花費紀錄,全都乖乖寫進檔案等人來看。人在迴路,實作完成。然後我們對自己做了對抗式稽核,發現一件很難堪的事:機器記得勤勤懇懇,卻沒有一個人真的坐下來讀過那些 log。
監控裝滿,沒有一個人在迴路裡
攤開 ~/.openclaw/logs,裡面躺著四五個檔案:護欄放行但可疑的 guardrail.log、語意品質的 semantic-quality.jsonl、LLM 錯誤的 llm-errors.log、每筆呼叫花費的 llm-cost.log。每一個都在寫,每一個都沒人開。
這正是人在迴路的反面。書要你把人放在該介入的點,我們把訊號都收集好了,卻沒搭一個人願意主動打開的介面。護欄攔到可疑輸出、語意心跳掉分、帳單在燒,全是該由人判斷的時刻,但那個「人」從來沒被叫到現場。訊號淹沒在一堆沒人看的檔案裡,跟沒有訊號沒兩樣。
所以我們做了 review-digest:一支唯讀、按需執行、不推 TG 的複查面板,把那四五個散落的 log 彙整成一頁,硬擋標紅、軟警告標黃、語意掉分標紅、花費排出燒最多的前五名。它刻意不推播,因為人在迴路的介面不是「再多一個通知」,是「一個人願意自己打開的地方」。
另一個諷刺:告警洗版洗到人麻木
如果說第一個坑是訊號沒人讀,第二個坑正好相反:訊號多到沒人想讀。
我們有一支 Claude 的 Stop hook,tg-mirror-check.py,立意很好:你從 TG 問 Claude 一件事,Claude 在終端機答了、卻忘了鏡射回 TG,你手機上什麼都沒看到就默默掉了交付。這個 hook 每回合結束檢查一次,抓到就提醒你。
問題是它放在 ~/.claude/hooks,是所有 session 共用的。每個 Claude session 結束都 fire,包括跟 TG 無關的終端機 coding session,它們讀著同一份共用 TG log,替一則不屬於自己的訊息推給老闆一句「你剛剛沒鏡射喔」。純粹的跨 session 噪音。更糟的是它一開始沒去重,同一則沒鏡射的訊息每個回合、每個 loop tick 都重發,老闆大約每 5 分鐘收到同一句告警。
一個為了把人拉進迴路而做的告警,反而把人洗到麻木。到第三遍人就自動略過了,連真正重要的那一遍一起略過。這比沒有告警更危險,因為你以為有人在看。
先花幾分鐘查你自己的人在迴路
01 數一數:幾個「機器在記」,幾個「人真的會讀」 人在迴路的第一個破口,是訊號收集得很勤,卻沒有一個人真的會去看。先數你有幾個在默默寫的 log 或告警管道,再誠實回答其中幾個是你這週真的開過的。
# 你有幾個地方在默默寫 log/推告警
ls ~/.openclaw/logs/*.log ~/.openclaw/logs/*.jsonl 2>/dev/null | wc -l
# 這裡面,你這週真的坐下來讀過幾個?(誠實回答,多半是 0)
紅旗:你數得出一整排在寫的 log,卻答不出上次真的坐下來讀是什麼時候。機器在記,不等於人在迴路。
02 你的複查介面是給人讀的,還是寫完就沒人碰 寫進硬碟、沒人打開的 log 不算人在迴路。檢查你有沒有一個「把散落訊號彙整成一頁、人願意主動拉取」的介面,還是訊號散在八個檔各自為政,順手看那個 log 最後被讀取和被寫入差多久。
# 這個監控 log 最後被讀取 vs 最後被寫入,差多久
stat -c '讀 %x/寫 %y' ~/.openclaw/logs/guardrail.log
# 讀遠舊於寫 = 一直在寫、沒人在讀(atime 若被關,就改問自己有沒有複查面板)
紅旗:你沒有一個彙整成一頁、按需拉取的複查面板,訊號各自躺在不同檔案,要看得同時開八個。
03 你的告警會不會重複洗版 洗版是人在迴路的慢性毒。查你的告警是「每次觸發都發」,還是「去重加上只在狀態轉態(OFF→ON)時才發」,再看同一則告警在 log 裡實際重複了幾遍。順帶查共用的 hook 會不會在它不該出聲的場合 fire。
# 告警腳本有沒有去重/只在 OFF→ON 轉態才發
grep -niE 'dedup|already.?alert|last.?state|OFF.*ON|轉態|transition' your-alert.*
# 同一句告警在 log 裡被重複發了幾遍
sort alerts.log | uniq -c | sort -rn | head
紅旗:找不到任何去重或轉態判斷,同一則告警在 log 裡重複幾十遍,或一個共用 hook 在跟它無關的 context 也照發。
我們實際怎麼改
兩刀。第一刀,把散落的訊號收進 review-digest 這一頁:唯讀、按需跑、零噪音,一個指令把護欄、語意、錯誤、花費一次拉出來看完,刻意不推 TG。第二刀,2026-07-04 修那支洗版的 hook:加去重讓同一則漏鏡射只告警一次,再把 TG 推播整個關掉改成只寫 log,訊號留在 missed-mirrors.log,不洗老闆的版。
值得講清楚它不是什麼:review-digest 是真的做好、跑得動的,不是空殼。難堪的地方不在它,在它之所以要存在,是因為我們先堆了一座沒人讀的監控山,而那支 hook 又提醒過頭把人洗到不想讀。兩個坑是同一枚硬幣的兩面:訊號沒人讀,和訊號多到沒人想讀,都讓人在迴路名存實亡。
人在迴路體檢清單
對你自己的系統跑一遍:
- 你有幾個在默默寫的 log/告警,其中幾個是這週真的讀過的
- 有沒有一個把散落訊號彙整成一頁、人願意主動拉取的複查介面
- 那個介面是「等人來看」的零噪音面板,還是「一直推」的通知流
- 告警有沒有去重,是不是只在狀態轉態(OFF→ON)時才發
- 共用的 hook 會不會在跟它無關的 session/context 也 fire
- 同一則告警在 log 裡重複幾遍,人是不是已經開始自動略過
這一章的四句話
- 人在迴路的門檻不是「有沒有介面」,是「那個介面人真的會打開」。log 寫滿沒人讀,等於沒有人在迴路。
- 監控是給機器記的,複查面板是給人讀的。把散落的訊號彙整成一頁、按需拉取、零噪音,人才會真的去看。
- 洗版是人在迴路的慢性毒。同一則告警發到第三遍,人就開始自動略過,連真正重要的那一遍一起略過。去重,只在狀態轉態時發。
- 共用的告警會在它不該出聲的場合出聲。發之前先問一句:這一則,現在這個人該收嗎。
原始碼位置:~/.openclaw/scripts/review-digest.sh(唯讀、按需、零噪音的人工複查面板,彙整 Ch18 護欄/Ch19 語意/Ch12 錯誤/Ch16 花費,--diagnose 才動用 AI 根因)、~/.claude/hooks/tg-mirror-check.py(TG 鏡射漏發偵測,2026-07-04 加去重+關掉跨 session 推播改 log-only,訊號落在 missed-mirrors.log)。
這是《Agentic Design Patterns》× 龍蝦艦隊系列。我們照書把一人公司的 AI agent 艦隊系統化,然後對自己做對抗式稽核。宣稱做到的每一章,都被重新驗證過一次,也把查法和改法整理成你能照著跑的步驟。這個系列的可信度,來自我們願意公開自己打臉自己。