MINARA

機構模式: 運維參考

多智能體投委會的分析師恢復契約與規範資產預解析

minara_institution_analyze 可以運行 Minara 默認投委會流程, 也可以運行網頁界面中為當前會話保存的 Roundtable。本頁說明 默認分析路徑使用的底層恢復與資產解析行為。階段編排、Agent 設置、模板和不可變運行快照見 Institution Mode

默認流程包含並行分析、多空辯論、研究綜合、交易方案、風險辯論 和最終組合判斷。自定義 Roundtable 可以替換這套安排,同時保留 相同的只讀安全邊界。

流水線超時和基準配置見 環境變量: Institution Mode

Roundtable 狀態與快照

Builder 為每個 Institution 會話保存一套活動流程。保存時會校驗預期 版本,因此另一個瀏覽器窗口不會悄悄覆蓋較新的修改,而會收到衝突。 如果會話沒有已保存流程,網關會依次採用最近一次運行快照和內置默認值。

Agent、階段和 Roundtable 模板分別存儲。內置模板不可修改。運行開始時, 完整流程會複製到不可變快照,其中包含階段結果、Agent 用量、最終狀態和 報告文件。相關接口包括:

分析師恢復,synthesis-and-parse

每個 Phase-1 分析師 slot 先在自由的 tool 調用循環裡跑 (submit_analyst_report 始終和角色數據工具一起暴露)。 當主循環提交了一份真實、非 stub 報告時,slot 附上捕獲的 tool_outputs[] 並返回。

當主循環沒提交(turn 上限觸發、模型寫了散文卻忘了提交)或 提交了空/佔位參數時,編排器跑 一次 綜合 turn:

  • 不帶 tools,不帶 tool_choice。開啟 thinking,這是之前在 tool_choice: { type: "tool" } 下失敗的調用,因為 Anthropic 拒絕那種組合,留給模型填充參數的推理空間為零。

  • 用戶消息要求嚴格的三段散文格式:

    HEADLINE: <一句结论>
    
    KEY FINDINGS:
    - <finding 1, 引用工具名 + 具体数字>
    - <finding 2, ...>
    
    CONFIDENCE: <0.0 到 1.0 之间的数字>

編排器通過 parseSynthesisProseToReport 在服務端把散文直接 解析為 AnalystReport。解析器寬容混合的 bullet 風格、段落 標記前後的 markdown 強調標記、以及範圍之外的置信度 (截斷至 [0, 1])。

當綜合 turn 的散文為空、格式錯亂、或者所有 bullet 都長得像 佔位("tried X: ok")時,編排器回落到 buildSubagentSummaryReport,通用的"始終產出可用結果" 構造器。兩種分支:

分支觸發條件HeadlineConfidence
部分 tool 成功toolsTried.some(t => t.status === "ok")"<ticker> (<role>): raw tool summary (model synthesis unavailable)"0.3
全部 tool 失敗/無 tool 調用toolsTried.every(t => t.status !== "ok") 或為空"<ticker> (<role>): no data gathered this session""... no tools available this session"0.1

當部分 tool 成功時,報告引用捕獲的 tool 數據(每個 tool 一條 bullet,從其 preview 派生),下游階段就能看到返回了什麼。 當全部失敗時,報告枚舉嘗試過的 tool,最後以角色的領域默認推理 一句話結尾(每個角色一句,定義在 roles.ts 角色定義旁邊)。

無論哪種分支,slot 的 ok 標誌都是 true,舊的 "data-gap" 概念已經退役。每個 Phase 1 slot 現在都給主智能體提供一份可用 總結,Phase 2-6 始終運行。

Tool outputs,捕獲返回數據面

每份 AnalystReport 攜帶一個可選的 tool_outputs[],由編排器 從 slot 的會話中填充。每個 tool 調用一條:

{
  tool: string;           // 工具名
  ok: boolean;            // true 表示调用成功
  preview: string;        // 成功:截断的 JSON / 文本(~1500 字符)
                          // 失败:错误信息字符串
  args_summary?: string;  // 调用输入的一行摘要
  error_code?: string;    // 结构化失败类别(如果有)
}

成功的調用攜帶漂亮打印的 JSON 預覽;失敗的調用直接把失敗 原因帶在 preview 裡,操作員能直接看到 WHY 一次調用沒返回 數據,而不是隻看到它沒返回。web-ui 裡的 PersonaOutputRenderer 把這些數據渲染為結構化輸出彈窗裡的 "Tool outputs" 段落, 每條可點擊展開。

規範資產預解析

Phase 1 派發之前,若 classifyAsset(ticker) === "unknown" (或 INSTITUTION_FORCE_RESOLVER_PREFLIGHT=true),編排器 跑服務端預解析:

  1. 查 SQLite 緩存(canonical_asset_cache 表)。
  2. 緩存未命中或過期:並行查詢 CoinGecko / CMC / DexScreener, 歸一化為 chain+contract 身份(CAIP-19 風格的 discriminated union:evm / native / solana / cosmos / polkadot / equity)。按結果分別 TTL 持久化。
  3. 結果分發:
    • resolved(唯一 chain+contract):補充 meta.resolved_ticker, 分析師在 preamble 看到規範身份。
    • multi(多鏈部署):同上,但候選數組進入消歧上下文。
    • ambiguous(provider 不一致):集中式消歧事件, 而不是四個並行 "which token did you mean?" 提問。
    • none:Phase 1 之前中止,零 LLM 調用。這是編排器 目前唯一仍會觸發的 abort kind。

規範身份是 chain+contract,不是 CoinGecko id。 CoinGecko 的內部 id 是依賴他們策展的中心化索引;用作 bootstrap 輸出會把整個智能體鎖在某一個 provider 的世界觀裡。下游接受 on-chain 查詢的工具直接吃 CAIP-19;provider-specific 工具 (CoinGecko 價格圖)只在規範身份確定後從 sources 讀自己的 id。

按結果的 TTL

緩存按結果使用不同 TTL,因為各結果的衰老速度不同:

結果默認 TTL為什麼
resolved30 天chain+contract 穩定,很少變
multi14 天用戶消歧可能固定到具體某條鏈
ambiguous7 天provider 數據可能收斂
none1 天provider 每日更新;儘快重試
user_supplied365 天操作員覆寫;信任人類

各類 TTL 通過 CANONICAL_ASSET_CACHE_TTL_*_DAYS 環境變量調 (見 env-vars 參考)。

當實時聚合失敗(provider 宕機、被限流)時, CANONICAL_ASSET_CACHE_FALLBACK_TO_EXPIRED=true(默認) 返回帶 from_expired_fallback: true 標記的過期緩存。設為 false 當部署不能容忍任何數據漂移。

添加缺失的 ticker

智能體首次遇到新 ticker 時就學到 ticker → 規範身份映射。新代幣 不需要 code deploy。兩種路徑:

  1. 實時解析:下一次 /institution <ticker> 觸發預解析, 緩存結果,之後所有角色都能看到規範身份。
  2. 操作員覆寫:當 CoinGecko / CMC / DexScreener 都沒有 這個代幣(如全新發行),操作員可以直接固定規範身份。UI: abort banner 提供合約地址表單。CLI: minara assets pin <ticker> --chain <chain> --contract <0x...> (當部署裡啟用了 assets CLI)。

methodology-storeTICKER_TO_CLASS 表依然存在,但用途 不同了(用於風險 / 投資組合代碼查 asset-class)。規範解析器 在它給出新的 asset_class 信息時回寫過去,但 TICKER_TO_CLASS 不再是規範身份的真理源。

在實踐中檢查恢復情況

institution_role_outputs.data_gap 列依然保留在 schema 上以 兼容舊行(data-gap 概念退役前寫入的數據)。新寫入始終設為 0。 指標聚合器 InstitutionStore.getAnalystStubMetrics 仍能讀出 做歷史報告,但這一列在當前的恢復路徑裡已經不再起作用。

逐 run 審計:

# 一次 run 所有分析师行,包含旧版 retry_count + data_gap。
minara learning methodology cases --run-id <run_id>

本頁目錄