# 工具設計與規則

## 工具設計規則

新增或編輯工具的四條強制規則（build-time 契約來自 `reasoning_guide(topics=["tool_generate"])`，對外部 agent 則以 `tool_generate_guide` 曝露；後續品質由 `code-reviewer` skill 檢查，v1.0.17 起不再內建，需以 `/skill` → `system` 安裝（v1.0.22 前為 `/skills`））：

1. **name 是首要的語意載體** — 自 v1.2.0 起，模型在 `find_tools` 取得 schema 前只看得到工具名稱 —— 除 `claude-code` 外的 provider 看的是每輪的 `Tools` 清單，`claude-code` 同樣只收到名稱，模型就是依 name 挑選工具
2. **description 固定 3 行、60-200 字元** — What（核心動作）／When（觸發時機 vs 替代方案，例：`use for X; Y for Z`）／Precondition（關鍵限制，無則省略）。不放填充語、不用粗體、不放輸出 schema dump。
3. **僅限英文** — 中文只出現在面向使用者的 handler 回傳訊息
4. **選用欄位必須宣告 `default`** — handler 仍需防禦 nil/缺失

觸發條件與同類工具比較是 When 行的必要內容，不是禁止項——只寫核心動作而沒有觸發訊號的 description 視為不完整。Parameter description 須涵蓋 How／When／Example，非平凡型別（object/array/enum）若說明少於 20 字元視為不完整。

## 工具並行標記

`toolRegister.Def` 帶有五個行為旗標：

| 旗標 | 效果 |
|---|---|
| `AlwaysAllow` | 豁免 confirm gate（唯讀工具） |
| `Concurrent` | 選擇加入 Pass 2 fan-out（每次呼叫一個 goroutine） |
| `Background` | 迴圈不等待其結果 |
| `SystemUse` | 內部管理用工具——不出現在一般列表，只有在對 `find_tools(mode=list)` 要求系統工具時才顯示 |
| `Timeout` | 覆寫預設上限（`DEFAULT_TOOL_TIMEOUT`，v1.1.2 起 15 分鐘，先前 1 分鐘）；`NoToolTimeout`（`ask_user` 自 v1.0.23 起使用）取消上限 |

`AlwaysLoad` 旗標已移除；schema 改經 `find_tools` 載入（移除於 v1.2.0）。

加入 `Concurrent: true` 需同時滿足「無副作用」與「上游允許並行」。當前的並行工具集列於執行引擎頁。

## 工具 timeout 矩陣

`toolRegister.Dispatch` 會以工具註冊的 timeout（未覆寫時為 `DEFAULT_TOOL_TIMEOUT`——v1.1.2 起 15 分鐘，先前 1 分鐘）包住每一次呼叫——內建、script 與 MCP 皆然。各 adapter 在此上限內再套自己的限制：

| Adapter | Adapter 預設 | 可設定 | 實際上限 |
|---|---|---|---|
| Built-in | 15 分鐘 | 每個工具的 `Def.Timeout` | `Def.Timeout` |
| Script（`script_*`） | 15 分鐘（v1.1.2 前為 300 秒） | `~/.config/agenvoy/tools/script/<name>/` 的 `tool.json` `"timeout": <seconds>`——同時註冊為 dispatch timeout | `tool.json` 的值，未設定為 15 分鐘 |
| MCP HTTP | Transport `ResponseHeaderTimeout` 15 分鐘（v1.1.2 前為 60 秒） | 無 | 15 分鐘 dispatch 預設 |
| MCP stdio | 無 | 無 | 15 分鐘 dispatch 預設 |

長時間執行的 script 工具每 30 秒向 daemon log 發出 `running name=... elapsed=Ys/Zs` 以利可見性。API 工具 adapter（`api_*`）與其 `Endpoint.Timeout` 已隨使用者自訂 API 工具移除於 v1.3.2。

長時執行的內建工具於註冊時宣告各自上限：`run_command` = 30 分鐘（`RUN_COMMAND_TIMEOUT`；v1.1.2 前為 60 分鐘）、`subagents` = `MAX_SUBAGENT_TIMEOUT_MIN`（30 分鐘，前景 leg）、`download_file` = 註冊 10 分鐘，請求本身由自身參數限制（預設 120 秒、上限 600 秒；v1.3.6 新增的 `render=true` 存網頁不套用此參數）、`generate_audio` = 5 分鐘、`fetch_page` / `search_web` = 90 秒、`http_request` = 由自身參數指定（預設 60 秒、上限 300 秒），仍受 15 分鐘預設約束、`generate_image` = 15 分鐘、`html_template` = 30 秒、`open_file` = 10 秒、`ask_user` = 無上限。`background_command` 與 `background_subagents` 呼叫後立即回傳 task id，因此不另註冊上限；背景指令或 leg 改受各自的 `timeout_min`（1-60 分鐘，預設 60）限制。在 TUI 以外兩者皆被排除。`run_command_background` 已更名為 `background_command`（移除於 v1.3.2）；`run_websocket` 與其 `timeout`（1-1440 分鐘）已移除於 v1.3.2，`subagents` 的 `background` / `timeout_min` 參數也已移除於 v1.3.2，改用 `background_subagents`。

## 憑證自動修復

`store_secret` 為 `SystemUse` 工具，不出現在一般的 `find_tools(mode=list)` 列表；自 v1.2.0 起它和固定組（`find_tools`、`run_tool`、`reasoning_guide`、`write_todo`、`chat_history`、`ask_user`、`write_result`）以外的工具一樣，schema 經 `find_tools` 取得。System prompt 原本的 `§10 Credential auto-heal` 段落已移除；自 v1.2.0 起 system prompt 只留一行短句 —— 憑證存放於 OS keychain（service `agenvoy`），查找方式見 `store_secret`。查找順序（keychain、account = 金鑰名稱，Linux 再查 `~/.config/agenvoy/.secrets`，最後是同名環境變數）、「不會匯出到行程環境變數，因此 `printenv` 為空不代表沒有金鑰」的說明，以及處理流程都寫在該工具自己的 description。遇到認證失敗——缺 key、`401`、`403`、token 過期——agent 從錯誤中取出 key 名稱、呼叫 `store_secret`（透過遮罩輸入取得新值 — 該值永不到達 LLM），再重新呼叫失敗的工具。每個工具每回合上限為兩輪 `store_secret`。
