MINARA

技能系統

路由與激活的工作原理,以及完整的可用技能目錄

技能是 Minara Agent 的能力單元。每個技能包含一段提示詞片段、一份工具白名單,以及一組告訴路由器該技能何時相關的元數據。技能是發現與 playbook 的入口:激活它會把該領域的工具暴露出來,並拉入使用這些工具的指引(何時該用哪個工具、某個工作流背後的方法論、它所依託的領域理論)。它不是工具授權門。普通會話裡每個已註冊工具都可直接調用;加載技能只是幫模型找到合適的工具並讀到 playbook。可以把技能理解為 Agent 按需加載的插件。

為何不用 MCP? Minara 的核心能力使用自有技能與工具註冊表(而非 MCP),原因是金融工具需要逐次調用的權限等級、類型化 schema 以及 MCP 規範未覆蓋的涉資金確認門。外部服務商仍通過 MCP 服務器集成(見 自訂 MCP)。

本頁涵蓋技能機制(路由與激活)及 Agent 可激活的完整技能目錄。

實際案例功能 頁面各自標註了所激活的技能。安裝技能 展示了外部技能 vendoring 的用戶側操作。

skill-routing diagram

三層結構

上圖展示路由管道:確定性的 L0 路由器、非確定性的 LLM 激活步驟,以及確定性的工具調用層。

L0 路由器是確定性的:相同輸入產生相同目錄。LLM 的 activate_skills 調用是唯一的非確定性步驟。工具調用層(逐次調用的權限等級與涉資金確認)再次迴歸確定性,且它在工具被調用時運行,而非在技能被激活時。因此管道兩端無需 LLM 即可測試,這是有意為之的設計選擇。

L0 路由:確定性預過濾

apps/agent/src/skills/router.ts 中的 buildRoutedCatalog() 接收 TurnRoutingContext,並對每個已註冊技能評分:

信號得分
用戶消息中關鍵詞命中每次 +30,上限 +60
生命週期階段匹配+20
資產類別匹配+15
來自其他命中技能的 co_activate+10
信號來源匹配(cron 輪次)+25
兜底(優先級決勝)100 - priority
負關鍵詞命中−∞
conditions 未通過−∞

任何評分為 -∞ 的技能將從目錄中徹底移除,LLM 不會看到它。conditions 是優雅降級的調節旋鈕:

conditions: {
  requires_env:      ["GLASSNODE_API_KEY"],   // skill hidden without key
  requires_tools:    ["glassnode_metric"],    // skill hidden without tool
  requires_toolsets: ["documents"],
  fallback_for_tools:["web_extract"],         // only surface when web_extract absent
  platforms:         ["darwin", "linux"],     // hide on Windows
}

輸出的 RoutedCatalogEntry[] 攜帶技能得分的原因(如 ["kw:buy", "stage:decide"]);註冊表的 buildCatalogFor() 將其渲染為目錄塊中的內聯提示,供 LLM 參考。

激活:由主 LLM 決定

基礎系統提示詞始終暴露一個元工具:

activate_skills(ids: string[], confirmed?: boolean)

LLM 讀取路由後的目錄,選擇請求所匹配的技能,並調用 activate_skills(["minara.core", "memory-personal"])。工具處理器調用 SkillSession.activate(),後者把這些技能的 playbook 與工具提示加載進提示詞。激活從不詢問用戶,也不運行任何風險門控;所有安全約束都在工具調用層(見下文)。

從機制上看,已加載集合就是最近一次 activate_skills 調用所傳入的內容,所以新的調用會替換上一組。這讓提示詞體積保持有界。它不是工具門:一組基線能力(activate_skillsget_pricesearch_tokensmemory_*todo 等,即 apps/agent/src/skills/session.ts 中的 DEFAULT_ALWAYS_INCLUDE_TOOLS 集合)在沒有任何技能激活時每輪都可調用,主會話中任何其他已註冊工具也可經 tool_invoke 直接觸達。激活關乎發現與 playbook 文字,而非授權。

沒有任何技能是常駐激活的。身份、安全不變量、語言策略、markdown 線協議都在緩存的系統提示詞骨架(apps/agent/src/core/system-prompt-skeleton.ts)中,烘焙進每一輪的前綴。

安全門到底在哪

技能激活從不做任何確認。涉資金與高風險門位於工具調用層,在 apps/agent/src/tools/_security/tier-gate.ts 中,按每個工具的 permissionTier 區分:

等級行為
READ_ONLY立即執行
CONFIRM_ONCE首次使用確認,之後本會話內記住
ALWAYS_CONFIRM每次調用都確認;自主調用需要已存儲的授權
MANUAL_ONLY需要顯式批准;自主調用被拒絕

由於該門控以工具而非技能為鍵,無論工具如何被發現都同樣生效。被篡改的工具輸出回顯 activate_skills 調用也無法轉移資金:激活只加載 playbook 文字,真正的交易工具仍會帶著完整參數上下文撞上 tier 門。Agent Loop 頁面詳細介紹了 hook 鏈(見 Agent 循環)。

生命週期階段

路由器從用戶消息推斷生命週期階段:

階段觸發詞
discover"what's trending", "show me", "price of"
evaluate"should I", "analyze", "compare", "risk"
decide"buy", "sell", "long", "short", "swap"
manage"close", "stop loss", "my positions"

階段用於路由(階段匹配會提升技能的目錄得分),併為工具調用層提供上下文(discover 輪次上的自主來源會收緊 tier 門將執行的內容)。階段不再鉗制哪些技能可以激活;交易邊界由工具 tier 把守,所以將交易調用藏入看似無害的問題中,仍會在執行時撞上確認門。

信號:cron 與 webhook 輪次

cron 觸發或 webhook 推送會構建一個 SignalContext

{
  source: "cron",
  signal_id: "btc_drop_5pct",
  asset: { symbol: "BTC", asset_class: "crypto_major" },
  severity: "warn",
  preload_skills: ["market.watch", "memory.alerts"],
  suggested_stages: ["evaluate"],
  trace_id: "t_abc123",
}

preload_skills 是給路由器的提示,指示其直接激活對應 id 而無需等待 LLM 調用 activate_skills。預加載只加載 playbook 文字,不繞過工具調用層的 tier 門,所以自主的 cron 或 webhook 輪次在執行時仍受約束:從 cron 來源調用 MANUAL_ONLY 工具會被直接拒絕。會話運行時 placement(Preferences computer.backend)固定該聊天的 shell / 文件 / execute_code;模型沒有按次 environment 覆蓋。trace_id 貫穿 WorkflowInstanceSkillAuditRecord 及工具執行日誌,因此"14:03 的 BTC 提醒做了什麼"只需一條 SQL 查詢即可追溯。

編寫優質技能

以下是從內置技能中積累的具體建議:

  • 提示詞片段控制在 800 token(約 3 KB)以內。 過長的提示詞會撐大可緩存的目錄塊,拖慢每次輪次。
  • description 要具體(不超過 80 個字符)。LLM 依據 description 選擇技能;激活後才會看到提示詞。"Perps: open, close, monitor positions on Hyperliquid" 是好示例,"Trading stuff" 則不是。
  • 沒有任何技能是常駐激活的。 若某些內容應在每輪運行(身份、安全、markdown 協議),它屬於 core/system-prompt-skeleton.ts,而非某個技能。
  • 準確設置每個工具的 permissionTier,而非技能。 風險落在工具上,而非技能。不要為了省一次確認而把涉資金工具標成低等級;審查會發現。
  • 為每個外部服務商聲明 conditions.requires_env 註冊表會在缺少密鑰的開發機器上靜默隱藏技能,這是正確行為。
  • 保持 tool_names 精簡。 只列出技能實際使用的工具。擁有 20 個工具的技能,通常是兩個技能硬撐成一個。

參考實現(SKILL.md 包):

外部技能

apps/agent/src/skills/external/ 存放 vendored 的第三方 SKILL.md 包。通過 minara skills add <git-url> 添加,流程如下:

  1. 將倉庫克隆至 apps/agent/src/skills/external/<id>/
  2. 檢測許可證並記錄在 .minara-skill.json 中。
  3. 拒絕添加專有許可證下的內容(歷史案例:Anthropic 的 office skills)。
  4. 啟動時通過 buildExternalDomainSkills() 從 SKILL.md frontmatter 構建 DomainSkill

外部技能與內置技能同等地位,經過相同的註冊表與路由器,其工具撞上同一套工具調用 tier 門,沒有單獨的代碼路徑。


技能目錄

每個內置技能和外部技能的完整目錄都放在參考文檔中。它由每個技能的 SKILL.md 自動生成,因此永遠不會與代碼脫節:

當一種能力兩種形式都有時,優先選擇內置技能。它隨二進制文件一起發佈, 在 CI 中做類型檢查,並直接調用內部工具註冊表。當內置技能沒有覆蓋你需要 的數據源,或你希望獲得上游 SKILL.md 更新而不必等待發版時,再選擇外部技能。


技能系統是 Minara Agent 資金安全模型最直觀的體現。如果要添加涉及資金轉移的技能,在寫任何代碼之前,請先完整走一遍流程(L0 評分、LLM 激活意圖,以及運行確認流程的工具調用 tier 門)。在設計階段發現問題,遠比在錯誤交易發生後打補丁代價要小得多。

本頁目錄