Nat 鍾承恩

作品 2026 / 06 約 4 分鐘

104 投遞代理人:從搜尋到追蹤壓成一條 pipeline

原始碼:https://github.com/NatChung/104-apply-agent

做什麼

這個 agent 做的事很具體:打開 104、照條件搜尋、評分排列、起草推薦信、送出表單、追回覆狀態。不是「AI 幫你找工作」的口號,是把五個重複動作——collectscoredraftapplypoll——串成一條有狀態的 CLI pipeline,讓重跑不重送、跳過的不會消失、回覆進度有地方記。

每一次跑完都留下可審閱的佇列。你核准了才送出;沒核准的繼續等在那裡。

為什麼這樣做

三個取捨貫穿設計,每一個都有對應的機制:

個人料不進 code。 關鍵字、地區、排除公司、評分詞表全在 config.yaml,履歷與定位放 profile/,兩者都 gitignored。repo 開源但個人料從未上傳——這是 config/code 分離不折不扣的實踐,而不是靠 prompt 叫 AI「記得不要說出去」。

投遞前必過人工閘。 review --approve 才推進到 apply,預設不自動送出。必填問答缺失的職缺自動標 needsQA 退回人工,不靜默跳過。agent 做的是整理與起草,判斷是我的事。

把 Cloudflare 擋掉的步驟委派出去。 collectrelatedapply 三個指令走 Claude Code 的 Playwright MCP 瀏覽器(已登入、CF-cleared);評分、起草、報告這些純資料步驟留在 headless script。哪些步驟可以自動、哪些需要已登入的瀏覽器——這條界線寫在架構裡,不是跑起來才遇到再想辦法。

三個決定加起來讓 repo 可以公開,同時讓 agent 在真實環境能穩定跑。

怎麼用·repo 導覽

環境需要:bun installbunx playwright install chromium、透過 MCP 瀏覽器匯出 104 登入態到 data/storageState.json。就緒後所有指令走 bun run 104 <cmd>

建議順序:先跑 doctor 確認環境完整;collect 透過 MCP 瀏覽器抓今日搜尋結果寫進 SQLite;review 在終端機列出待審佇列、逐一核准或標記;apply 送出已核准的項目;poll 定期追回覆狀態。

核心模組各司其職:score.ts 是確定性啟發式先篩,詞表加權評分並永遠帶 reasons[] 分項讓審閱頁可以攤開來看;store.ts 是 bun:sqlite 狀態機,seen / queue / history 三態加 WAL + transaction 防重送;draft.tstemplateLetter.ts 組成推薦信骨架加客製 hook,讓每封信有個人脈絡而不是一份模板複製貼上。

config.example.yaml 附有完整欄位說明;照著填、改成自己的條件、跑 doctor,通常十分鐘內能把第一批職缺跑起來。

背後的工程模式(CF 委派、確定性邊界、stdin 防注入)見擋住 agent 越權:把模型的弱點交給確定性 script;冪等餵入與防重投的三條防線見資料餵進去不會壞:idempotent ingestion 的三條防線