在過去將近一個月的時間裡,我們從零碎的抓取腳本出發,一步步建構出一套具備多代理人審查、狀態機推演、雲端同步、自動降級重試與戰情檢視器的情報雷達系統(Intelligence Radar)。
在鐵人賽即將抵達終點的倒數第二篇,我們暫時抽離繁瑣的語法與錯誤排除日誌,站在純粹的軟體工程視角進行深度復盤:為什麼從 Day 1 開始,我們就堅持採用看似繁瑣的「六角架構(Hexagonal Architecture / Ports & Adapters)」?在面對極端脆弱、快速變遷的 AI 時代,它究竟為自主智能體系統帶來了哪些真正的底氣?
在當前的 LLM 應用開發圈中,最常見的架構反模式(Anti-Pattern)就是「PoC 腳本無限膨脹」:
[原始抓取/爬蟲] ──(同一個檔案)──► [寫入 Google Sheet / DB]
│
(混雜其中)
▼
[硬編碼的 Prompt 與特定模型 SDK (如 genai.Client)]
│
(再混雜其中)
▼
[解析回傳字串、格式化為 Markdown、打 Discord Webhook]
當系統處於 Demo 或單元實驗階段時,把所有東西寫在一個 main.py 確實最快。但一旦系統進入長期維運,就會迅速撞上三大災難:
gemini-2.0 過渡到 gemini-3.8)、廢除舊 API,或是需要改打 Anthropic / OpenAI 時,整份腳本從頭到尾都要大改。六角架構的核心哲學非常純粹:核心業務邏輯(Domain Core)必須處於系統中心,外部的一切(UI、資料庫、檔案系統、LLM API、訊息推播)都只是外掛的插頭(Ports)與插座(Adapters)。
在我們的情報雷達中,系統被嚴格拆分為三層:
+----------------------------------------------------------------------------------+
| 外部世界 (Driving & Driven Adapters) |
| |
| [Ingress Ports] [Egress Ports] |
| - Spark / HF Papers - Google Sheets |
| - ArXiv API - Obsidian Vault |
| - GitHub Trending - Notion API |
| │ - Discord Webhook |
| ▼ ▲ |
| +───────────────────────────────────────────────────────────────────+ │ |
| │ Application Services Layer (應用編排層) │ │ |
| │ - IntelligencePipeline (四階段狀態機編排) │──┘ |
| │ - Tenacity 指數退避執行器 │ |
| │ - 均勻節奏控速冷卻 (5 RPM 防禦) │ |
| +──────────────────────────────────┬────────────────────────────────+ |
| │ |
| ▼ |
| +───────────────────────────────────────────────────────────────────+ |
| │ Domain Core Layer (純粹領域核心層) │ |
| │ - IntelligenceItem (15 欄位核心資料契約,Pydantic V2) │ |
| │ - ItemStatus / DomainType (領域狀態與分類列舉) │ |
| │ - DataHarmonizer (量表標準化、時間與異構資料對齊轉換器) │ |
| +──────────────────────────────────┬────────────────────────────────+ |
| │ |
| ▼ |
| [Agent Reasoning Adapters] |
| - BaseAgent (重試/全域降級引擎) |
| - ReviewerAgent (初審守門員) |
| - DomainExpertAgent (指標與極限挑戰) |
| - SynthesizerAgent (二階跨界推演) |
| - EditorAgent (決策層精煉) |
+-----------------------------------------------------------------------------------+
models.py:定義系統的靈魂 IntelligenceItem。它只專注於資料的真實長相與不可妥協的合約(例如 verified_score 必須是 1~5 星級)。它不匯入任何 Google GenAI SDK,也不在乎資料最後是存在 Google Sheets 還是硬碟檔案。
harmonizer.py:純粹的對齊與轉換器。無論外部信源給的是 Unix 時間戳、字串日期,或是 LLM 輸出的 0~100 分,都在這一步由 scale_100_to_5 與容錯解析器吸收差異,確保進入領域核心的永遠是乾淨合規的標準物件。
pipeline.py:負責串接業務流程,推動條目經歷 PENDING ➔ ANALYZING ➔ PROCESSED / ARCHIVED / ERROR 的生命週期。
編排層不寫具體的 LLM 提示詞,只負責呼叫代理人介面、落實 12 秒均勻冷卻節奏,並在遭遇未捕獲異常時確保狀態安全轉移。
推理適配器(Agent Adapters):繼承自 BaseAgent,將特定提示詞與結構化輸出綁定到 Google GenAI SDK。
出口適配器(Egress Adapters):SheetsAdapter、ObsidianVaultAdapter、NotionSyncAdapter。它們各自專注於與第三方 API 或檔案系統溝通,彼此互不知曉對方的存在。
在這一個月的實戰除錯中,六角架構多次展現了防禦與隔離的威力:
gemini-3.8-flash 遭遇 429 每日限額耗盡,而舊型號 gemini-2.0-flash 突遭 Google 下線報出 404。pipeline.py 的編排邏輯!所有的改動僅限於 BaseAgent 的內部迴圈:加入全域黑名單 _exhausted_daily_models、原地 503 指數退避、並將降級鏈路平滑切換至 gemini-3.6-flash。整個上層業務感知為零。情境:原本情報雷達只將資料寫入 Google Sheets。到了第三週,我們需要同時輸出 Obsidian 雙鏈 Markdown 與 Notion 雲端資料庫。
架構價值:我們不需要重構任何既有的代理人或爬蟲程式碼。只需要遵照 EgressPort 介面,實作獨立的 ObsidianVaultAdapter 與 NotionSyncAdapter。核心管線處理完 IntelligenceItem 後,資料便能自由流向任何目的地,擴充新渠道的邊際成本趨近於零。
tmp_path 與 MagicMock,在完全離線的狀態下對 Obsidian 的 Frontmatter 轉譯、檔名合法化清洗,以及 Notion 的 2,000 字元切片與 API 異常處理完成了防禦型契約測試,全套測試在 0.12 秒內綠燈通過。從這套情報雷達的架構實踐中,我們提煉出適用於所有自主智能體(Agentic Systems)落地的四大通用法則:
合約優先(Contract-First & Separation of Concerns):
嚴格區分「領域模型(Domain Model)」與「LLM 輸出模型(Agent Schema)」。LLM 適合在 0~100 分的高維度區間進行精細扣分推理,但落盤儲存時必須由 Harmonizer 正規化為系統規範的 1~5 星級,絕不讓外部模型定義的資料型態污染領域核心。
模型零感知(Model-Agnostic Agents):
子代理人只負責業務專屬的 Prompt 與 Schema 定義,所有關於網路逾時、503 退避、429 配額偵測、雙模型降級與全域黑名單的容錯工程,通通收斂於抽象基底(BaseAgent)。
顯式狀態機轉移(Explicit State Machine Transitions):
不要讓 Agent 直接決定全域狀態。流水線必須擁有明確的狀態節點(PENDING ➔ ANALYZING ➔ PROCESSED / ARCHIVED / ERROR)。即使模型拋出未預期的崩潰,保險絲機制也必須確保條目被安全標記為 ERROR,杜絕任何幽靈卡死或管線阻斷。
防禦型節奏控制(Defensive Rate Regulation):
外部服務的速率限制(Rate Limits)是客觀物理規律。在單條目需要依序經過 4 個 Agent 的鏈路下,與其在撞牆後無休止重試,不如在各階段交接間主動插入勻速冷卻節奏(如 time.sleep(12)),以極低成本換取 100% 的運行可靠性。
六角架構並不是脫離實務的學院派理論,而是保護工程師在充滿變數的 AI 浪潮中不被外部依賴拖垮的防彈衣。透過將「資料契約」、「業務編排」、「模型推理」與「基礎設施適配」徹底分流,我們的情報雷達具備了隨插即用、自我修復與長效維運的工業級體質。
明天,我們將迎來這趟 30 天長征的最終完結篇:Day 30:「三十天馬拉松終局:打造永不休眠的個人智慧情報雷達(系統全景、交付與未來展望)」。我們將串聯這一個月來構建的所有模組,展示這座全自動情報要塞的完整運行全景!