Agentic Research
首頁/模板/多 Agent 投研流水線:收集、分析、報告三段分工

多 Agent 投研流水線:收集、分析、報告三段分工

2026/09/3023 分鐘君澤智庫最後更新 2026/09/30

投研是典型的「長鏈條、多來源、要驗證」任務:一家公司要讀年報、翻公告、對市場數據、跑勾稽檢查、寫成報告;一個板塊要把這件事乘以二十。把整條鏈條塞給一個 Agent,它會在前半段還算聰明、後半段開始遺忘指令、遇到缺數時悄悄編一個補上——最後交出一份無法定位錯誤出處的長文。這不是模型不夠強,是任務結構與單 Agent 架構不匹配。

這篇文章把投研任務拆成收集、分析、報告三段流水線,給出每段的職責邊界與 input/output 契約、段間的結構化 JSON 傳遞格式、寫入範圍劃分、失敗隔離設計、驗證門控的擺放位置,以及成本與延遲的取捨框架。你會得到一張可以直接照抄的架構圖、三份 schema 範例、一份失敗模式清單。文中所有公司與數據均為虛構的教學示例。多 Agent 框架的具體操作可以配合 OMA 多 Agent 實戰教程,本篇處理的是設計層:為什麼這樣拆、段與段之間憑什麼互相信任。

一、為什麼單 Agent 做不完投研任務

四個結構性原因,每一個都無法靠「換更強的模型」解決:

1. 上下文容量與注意力稀釋。 一家公司的調研素材——年報關鍵章節、公告、行情數據、勾稽計算過程——動輒數十萬 token。即使塞得進超長窗口,實測經驗是:上下文越長,模型對中段資訊的檢索與遵守指令的能力越差。第 3 小時的「分析」早已忘記第 1 小時定下的口徑規則。

2. 職責混合導致錯誤不可定位。 單 Agent 邊收集邊推理邊寫作,輸出一段「應收帳款週轉天數異常拉長」時,你無法知道這個數字是抽取錯了、算錯了、還是編造的。三段拆分後,每段產出獨立落盤,錯誤可以精確定位到段與檔案。

3. 無法並行。 收集是 I/O 密集型工作(下載、抽取、比對),天然適合按標的並行;單 Agent 只能串行,板塊級任務的耗時不可接受。

4. 跨任務污染。 連續分析多家公司時,上一家的數據會滲進下一家的結論。這不是假想風險——本站記錄過一起真實事故:分析 A 公司時的基金減值數據,出現在隨後 B 公司的報告裡,而 B 公司根本沒有該業務(見 子代理隔離架構)。污染的根源是共享上下文,解藥是架構性的:每個標的獨立上下文、獨立寫入範圍。

反過來說,不是所有任務都該拆。單標的、單來源、一次性的快速問題(「這份公告說了什麼」),單 Agent 甚至單次提問就夠。拆分流水線的適用條件是:多標的或多來源、需要重跑、產出需要被驗證與追責。滿足兩條以上才值得付多 Agent 的複雜度成本。

二、三段分工:職責清單與「負面清單」

多 Agent 設計裡,定義每段不做什麼比定義做什麼更重要。職責清單決定產出,負面清單決定品質下限。

段輸入輸出只做絕不做
收集 Agent標的清單+資訊源白名單+字段清單facts JSON(值+來源指針+as-of)下載、抽取、欄位映射、metadata 規範化分析、推理、評價;缺失值「合理估計」;白名單外的來源
分析 Agent收集段產物(只讀)claims JSON(論斷+證據指針+信心等級)勾稽、指標計算、訊號判斷、交叉比對訪問外部資料源;為缺數編造補丁;輸出無證據指針的論斷
報告 Agent分析段產物+報告模板報告 Markdown+引用索引組織敘事、渲染表格、生成引用索引引入任何新事實;改動數字;對低信心論斷使用確定性語言

三個設計要點:

收集段禁止分析。 一旦收集 Agent 開始「順帶」總結,它就會為了敘事流暢而補全缺失——污染從源頭開始。收集段的產出應該是「無聊」的:一堆帶來源的三元組。

分析段禁止碰外部。 分析只允許在收集段的產物上工作。這條約束把「數據從哪來」的問題收斂到收集段一處,驗證只需要守住一個入口。分析發現缺數時的唯一合法動作是輸出 missing 標記與缺數影響說明,由編排層決定補採還是降級。

報告段禁止新事實。 報告裡的每個數字、每個論斷,都必須能在 claims JSON 中找到對應條目。這條規則讓「報告↔分析產物」的機械核對成為可能(第六節的 G3 門控)。

每段內部再按標的切片:收集段對每個標的起一個獨立子任務(獨立上下文),分析段同理。這就是三段流水線與按標的並行的組合:段間串行、段內並行。

三、段間資料契約:結構化 JSON 而非自由文字

段與段之間用自由文字傳遞(「收集 Agent 寫一段總結給分析 Agent 讀」)是多 Agent 系統最常見的偷工減料,代價是:來源指針丟失、無法機械驗證、下游把上游的推測當事實。契約必須是結構化的。

收集段輸出:facts(每個事實自帶完整 metadata):

{
  "schema_version": "1.2",
  "run_id": "run-20260930-001",
  "target_id": "FAKE-001",
  "target_name": "甲公司(虛構,教學用)",
  "collected_at": "2026-09-30T10:00:00Z",
  "facts": [
    {
      "id": "f-001",
      "field": "revenue_fy2025",
      "value": 1609.8,
      "unit": "million",
      "currency": "HKD",
      "period": "FY2025",
      "source": {"type": "filing", "doc": "annual-report-2025.pdf", "page": 88},
      "extracted_by": {"agent": "collect-v3", "model": "model-a", "method": "ocr+rule"},
      "status": "ok"
    },
    {
      "id": "f-002",
      "field": "trade_receivables_fy2025",
      "value": null,
      "unit": "million",
      "period": "FY2025",
      "source": {"type": "filing", "doc": "annual-report-2025.pdf", "page": 120},
      "status": "missing",
      "missing_reason": "附註表格跨頁,抽取失敗,需人工或二次抽取"
    }
  ]
}

注意 f-002:缺失就是 null,絕不是估計值。missing_reason 讓編排層能決定重試策略。

分析段輸出:claims(每個論斷綁定證據與信心):

{
  "schema_version": "1.2",
  "run_id": "run-20260930-001",
  "target_id": "FAKE-001",
  "claims": [
    {
      "id": "c-001",
      "type": "numeric",
      "statement": "FY2025 現金轉換率為 0.29,連續四年下滑",
      "value": 0.29,
      "method": "ocf / net_profit,口徑見 analysis-policy v4",
      "evidence_ids": ["f-010", "f-011", "f-021", "f-022"],
      "confidence": "high",
      "caveats": []
    },
    {
      "id": "c-002",
      "type": "qualitative",
      "statement": "應收帳款增速持續高於收入增速,收入品質存疑",
      "method": "rule CQ-002,參數 ar_gap_pp=15",
      "evidence_ids": ["f-001", "f-003"],
      "confidence": "medium",
      "caveats": ["帳齡附註缺失,無法排除大客戶集中回款的替代解釋"]
    }
  ]
}

報告段輸出:report(章節綁定 claim 引用):報告 Markdown 中每個數字與論斷帶 [c-001] 式引用標記,另附引用索引檔,列出每條 claim 到 fact 再到 source 的完整鏈路。

契約的執行靠 schema 校驗:每段收到輸入先跑 JSON Schema 驗證,schema_version 不匹配或缺必填欄位直接拒收並報錯,不嘗試「理解」不合規的輸入。契約升版時全鏈路一起升,禁止兩段之間用不同版本的 schema 對話。

四、寫入範圍劃分與衝突避免

多 Agent 並行時,檔案系統就是共享狀態,寫入範圍必須像資料庫權限一樣劃分:

runs/
└── run-20260930-001/
    ├── manifest.json              # 編排層專屬:任務清單、狀態、run 級配置
    ├── collect/
    │   ├── FAKE-001.facts.json    # 收集 Agent-1 專屬寫入
    │   ├── FAKE-002.facts.json    # 收集 Agent-2 專屬寫入
    │   └── ...
    ├── analysis/
    │   ├── FAKE-001.claims.json   # 分析 Agent 專屬寫入
    │   └── ...
    ├── report/
    │   ├── FAKE-001.md
    │   └── citation-index.json
    ├── gates/                     # 門控專屬:驗證結果只有門控進程可寫
    │   ├── g1/FAKE-001.json
    │   ├── g2/FAKE-001.json
    │   └── g3/FAKE-001.json
    └── logs/

規則四條:

1. 每個 Agent 只寫自己的輸出檔,檔名含 run_id 與 target_id;
   任何 Agent 都不得寫別人的目錄,不得寫「全局匯總檔」
2. 匯總是最後一步的獨立產物:所有標的通過門控後,
   由編排層(或獨立的匯總任務)一次性生成,生成過程唯讀所有輸入
3. 冪等重跑:同一 (run_id, target_id) 重跑即覆蓋自己的產物;
   重跑不依賴上一次執行的記憶體狀態,只依賴落盤的輸入檔
4. 門控結果由門控進程獨佔寫入——被驗證者不能寫自己的驗證記錄,
   這是防止「自己給自己蓋章」的架構手段

第 4 條背後有實證教訓:本站觀測過 LLM Agent 在連續執行中從「跳過驗證」惡化為「偽造驗證記錄」的行為(LLM Agent 自主繞過流程約束的實證分析)。只要驗證記錄的寫入權在被驗證者手裡,文字層面的「你必須如實記錄」就不可信。

五、失敗隔離:一個 Agent 出錯不污染全局

流水線的失敗哲學:預期每一段都會出錯,設計讓錯誤的影響範圍等於它的產生範圍。一個標的的收集失敗,影響範圍是那個標的;一個來源掛掉,影響範圍是使用該來源的字段。

隔離手段分四層:

層手段防的是什麼
上下文隔離每標的獨立子任務、獨立會話,禁止跨標的共享工作記憶A 公司數據滲進 B 公司結論
檔案隔離第四節的寫入範圍劃分產物互相覆蓋、半成品被當成品
執行隔離單標的失敗→標記 failed→其餘標的繼續;重試有上限與退避;來源連續失敗→熔斷該來源一個標的拖死整個 run
污染檢測實體一致性校驗:每條 fact 的 target_id 必須與內容中出現的實體名一致;量級合理性斷言(單位、幣別、數量級);schema 校驗抽取錯位、跨檔混入、單位事故

每個標的在編排層維護一個顯式的任務狀態機,狀態轉移只由門控結果觸發,不由 Agent 自報:

queued → collecting → g1_pass → analyzing → g2_pass → reporting → g3_pass → done
            │                       │                      │
            ▼                       ▼                      ▼
        collect_failed          g1_reject              g2_reject / g3_reject
        (重試≤N次後)          (退回重採,            (退回上段重修,
                                 記 missing 清單)        重修次數同樣有上限)

終態只有三種:done(全鏈路通過)、degraded(部分字段缺失但已標記,
人工裁決後放行)、failed(重試耗盡)。
不允許「無聲消失」:manifest 裡每個 target 必須落在某個終態。

狀態機的好處是把「部分成功」變成一等公民:一個標的的應收帳款附註抽不到,正確處理是標記 degraded、在報告裡明示缺數影響,而不是讓整個 run 卡死,更不是讓分析段悄悄補數。

失敗模式清單(設計評審時逐條過):

失敗模式症狀隔離/恢復設計
收集超時/來源改版facts 缺欄位、status=missing 激增重試+退避;熔斷來源;缺欄位降級而非中斷
OCR 錯位數值量級異常、勾稽失敗G1 量級斷言+勾稽檢查攔截;回查原頁
跨標的污染B 檔出現 A 的實體名實體一致性校驗(G1 硬性);上下文隔離
分析補數claims 的 evidence_ids 指向不存在或缺失的 factG2 證據存在性校驗:指針必須落到 status=ok 的 fact
報告改數報告數字與 claim 不一致(四捨五入、口徑偷換)G3 機械核對:報告中每個數字與引用 claim 逐一 diff
部分完成當全部完成匯總表少了標的卻沒說明manifest 對帳:匯總產物必須解釋每個標的最終狀態(成功/失敗/剔除)
成本失控token 消耗異常run 級預算+熔斷;單標的預算上限
schema 漂移下游解析錯誤或靜默丟欄位schema_version 嚴格校驗,不匹配即拒收

六、驗證門控放在哪裡:段間邊界+機械核對

門控的擺放原則:每個信任邊界一道門。段與段之間就是信任邊界——分析段不信任收集段的產出品質,報告段不信任分析段的輸出紀律,這種「不信任」要用代碼表達。

收集(每標的並行) ──▶ [G1] ──▶ 分析(每標的並行) ──▶ [G2] ──▶ 報告 ──▶ [G3] ──▶ 人工抽審 ──▶ 發布
                      │                             │                    │
              schema+來源指針              證據存在性+重算斷言      數字機械核對
              +實體一致性+勾稽            +信心標註率              +引用完整性+措辭掃描
                      │                             │                    │
                 fail→重採/標記missing         fail→退回分析          fail→退回報告

三道門的具體內容:

  • G1(收集後):schema 校驗;每個非 null 值必須有來源指針;實體一致性(fact 內容的實體=target);關鍵字段勾稽(三表勾稽公式,見 三表聯動與現金流品質檢查);按比例抽樣回原文檔重抽比對。
  • G2(分析後):每條 claim 的 evidence_ids 必須存在且 status=ok;數值型 claim 用獨立代碼重算(不復用分析 Agent 自己的算式);信心等級必填;低信心 claim 自動進入人工複核佇列。
  • G3(報告後):報告中每個數字與所引 claim 的機械 diff(容差內四捨五入要顯式登記);引用索引覆蓋率 100%;措辭掃描(對外部發布物檢查指令性、承諾性語言,見 投研 AI 的合規邊界)。

兩條架構級紀律。第一,門控必須是外部代碼,不是提示詞。在 prompt 裡寫「請仔細驗證」等於沒有驗證——被驗證者自己執行的「驗證」會被跳過甚至被偽造,這是實測結論(Agent 驗證架構的信任建築學)。第二,門控失敗的默認動作是攔截,不是警告後放行;放行需要人工在門控記錄上簽字。

七、成本與延遲的取捨

多 Agent 的成本結構與單 Agent 完全不同:多了編排開銷與重複校驗,省了長上下文的注意力浪費與重跑成本。優化槓桿按段分配:

段成本特徵優化槓桿不能省的
收集I/O 密集、token 中等、可高度並行小模型+規則優先(正則、模板抽取),大模型只處理非結構化殘段;來源快照快取來源指針的完整性;抽樣回查
分析token 少、推理密度最高用你可負擔的最強模型;一次只做一個標的(上下文小而乾淨,反而省 token)重算斷言;信心標註
報告token 中等、模板化程度高中檔模型+嚴格模板;引用索引機械生成而非模型生成G3 機械核對
門控純代碼、成本近零——任何一道門

延遲方面,三段流水線的關鍵路徑是「最慢的標的」:段內並行度足夠時,總延遲≈單標的延遲×3+門控時間。三個實務決策:

1. 收集段預取:資訊源快照與抽取可以在任務下達前就完成
   (年報發布即入庫),把收集延遲移出關鍵路徑
2. 流式過門:標的級粒度過門控——FAKE-001 通過 G1 就進分析,
   不等 FAKE-002;全 run 的 barrier 只留在匯總前
3. 預算熔斷:run 級 token 與時間預算,超限即停止新任務派發,
   已完成部分照常過門產出——部分結果好過沒有結果

最後是那個最容易被忽略的取捨:驗證成本與返工成本。砍掉門控省下的錢,會以「發現報告有錯→全板塊重跑→聲譽損失」的形式加倍收回。門控是全鏈路裡單位成本最低、回報最高的環節,預算緊張時先砍收集段的模型檔次,最後才動門控。

成本要落到可觀測的指標上才算管理。每次 run 結束,manifest 裡固定沉澱一組運行統計:各段的 token 消耗與耗時(按標的、按段拆分)、重試次數與原因分佈、門控攔截率(G1/G2/G3 各攔了多少、因為什麼)、missing 字段率、單標的平均成本。這組數字每週看一次趨勢:攔截率突然上升通常意味著上游抽取品質退化;重試激增通常意味著某個資訊源改版;單標的成本漂移則多半是提示詞或模型檔次被人動過。成本監控與品質監控共用同一套運行統計,這也是下一篇系統設計文章的伏筆——流水線的運行數據本身就是系統最重要的資產之一。

八、AI 會在這裡出錯:段間幻覺放大

單 Agent 的幻覺是點狀的;流水線的幻覺是級聯放大的。典型鏈路:

收集段:附註抽取失敗 → 輸出 missing(5% 的正常缺損率)
分析段:模型「知道」這類公司帳齡結構通常長什麼樣 → 用合理推斷補上缺口
        → claim 的 evidence_ids 指向一條 status=missing 的 fact(或乾脆不指向任何 fact)
報告段:claim 進了報告,caveats 被敘事「順平」,信心 medium 被寫成確定語氣
讀者:看到一段流暢、自信、有數字有結論的分析——其中關鍵一環是編的

三段各自的危險點與對應的機械防禦:

段危險動作機械防禦
收集把缺失值補成「合理估計」規則:value=null 必須伴隨 missing_reason;G1 攔截無來源的值
分析論斷與證據脫鉤;用記憶中的「行業常識」當數據G2 證據存在性校驗+獨立重算;claims schema 中無 evidence 的論斷只能標 type=hypothesis 且禁止進報告正文
報告數字改寫、信心升格、caveats 丟失G3 逐數字 diff;模板強制渲染 caveats;低信心 claim 的措辭白名單

再加一道端到端抽審:每次 run 隨機抽一個報告中的數字,沿 report→claim→fact→source 全鏈路人工回溯到原始文件的那一頁。這條抽審是全系統唯一能發現「三道門都沒想到的新錯誤模式」的機制,它的發現應該回流成新的門控規則。

流水線拆分不能消除幻覺,但它把幻覺從「瀰漫在全文」變成「卡在某道門」——可定位、可攔截、可統計。在此之上的系統級設計(技能庫、評測集、多層門控、維運),見 自建投研系統;三段分工背後的通用 Agent 分層原理,見 三層 Agent 框架 與 Agent 循環架構比較。

下一步