技能系統
路由與激活的工作原理,以及完整的可用技能目錄
技能是 Minara Agent 的能力單元。每個技能包含一段提示詞片段、一份工具白名單,以及一組告訴路由器該技能何時相關的元數據。技能是發現與 playbook 的入口:激活它會把該領域的工具暴露出來,並拉入使用這些工具的指引(何時該用哪個工具、某個工作流背後的方法論、它所依託的領域理論)。它不是工具授權門。普通會話裡每個已註冊工具都可直接調用;加載技能只是幫模型找到合適的工具並讀到 playbook。可以把技能理解為 Agent 按需加載的插件。
為何不用 MCP? Minara 的核心能力使用自有技能與工具註冊表(而非 MCP),原因是金融工具需要逐次調用的權限等級、類型化 schema 以及 MCP 規範未覆蓋的涉資金確認門。外部服務商仍通過 MCP 服務器集成(見 自訂 MCP)。
本頁涵蓋技能機制(路由與激活)及 Agent 可激活的完整技能目錄。
實際案例:功能 頁面各自標註了所激活的技能。安裝技能 展示了外部技能 vendoring 的用戶側操作。
三層結構
上圖展示路由管道:確定性的 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_skills、get_price、search_tokens、memory_*、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 貫穿 WorkflowInstance、SkillAuditRecord 及工具執行日誌,因此"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 包):
- 工具密集型技能:
minara-perps/ - 提示詞密集型技能:
deep-research/ - 方法論透鏡技能:
analysis/
外部技能
apps/agent/src/skills/external/ 存放 vendored 的第三方 SKILL.md 包。通過 minara skills add <git-url> 添加,流程如下:
- 將倉庫克隆至
apps/agent/src/skills/external/<id>/。 - 檢測許可證並記錄在
.minara-skill.json中。 - 拒絕添加專有許可證下的內容(歷史案例:Anthropic 的 office skills)。
- 啟動時通過
buildExternalDomainSkills()從 SKILL.md frontmatter 構建DomainSkill。
外部技能與內置技能同等地位,經過相同的註冊表與路由器,其工具撞上同一套工具調用 tier 門,沒有單獨的代碼路徑。
技能目錄
每個內置技能和外部技能的完整目錄都放在參考文檔中。它由每個技能的 SKILL.md 自動生成,因此永遠不會與代碼脫節:
當一種能力兩種形式都有時,優先選擇內置技能。它隨二進制文件一起發佈, 在 CI 中做類型檢查,並直接調用內部工具註冊表。當內置技能沒有覆蓋你需要 的數據源,或你希望獲得上游 SKILL.md 更新而不必等待發版時,再選擇外部技能。
技能系統是 Minara Agent 資金安全模型最直觀的體現。如果要添加涉及資金轉移的技能,在寫任何代碼之前,請先完整走一遍流程(L0 評分、LLM 激活意圖,以及運行確認流程的工具調用 tier 門)。在設計階段發現問題,遠比在錯誤交易發生後打補丁代價要小得多。