# 架構

Agenvoy 整體如何組合的高階視角。各模組圖表、序列流程與 tool-dispatch 狀態機請跳至各主題專頁。

## 概覽

```mermaid
graph TB
    subgraph Entry["Entry · cmd/app"]
        App["agen · TUI (socket client) + daemon<br/>agen stop · update · --daemon<br/>non-TTY stdin · MCP server"]
        Web["Web dashboard · page/<br/>embedded in the binary<br/>served at 127.0.0.1 / [::1]:17989"]
        IPC["Daemon IPC · internal/runtime/ipc<br/>~/.config/agenvoy/daemon.sock · 0600<br/>run · pending · cancel · steer · reply · mcp"]
    end

    subgraph Engine["Engine · internal/agents/exec"]
        Run["exec.Prepare · exec.Run<br/>skill match → named skill → exec/model.Route<br/>session model · dispatcher · tiers · priority"]
        Execute["exec.Execute · ≤256 iterations<br/>3-pass parallel tool calls<br/>7 fixed tools loaded, rest by name via run_tool"]
        Sub["exec/subagent.Exec<br/>in-process · max(NumCPU/2, 3) concurrent<br/>background legs (TUI)"]
        Compact["compact · threshold → old history → tool history<br/>overflow → learned limit → decision prune → trim"]
        Decision["decision · internal/agents/decision<br/>TypeSafe / OpenRouter · 3 s typed calls<br/>dispatch · watch · web filter · turn context · summary · trim"]
    end

    subgraph Pending["Pending · internal/runtime"]
        Reg["Prefix-routed listener registry<br/>per-entry buffered=1 reply ch<br/>TUI cli- (per window) · web chat- · Telegram tg- · Discord dc-"]
        BG["Background jobs · internal/tools/interactive<br/>cmd_ · sub_ legs grouped per turn<br/>report to open task · run next when ended · cancel"]
    end

    subgraph Providers["go-llm-router v0.10.2 · 14 provider entries + compat<br/>incl. claude-code · + TypeSafe for decisions"]
        P["OpenAI · Codex · Claude · Gemini<br/>Grok · Grok (xAI) · Copilot · DeepSeek<br/>Mistral · NVIDIA · Ollama Cloud · OpenRouter<br/>Cloudflare · + any OpenAI-compatible endpoint<br/>Claude Code · local claude CLI, opt-in"]
    end

    subgraph Tools["Tool Subsystem · internal/tools"]
        T["find_files · read_files · edit_file · remove_file · restore_file · file_history<br/>search_web · fetch_page · http_request<br/>subagents · schedules · run_skill · ask_user<br/>chat_history · error_history · write_error · find_tools · run_tool<br/>run_command · background_command · background_subagents<br/>public_api_list · reasoning_guide · write_result · html_template"]
        MCP["MCP · internal/runtime/mcp<br/>client + server · go-sdk"]
        Adapter["toolAdapter · internal/runtime<br/>script_* · ext_*"]
    end

    subgraph Security["Security · go-pkg/sandbox"]
        S["bwrap (Linux) / sandbox-exec (macOS)<br/>filesystem.Policy · DeniedMap"]
    end

    subgraph Session["Session · internal/session"]
        SL["history.json · summary.json<br/>action.log · pending/<br/>fsnotify watch"]
    end

    subgraph Memory["Memory · SQLite + ToriiDB"]
        M["history.db · session · message_meta<br/>messages + FTS5 · action_history<br/>file_history · usage + tool call ids<br/>db_0..db_3 · error_memory 90d TTL"]
    end

    subgraph Kura["KuraDB · 使用者自行註冊的 MCP server"]
        K["kura mcp<br/>mcp.json 中的一筆設定<br/>mcp__kura__list_rag · mcp__kura__search_rag"]
    end

    App -->|Unix socket| IPC
    IPC --> Run
    Web --> Run
    Run --> Execute
    Execute -->|subagents| Sub
    Sub -->|exec.Run isSub| Run
    Execute --> Compact
    Execute -->|tool gap · skill filter| Decision
    Compact --> Decision
    Execute -->|Send| Providers
    Execute -->|tool calls| Tools
    Tools --> MCP
    Tools --> Adapter
    Tools --> Security
    Tools -.->|mcp__kura__*<br/>未註冊該伺服器時完全不存在| Kura
    Execute <-->|confirm/ask| Pending
    IPC <-->|ask · reply| Pending
    Sub <-->|subagent ask_user| Pending
    Tools -->|background| BG
    BG -->|resume| Run
    Execute <--> Memory
    Execute <--> Session
```

`run_command_background` 更名為 `background_command`，`run_websocket`、`pkg_manage` 與使用者自訂的 `api_*` 工具已移除（移除於 v1.3.2）；請改用 `background_command`、帶 `sudo` 或 `sandbox: false` 的 `run_command`，以及內建的 `public_api_list`。

## 橫切原則

- **OS-native sandbox 優於 Go 側 filter** — 安全 policy 在 OS 邊界強制執行；新限制放進 `go-pkg/sandbox`，不進 agenvoy caller
- **Prompt 即 policy** — system-prompt 保護（來自 `configs/jsons/guardrail_rules.json` 的 guardrail 規則）與跨工具的輸出規範住在 `configs/prompts/` 下的 system prompt，哪個需求用哪個工具則寫在該工具自己的 description；新增類別意味編輯 prompt 或 description，而非 engine。permission mode 已不再寫進 system prompt（移除於 v1.3.7），改由 confirm gate 強制執行
- **subagent 走 in-process 而非 HTTP** — `subagents(mode=invoke)` 經 `exec/subagent.Exec` 直接呼叫 `exec.Run(..., isSub=true)`，共用同一組 provider client、sandbox、pending registry 與 memory 層；`AllowAll` 與 `WorkDir` 透過 ctx 流動
- **read tool 扇出、write tool 序列化** — 並行為 opt-in，且同時要求「無副作用」與「上游允許並行」
- **每個關注點一層 config** — provider 憑證在 OS keychain、已註冊 model、優先序、tier 與 limits 在 `config.json`、MCP 在 `mcp.json`、session 設定與 persona 在 SQLite `session` 表；每位 tool 作者／使用者最多動一個地方
- **單一 daemon 執行所有 agent** — 瀏覽器儀表板、聊天通道與外部呼叫端透過 `127.0.0.1:17989`（另有 `[::1]:17989`）的 HTTP 連到 daemon；v1.2.0 起 TUI 不再自行執行 agent 或開啟 MCP 連線，改經 Unix socket `~/.config/agenvoy/daemon.sock`（權限 0600、以換行分隔的 JSON）送出執行、pending 續行、取消、steer、回覆與 `/mcp` 操作。儀表板為內嵌而非外部託管，因此沒有第二個來源需要同步
- **廠商程式碼留在上游** — provider adapter 已移至 `go-llm-router`、MCP 協定改用官方 go-sdk；修正應進上游模組，而非在本地加 shim
