機構模式: 運維參考
多智能體投委會的分析師恢復契約與規範資產預解析
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,通用的"始終產出可用結果"
構造器。兩種分支:
| 分支 | 觸發條件 | Headline | Confidence |
|---|---|---|---|
| 部分 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),編排器
跑服務端預解析:
- 查 SQLite 緩存(
canonical_asset_cache表)。 - 緩存未命中或過期:並行查詢 CoinGecko / CMC / DexScreener,
歸一化為 chain+contract 身份(CAIP-19 風格的 discriminated
union:
evm/native/solana/cosmos/polkadot/equity)。按結果分別 TTL 持久化。 - 結果分發:
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 | 為什麼 |
|---|---|---|
resolved | 30 天 | chain+contract 穩定,很少變 |
multi | 14 天 | 用戶消歧可能固定到具體某條鏈 |
ambiguous | 7 天 | provider 數據可能收斂 |
none | 1 天 | provider 每日更新;儘快重試 |
user_supplied | 365 天 | 操作員覆寫;信任人類 |
各類 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。兩種路徑:
- 實時解析:下一次
/institution <ticker>觸發預解析, 緩存結果,之後所有角色都能看到規範身份。 - 操作員覆寫:當 CoinGecko / CMC / DexScreener 都沒有
這個代幣(如全新發行),操作員可以直接固定規範身份。UI:
abort banner 提供合約地址表單。CLI:
minara assets pin <ticker> --chain <chain> --contract <0x...>(當部署裡啟用了 assets CLI)。
methodology-store 的 TICKER_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>