MINARA

個性化與工作區

手動編輯的 persona 文件、自動重建的財務檔案、11 個行為標籤維度及重建流程

個性化層讓 Agent 對"與誰對話"形成穩定認知: 經驗水平、風險偏好、偏好資產、歷史交易摘要, 以及回覆風格的 persona 指令。

該層由兩個子層構成:

  • 工作區文件(手動編輯的 Markdown):Agent persona、 啟動指令、用戶檔案、精選長期記憶。 用編輯器直接控制。
  • 財務檔案 + 用戶標籤(自動重建的數據庫表): 定時 LLM 任務讀取聊天和交易歷史, 維護結構化字段(交易摘要、11 個標籤維度、個性化類記憶)。

兩者都會輸入到提示詞構建器。 文件層穩定且明確; 數據庫層反映實際行為,隨時間更新。

為何分兩層而非一層? 純文件層要求用戶自己持續更新自身信息, 實際上很少有人會堅持。 純推斷層會發生漂移:LLM 對"這個用戶是誰"的印象隨每筆交易變化, 可能覆蓋刻意設置的偏好。 分層可以讓用戶主動聲明的意圖(persona、顯式偏好)始終處於上層, 同時將推斷出的檔案作為 Agent 參考的證據,而非覆蓋依據。 就像簡歷放在一個文件裡、交易歷史放在另一個文件裡: 作者不同,更新週期也不同。

實際效果參見功能 → 記憶 介紹了用戶端"告訴 Minara 關於我的信息"的流程, 該流程會同時填充這兩層。

關於每個角色的決策反思(完全不同類型的記憶), 參見角色記憶

工作區文件(persona 層)

Minara 在會話啟動時讀取一組 Markdown 文件, 用於定製身份、用戶檔案和精選長期記憶。 該目錄與 OpenClaw 的佈局兼容, 可通過 --workspace 將 Minara 指向已有的 OpenClaw 工作區。

目錄結構

默認位置:~/.minara/workspace/

workspace/
├── SOUL.md        — agent 身份 / persona
├── AGENTS.md      — 会话启动指令
├── IDENTITY.md    — agent 自我描述(名称、风格、emoji)
├── USER.md        — 被服务用户的档案
├── MEMORY.md      — 精选长期记忆
├── TOOLS.md       — 工具参考(仅供参考)
├── BOOTSTRAP.md   — 仅首次运行,初始读取后删除
├── HEARTBEAT.md   — 会话状态文件
└── memory/
    └── YYYY-MM-DD.md  — 每日记忆笔记(3 天窗口)

minara setup 會創建該目錄並填充合理的默認值。 用任意編輯器修改;寫入在下一次會話生效, 因為工作區在啟動時加載一次後即凍結,整個會話期間不變。

文件清單

文件用途提示詞位置
SOUL.mdAgent 身份 / persona可緩存的身份塊(前綴)
AGENTS.md會話啟動指令可緩存的身份塊(前綴)
USER.md被服務用戶的檔案個性化快照(動態)
MEMORY.md精選長期記憶記憶快照塊(動態)
memory/YYYY-MM-DD.md每日記憶筆記(最近 3 天)記憶快照塊(動態)
IDENTITY.mdAgent 自我描述(名稱、風格、emoji)僅元數據(展示用,不進入提示詞)
TOOLS.md人類可讀的工具參考僅供參考;Agent 實際使用 schema
BOOTSTRAP.md僅首次運行的設置指令合併到身份塊,執行一輪
HEARTBEAT.md會話狀態文件參見工作流Autopilot

各文件如何進入提示詞

SOUL.md     ──┐
              ├─▶ systemPromptPrefix (cached block)
AGENTS.md   ──┘

MEMORY.md   ──┐
memory/*    ──┼─▶ memory snapshot block (dynamic)
USER.md     ──┘

IDENTITY.md ───▶ metadata (name, emoji) for display only
TOOLS.md    ───▶ informational, rarely injected
  • SOUL.mdAGENTS.md 與身份一起緩存,緩存命中率較高。 保持小幅修改,修改後用 /prompt 驗證。 結構性修改可能在下次編輯之前降低所有會話的緩存命中率,需謹慎處理。
  • USER.md 描述用戶,每輪追加到個性化快照。
  • MEMORY.md 是精選長期記憶。建議在會話中通過 memory_write 寫入,由壓縮機制將持久事實提升到該文件。
  • memory/YYYY-MM-DD.md 是每日筆記,只加載最近 3 天。
  • IDENTITY.mdTOOLS.md 不進入提示詞。
  • BOOTSTRAP.md 只在首次會話執行一次,之後刪除。

凍結快照語義

工作區在會話啟動時加載一次。 會話中的寫入會持久化到磁盤,但不會修改運行中的提示詞。 這與記憶存儲使用相同的凍結快照模式(參見 記憶系統), 原因也相同:保持 Anthropic 提示詞緩存穩定性。

若在會話中編輯了 USER.md,請重啟 REPL 或執行 /new, 以便快照重新加載。

/workspace REPL 命令

/workspace soul     # 打印 SOUL.md
/workspace agents   # 打印 AGENTS.md
/workspace user     # 打印 USER.md

參見斜槓命令 → /workspace

工作區安全注意事項

  • 工作區文件屬於受信任輸入。 未經審查,不要將其交給不可信用戶。 惡意的 SOUL.md 可將 persona 設置為"始終無需詢問即確認交易", LLM 會照此執行。
  • 編輯在下一次會話生效。 會話中對 USER.md 的修改, 重啟或 /new 之後才會生效。
  • SOUL.mdAGENTS.md 是緩存提示詞塊。 結構性修改可能在下次編輯之前降低所有會話的緩存命中率; 保持小幅改動,並用 /prompt 驗證。

源碼:apps/agent/src/config/workspace.ts

財務檔案與用戶標籤(自動重建)

工作區文件由人工編輯,財務檔案層則由定時 LLM 任務自動重建, 該任務讀取近期對話和交易歷史。

兩張表加一個分類

個性化服務維護的所有數據存放在三個位置:

  1. financial_profile:每個用戶一行。交易摘要、 參考錢包、自定義提示詞片段、可見性標誌、重建冷卻游標。
  2. user_tags:每個用戶最多 11 行,每個維度一行, 外加 source 字段,記錄該值是用戶聲明還是行為推斷。
  3. 個性化類記憶memories 表中 category = 'personalization' 的普通行。與常規記憶共存,FTS5 和凍結快照加載器無需特殊處理, 但加載優先級更高。

所有數據以 user_id 為鍵(單用戶部署默認為 'default')。

financial_profile 字段說明

字段類型用途提示詞位置
user_idTEXT PK用戶標識,默認為 'default'
platform_wallet_summaryTEXTLLM 生成的用戶 Minara 錢包活動摘要。個性化塊
reference_wallets_summaryTEXTLLM 生成的用戶關注的參考錢包摘要。個性化塊
reference_wallets_jsonTEXT參考錢包地址的 JSON 數組。個性化塊
custom_promptTEXT用戶自定義指令,追加到系統提示詞。個性化塊
include_memoriesINTEGER可見性標誌。0 表示不在提示詞中顯示個性化記憶。切換塊包含
include_trading_summaryINTEGER交易摘要文本的可見性標誌。切換塊包含
include_tagsINTEGER行為標籤行的可見性標誌。切換塊包含
trading_summary_next_updateTEXT冷卻目標:摘要最早可再次重建的時間。
tags_next_updateTEXT標籤重建的冷卻目標。
memories_next_updateTEXT個性化記憶提取的冷卻目標。
last_indexed_chat_idTEXT記憶重建器增量掃描聊天的游標。
trading_summary_updated_atTEXT交易摘要本身上次重建的時間(與行級 updated_at 不同)。
created_at, updated_atTEXT標準行時間戳。

字段定義位於 apps/agent/src/memory/personalization-service.ts。 啟動時會通過冪等 ALTER TABLE 遷移補充現有數據庫中缺失的列。

11 個行為標籤維度

每個用戶都有一組從交易歷史和對話中推斷出的金融特徵標籤向量。 每個維度存儲機器可讀的 value(slug,或用於等級制的 level_N); 下方顯示的人類可讀標籤用於 UI 和提示詞渲染。 七個維度屬於 v2 / 用戶畫像集; 四個人格維度從 v1 沿用(其 value 與 label 相同)。

維度允許值(value → 標籤)
finance_knowledgelevel_1 初學者 / level_2 中級 / level_3 高級 / level_4 專家
frequencypassive / weekly / daily / active
markets(多選)crypto_majors / crypto_alts / memes / stocks / commodities / pre_ipo
riskconservative / balanced / aggressive
web3_knowledge_levellevel_1 新手 / level_2 熟悉 / level_3 有經驗 / level_4 專業
stylefundamentals / technical / narrative / news_event / community
horizonintraday 日內 / swing 波段 / position 中線 / long_term 長線
FOMO IndexVery Low / Low / Medium / High / Very High
FUD ImmunityStrong / Medium / Weak
Patience LevelHigh / Medium / Low
Greed IndexVery Low / Low / Medium / High / Very High

markets 為多選:其 value 是單個 user_tags.value 列中的 JSON 數組字符串, 其他所有維度均存儲單個值。 字段定義位於 apps/agent/src/memory/tags-schema.ts; 調用方使用其類型化輔助函數(allowedValuesisValidTagValueserializeTagValueparseStoredTagValuerenderTagSchema),而非直接讀取 schema map。 超出允許值範圍的寫入會被 PersonalizationService.upsertTag 拒絕,不會靜默強制轉換。

除了 onboarding 和對話推斷外,markets 還有一個客觀來源。一個 24 小時 定時任務(MarketsObjectiveUpdaterapps/agent/src/memory/markets-updater.ts) 掃描用戶當前 autopilot 策略的標的,以及過去 30 天內記錄的合約成交, 將每個 symbol 分類到某個市場,並通過 PersonalizationService.unionMarkets 把結果以並集方式推入該標籤。它只新增、從不移除,並保留該行已有的 source, 因此推斷來源的寫入永遠不會降級或清除用戶主動聲明的選擇。agent 之外(非 agent 發起)的合約成交活動會觸發一次更早的、受冷卻時間限制的運行。

現有 v1 行可通過一次性腳本 pnpm --filter @minara/agent migrate:user-tags-v2 遷移到此 schema (默認試運行,加 --apply 才寫入)。 該腳本將 Risk ProfileriskWeb3 Knowledge Levelweb3_knowledge_levelDecision-Making StylestyleAsset Preferencemarkets,刪除已廢棄的 Asset Tier / Trading Frequency / Learning Preference 維度,保留四個人格維度不變。

資金指標(客觀,Agent 內部)

用戶的投入資金是客觀指標,既非自我申報,也不在設置頁面顯示。 它取代了 v1 中自我申報的 Asset Tier 標籤, 存儲在獨立的 capital_metrics 表(每個用戶一行), 僅供 Agent 推理使用,不屬於面向用戶的個性化快照。

capital_total_usd = spot_holdings_usd + perp_value_usd

spot_holdings_usd 彙總跨鏈投資組合資產價值; perp_value_usd 是永續合約子賬戶權益的彙總值。 總額分為 8 個等級(tier_1 < $10 … tier_8 ≥ $50k)。 重新計算由 24 小時定時任務及鏈下活動通知驅動,受冷卻時間限制; 當讀取來源不可用時,降級為保留上次值,而非寫入誤導性的零值。 字段定義和等級劃分位於 apps/agent/src/memory/capital-metrics.ts

策略運行記錄(Autopilot 歷史)

strategy_runs 是 Autopilot 激活的只追加歷史記錄, 每次啟用→禁用週期對應一行, 包含分配資金、開始/停止時間、狀態、 stop_reasonuser_manual / insufficient_balance / drawdown_protection / liquidated / strategy_expired / other), 以及停止時回填的已實現 PnL。 與資金指標一樣,這是 Agent 內部數據,不屬於面向用戶的快照。

啟用完全託管策略會開啟一條運行記錄; 通過 Agent 禁用會將其關閉為 user_manual。 由於 fullyManagedStrategies 位於上游,Agent 無法感知某些停止事件 (如通過 Web UI 禁用,或因回撤/清算自動停止), 這些情況由對賬流程處理:Agent 列舉策略時, 若已開啟的運行記錄不再出現在上游運行集中,則將其關閉(other), 並設置短暫的寬限窗口,避免剛啟用的運行在顯示為運行中之前被誤關閉。 存儲邏輯位於 apps/agent/src/memory/strategy-runs.ts

手動交易檔案

TradingProfileReader 將用戶 30 天內的鏈下永續合約活動 (perps_fills 鏡像,即通過 Web / 移動端 / 手動操作的交易) 彙總為簡潔畫像: 交易次數、按數量和成交量排名的頭部標的、 多空比例、已實現 PnL、平倉勝率、平均交易規模、最近交易時間。 該模塊同時支撐 search_user_trades Agent 工具, 可返回用戶某資產的近期成交記錄(方向、開倉/平倉方向、USD 規模、價格、已實現 PnL)。 兩者均為 Agent 內部數據,將分析錨定在用戶真實歷史上。 該鏡像不含槓桿信息,也不區分手動與 Autopilot,因此這兩項超出當前範圍。 源碼: apps/agent/src/memory/trading-profile.ts

按需個性化召回

緩存安全的個性化召回方式是讓模型按需拉取所需信息, 而非將所有內容始終注入緩存前綴。 search_conversation_memoryconversation-memory-tool.ts) 按需召回用戶的持久個性化記憶(偏好、檔案事實、約束、目標), 限定 personalization 分類,複用 FactLayer 混合檢索。 工具結果落在緩存前綴之後,召回不會干擾提示詞緩存。 它與 personalization_snapshot(按需獲取完整畫像)和 memory_search(所有分類)配合使用。

新用戶引導

用戶級引導流程從明確的答案中生成初始畫像。 POST /v1/profile/onboarding 將答案映射到用戶聲明的標籤 (finance_knowledgefrequencyriskmarkets), 每個已回答的維度寫入一條個性化記憶(僅首次完成時寫入, 重新提交會更新標籤但不會重複創建記憶), 並將自我申報的投資資金記錄為記憶,而非標籤或資金指標(資金指標保持客觀)。 原始答案和完成標誌持久化到 financial_profile 行; GET /v1/profile/onboarding 返回狀態,供 Web UI 判斷是否顯示引導流程。 該調用是冪等的,會在任何寫入之前拒絕無效標籤值。 實現位於 PersonalizationServicecompleteOnboarding / getOnboardingStatus)。

user_tags 中的每行也記錄 source 字段, 說明該值是用戶聲明還是 LLM 推斷。 提示詞構建器據此對標籤加權(聲明值優先於推斷值)。

三種重建流程

個性化由 apps/agent/src/memory/personalization-rebuilder.ts 定時重建。 心跳監視器調度三個獨立方法,各自有獨立冷卻窗口, 單個慢重建不會阻塞其他重建。

方法觸發條件冷卻時間(默認)輸入輸出
rebuildTradingSummary()trade_history / perps_fills:recorded / external_spot:recorded 事件;通過 /profile refresh 強制觸發30 分鐘合併三個來源:會話內 trade_historyperps_fills(鏈下永續合約鏡像)、external_spot_activities(鏈下現貨鏡像),以及參考錢包合成 platform_wallet_summaryreference_wallets_summarytrading_summary_updated_at
rebuildTags()通過 tags_next_update 定時調度30 天檔案 + 交易歷史 + 枚舉 schema標籤行 upsert 到 user_tags
rebuildMemories()通過 memories_next_update 定時調度10 分鐘last_indexed_chat_id 之後創建的聊天個性化類記憶 + 游標推進

每次重建是一次廉價的單次 LLM 調用(默認使用 Haiku)。 冷卻時間按 v1 的經驗調整: 交易摘要刷新頻繁(新交易很重要),標籤刷新罕見(屬於緩慢變化的檔案數據), 記憶提取頻繁(及時捕捉用戶表達的新偏好)。

last_indexed_chat_id 游標使 rebuildMemories 只讀取未處理的聊天。 若無此機制,每次觸發都會重新讀取完整的聊天曆史,消耗大量 token 預算。

三來源交易摘要詳解

rebuildTradingSummary() 讀取三個獨立來源, 設置合併閾值,並推進三個獨立游標, 確保某次解析失敗不會悄悄丟失其他來源的數據。

                ┌──────────────────────────────────────────┐
trade event ────►│ trade_history (in-session)               │──┐
                └──────────────────────────────────────────┘  │

                ┌──────────────────────────────────────────┐  │
Minara web/    ►│ perps_fills (cross-sub mirror)            │──┤
mobile perps    └──────────────────────────────────────────┘  │
   (via                                                        ▼
    MinaraHistorySync.syncAll)                ┌─────────────────────────┐
                ┌──────────────────────────────────────────┐ │ rebuildTradingSummary │
Minara web/    ►│ external_spot_activities (mirror)         │►┤ gates: newTrades +      │
mobile spot     └──────────────────────────────────────────┘ │  newPerpsFills +        │
                                                              │  newExternalSpot ≥      │
                                                              │  threshold               │
                                                              │                          │
                                                              │ LLM emits 4 fields →    │
                                                              │   platformWalletSummary │
                                                              │   spotBreakdown          │
                                                              │   perpsBreakdown         │
                                                              │   referenceWalletsSummary│
                                                              │ → composed into one      │
                                                              │   platform_wallet_summary│
                                                              │   string with Spot: /    │
                                                              │   Perps: prefixes        │
                                                              └─────────────────────────┘

三個獨立游標存儲在 financial_profile 行上:

  • trading_summary_last_trade_id_seen(原有)
  • trading_summary_last_perps_fill_id_seen(新增)
  • trading_summary_last_external_spot_id_seen(新增)

三個游標僅在 LLM 返回可解析響應且新摘要已寫入後才推進。 解析失敗時所有游標保持原位,下次重建會重試同一窗口,不會悄悄丟失任何來源。

MinaraHistorySync 觸發路徑

鏈下鏡像表由 MinaraHistorySyncapps/agent/src/memory/minara-history-sync.ts)填充。 同步是即發即忘的,自帶節流,失敗時最多隻會導致新增 0 行。 三條觸發路徑:

  1. 交易事件搭載eventBus.on("trade:recorded", () => minaraHistorySync.scheduleSync())。Agent 自身记录交易时,用户很可能也在 Web / 移动端操作,此时同步成本低且及时。5 分钟节流(historySyncMinIntervalMs)可合併突發請求。
  2. 安全網定時器:每 30 分鐘,應用計時器調用 minaraHistorySync.runIfStale(),確保漏掉事件時鏡像不會長期停滯。
  3. 強制刷新:CLI /profile refresh(或對應的 HTTP 接口 POST /v1/profile/refresh)繞過節流,在重建前執行 runOnce(),保證下次摘要能看到最新的鏈下活動。

連續失敗次數達到 historySyncMaxFailures(默認 5)後, 該 (source, sub_account_id) 鍵在常規調度中會被跳過。 自 last_synced_at 起經過 historySyncFailureCooldownMs(默認 30 分鐘)後, 會主動觸發一次探測。探測成功則將 consecutive_failures 重置為 0, 防止瞬時故障永久停用鏡像。

memory.trading-cases 的邊界

memory.trading-casesmethodology_cases SQLite 表)是獨立的記憶, 與個性化畫像並列存在,互不重疊。 分離的原因是兩份記錄面向不同的消費方,混合會相互汙染:

  • memory.trading-cases 是 Agent 的學習循環。 每行是 Agent 在會話中做出的一次決策,歸因到一個或多個方法論 ID, 並在事後以 Wilson 畢業機制打分。 消費方是方法論系統,用來決定某個方法論是否應繼續被推薦。
  • 個性化畫像(本頁)是 Agent 對用戶是誰的認知, 彙總為一段 Agent 始終隨系統提示詞攜帶的描述段落。 它讀取會話內交易 + 鏈下永續合約 + 鏈下現貨數據。

MinaraHistorySync 的外部成交記錄故意寫入 methodology_cases, 因為它們不攜帶方法論 ID 或提示詞 hash, 反向歸因會汙染方法論畢業所依賴的 Wilson 統計數據。 出於同樣原因,Web UI 中的交易案例頁是隻讀審計看板,編輯會破壞學習語料庫。

與普通 memory_write 的關係

個性化重建經過審計日誌鉤子,這是刻意設計:

  • 重建按計劃運行。每次觸發都會產生大量審計行, 而輸出是派生數據而非用戶操作。審計日誌會被重建噪音填滿。
  • 用戶發起的 memory_write 仍走正常的工具調度路徑, 並以完整推理落入 audit。用戶主動發起,因此用戶行為可審計。

若需瞭解個性化重建的上次運行時間, 可直接查詢該行的 trading_summary_updated_attags_next_update。 對於單條個性化記憶寫入,可在 memories 表中按 category = 'personalization' 過濾 created_at 查詢。

配置

冷卻間隔、LLM 模型和啟動時重建行為配置於 apps/agent/src/memory/financial-profile-config.ts。 默認值直接沿用 v1:

  • tradingSummaryCooldownMs:30 分鐘
  • tagsCooldownMs:30 天
  • memoriesCooldownMs:10 分鐘
  • rebuildOnBootfalse

未提供 LLM 客戶端時(用於測試),重建為空操作。 如有需要,可通過 MINARA_PERSONALIZATION_REBUILD=disabled 在生產環境完全關閉該服務; 但請注意,關閉後持久記憶永遠不會進入 personalization 分類。

/profile REPL 命令

在 REPL 中查看當前個性化快照:

/profile

打印財務檔案行、活躍用戶標籤、近期個性化記憶,以及自定義提示詞片段(如有)。 這是排查"Agent 為何這樣表現"最快的方式: 若檔案顯示 risk: conservative,Agent 卻建議 10 倍槓桿, 說明上游某處出現了問題。

編輯檔案字段

直接字段編輯通過配置 CLI 完成:

minara config get financial.custom_prompt
minara config set financial.custom_prompt "Always prefer stablecoin pairs."

標籤編輯通過個性化服務完成。 最簡單的方式是讓 Agent 從對話中推斷。 內部輔助函數支持直接手動 upsert,用於 CI 數據預填,但不對外暴露為 CLI 命令。

安全注意事項

  • 個性化重建由 LLM 驅動。 Haiku 調用成本低但不為零; 生產環境請設置 MINARA_DAILY_CAP_USD。 錯誤配置的重建循環可能悄悄消耗預算。
  • custom_promptSOUL.md 一樣屬於受信任輸入。 能編輯它的用戶可以改變 Agent 的行為。 多租戶部署需在自有認證層後面限制寫入權限。
  • 標籤推斷不代表事實。 標籤向量是基於聊天和交易樣本的盡力推斷。 Agent 將聲明值視為強於推斷值,但兩者都不應用來覆蓋用戶在對話中的明確指令。
  • 部分重建會留下過期狀態。 若 LLM 調用在重建中途超時, 冷卻時間仍然會推進。下次重建正常運行,期間會出現短暫的過期窗口。 請根據實際情況調整冷卻時間。

本頁目錄