# Tool Agent 设计文档

## 1. 概述

- 项目名称：tool_agent
- 目标：可自动封装、接入、部署、编写工具的 Agent + 工具库系统
- 目标用户：其他 Agent 系统（作为工具供应商）

## 2. 系统架构

tool_agent 由三个核心角色协作：

```
┌─────────────────────────────────────────────────────────┐
│                    RouterAgent（常驻）                    │
│  main 启动时即运行，负责：                                │
│  - 对外接口（FastAPI: /health, /tools, /run_tool, /chat）│
│  - CodingAgent 调度（接收任务书 → 创建工具）             │
│  - 工具注册表 + 状态管理                                 │
│  - 全局状态监控（工具/CodingAgent/ServiceAgent 窗口）    │
├─────────────────────────────────────────────────────────┤
│                  ServiceAgent（按需创建）                 │
│  每个 chat_id 对应一个独立对话 session：                  │
│  - 只读查询工具表、工具组、后端运行时、状态              │
│  - 与外部 Agent 交流，解答工具使用问题                   │
│  - 撰写任务书 → 提交给 RouterAgent                      │
│  - 一个实例，多个 chat_id 窗口并发                       │
├─────────────────────────────────────────────────────────┤
│                  CodingAgent（按需唤醒）                  │
│  接收 RouterAgent 的任务书：                              │
│  - 自主编码、测试、部署工具                              │
│  - 注册工具到 Registry                                   │
└─────────────────────────────────────────────────────────┘
```

### 2.1 调用层与后端执行环境

所有工具对外统一为 **本地 Python/FastAPI 调用层**（uv 管理），
内部后端执行环境（backend_runtime）分三类：

```
外部调用者（其他 Agent / HTTP 客户端）
  │
  ▼
统一调用层（本地 Python + FastAPI HTTP 接口）
  │
  ├─ backend_runtime: local   → 本地 Python 运行时（纯 uv 子进程）
  ├─ backend_runtime: docker  → Docker 容器运行时
  └─ backend_runtime: remote  → 远程 API / 云端服务
```

### 2.2 消息流

```
外部 Agent
  │
  ├─ IM 消息 ──→ IMClient ──→ ChatWindow(chat_id) ──→ SessionManager ──→ ServiceAgent
  │                                                                          │
  ├─ HTTP /chat ─────────────────────────────────────→ SessionManager ──→ ServiceAgent
  │                                                                          │
  │                                                    需要创建工具时：       │
  │                                                    submit_task() ────→ RouterAgent
  │                                                                          │
  │                                                                    CodingAgent
  │                                                                          │
  └─ HTTP /run_tool ──→ Dispatcher ──→ 工具进程 ←── 注册完成 ←──────────────┘
```

### 2.3 工具组（Tool Group）

需要固定配合使用的工具组成工具组，定义在 `data/groups.json`。
例如 RunComfy 生命周期管理组：launch → run → stop。

## 3. 三层架构

```
外部 Agent 请求
       │
       ▼
┌─────────────────────────────────────┐
│        注册层 (Registry)             │
│  - 工具元数据 CRUD (registry.json)   │
│  - 工具组管理 (groups.json)          │
│  - 按类别/关键字/后端运行时搜索      │
└──────────────┬──────────────────────┘
               │
               ▼
┌─────────────────────────────────────┐
│   路由层 (Router) — 兼任对外网关     │
│  - FastAPI 对外接口                  │
│  - 来源管理 (SourceStore)            │
│  - 工具启停 (ToolStatusManager)      │
│  - 请求分发 (Dispatcher)             │
│  - CodingAgent 调度                  │
│  - 全局状态监控                      │
└──────────────┬──────────────────────┘
               │
               ▼
┌─────────────────────────────────────┐
│        运行层 (Runtime)              │
│  - LocalRunner (uv 本地进程)         │
│  - DockerRunner (Docker 容器)        │
│  - 远程 API 直接转发                 │
└─────────────────────────────────────┘
```

## 4. 对外接口

仅暴露 4 个 HTTP 接口：

| 接口 | 方法 | 说明 |
|------|------|------|
| `/health` | GET | 健康检查 |
| `/tools` | GET | 完整工具表（含后端分类、工具组、运行状态） |
| `/run_tool` | POST | 调用工具 `{tool_id, params}` |
| `/chat` | POST | 与 ServiceAgent 对话 `{message, chat_id}` |

### 4.1 /tools 响应示例

```json
{
  "backend_runtimes": [
    {"backend_runtime": "local", "name": "本地 Python 运行时", "tool_count": 5},
    {"backend_runtime": "docker", "name": "Docker 容器运行时", "tool_count": 0},
    {"backend_runtime": "remote", "name": "远程 API / 云端服务", "tool_count": 0}
  ],
  "groups": [
    {
      "group_id": "runcomfy_lifecycle",
      "name": "RunComfy 生命周期管理",
      "tool_ids": ["launch_comfy_env", "runcomfy_workflow_executor", "runcomfy_stop_env"],
      "usage_order": ["launch_comfy_env", "runcomfy_workflow_executor", "runcomfy_stop_env"]
    }
  ],
  "tools": [
    {
      "tool_id": "image_stitcher",
      "name": "图片拼接工具",
      "category": "cv",
      "backend_runtime": "local",
      "group_ids": [],
      "state": "stopped"
    }
  ]
}
```

### 4.2 /chat 请求/响应

```json
// 请求
{"message": "有哪些图片处理工具？", "chat_id": "user_A_window_1"}

// 响应
{"response": "当前有 image_stitcher...", "chat_id": "user_A_window_1"}
```

## 5. 内部通信

### 5.1 来源类型（SourceType）

| SourceType | 说明                    | 通信方式                            |
| ---------- | ----------------------- | ----------------------------------- |
| `local`    | 本地 uv 项目            | `uv run` 启动 HTTP 服务，httpx 调用 |
| `docker`   | Docker 容器             | 端口映射 HTTP                       |
| `remote`   | 远程 API / 云端服务     | 直接转发 HTTP                       |

### 5.2 请求分发流程

```
POST /run_tool {tool_id, params}
       │
       ▼
ToolStatusManager.get_status(tool_id)
       │ 未运行？
       ▼
ToolStatusManager.start_tool(tool_id)
  ├─ local:  uv run python main.py --port {free_port}
  ├─ docker: 检查容器端口映射
  └─ remote: 直接标记 running
       │
       ▼
Dispatcher.dispatch(tool_id, params)
  → httpx.post("http://127.0.0.1:{port}{endpoint_path}", json=params)
       │
       ▼
返回结果
```

### 5.3 端口分配

```
对外（固定）:
  8001        - FastAPI

对内（动态）:
  uv 本地工具  - 随机空闲端口（socket bind 0）
  Docker 工具  - 容器内部端口映射
  远程工具     - 无需端口，直接转发
```

## 6. Agent 角色详解

### 6.1 RouterAgent

常驻进程，main 启动时即运行。

**职责**：
- 管理工具注册表（Registry）和状态表（ToolStatusManager）
- 调度 CodingAgent 执行工具创建任务
- 监控全局状态（工具、CodingAgent 任务、ServiceAgent 窗口）
- 对外暴露 FastAPI 接口

**全局状态查询** (`router.get_system_status()`)：

```json
{
  "tools": {"total": 5, "active": 5},
  "coding_agent": {
    "running_count": 1,
    "running_task_ids": ["create_a1b2c3d4"],
    "queued_count": 0,
    "recent_tasks": [
      {"task_id": "create_a1b2c3d4", "status": "pending", "task_spec": "..."}
    ]
  },
  "service_agent": {
    "total_windows": 3,
    "im_connected": true,
    "windows": [
      {"chat_id": "user_A_w1", "sdk_session_id": "...", "has_im_window": true}
    ]
  }
}
```

### 6.2 ServiceAgent

按需创建，一个实例管理多个 chat_id 窗口。

**职责**：
- 只读查询工具表、工具组、后端运行时、工具状态
- 与外部 Agent 对话，解答工具使用问题
- 撰写任务书提交给 RouterAgent

**工具列表**（6 个）：

| 工具 | 权限 | 说明 |
|------|------|------|
| `list_tools` | 读 | 列出所有工具 |
| `get_tool_details` | 读 | 查看工具详情（参数、Schema） |
| `list_groups` | 读 | 列出工具组及使用顺序 |
| `list_backend_runtimes` | 读 | 列出后端执行环境类型 |
| `check_task_status` | 读 | 查询任务进度 |
| `submit_task` | 写 | 撰写任务书提交给 RouterAgent |

**会话管理**：
- SessionManager 按 chat_id 管理 Claude SDK session
- 每个 chat_id 独立的对话记忆（通过 SDK resume 机制）
- 同一个 ServiceAgent 实例并发处理多个窗口

### 6.3 CodingAgent

按需唤醒，接收 RouterAgent 的任务书。

**工具列表**（10 个）：

| 分类   | 工具                   | 说明                              |
| ------ | ---------------------- | --------------------------------- |
| Docker | `create_docker_env`    | 创建容器（端口映射/挂载/GPU）     |
| Docker | `run_in_docker`        | 容器内执行命令（前台/后台）       |
| Docker | `rebuild_docker_ports` | 重建容器加端口映射                |
| Docker | `destroy_docker_env`   | 销毁容器                          |
| uv     | `create_uv_project`    | 创建 uv 项目                      |
| uv     | `run_in_uv`            | 在 uv 环境中运行命令              |
| uv     | `uv_add_dependency`    | 添加依赖                          |
| 文件   | `write_file`           | 写文件（overwrite/append）        |
| 文件   | `read_file`            | 读文件                            |
| 注册   | `register_tool`        | 注册工具到 Registry               |

## 7. IM Client 接入

### 7.1 架构

```
IM Server (WebSocket, port 8000)
    ↕
IMClient (单 WebSocket 连接，contact_id="tool_agent")
    ├─ ChatWindow(chat_id_1) ──→ SessionManager ──→ ServiceAgent session_1
    ├─ ChatWindow(chat_id_2) ──→ SessionManager ──→ ServiceAgent session_2
    └─ ChatWindow(chat_id_3) ──→ SessionManager ──→ ServiceAgent session_3
```

### 7.2 消息路由

- 外部 Agent 发送消息时指定 `receiver_chat_id`，定向到对应窗口
- 未指定 `receiver_chat_id` 时广播到所有窗口
- 回复时带上 `receiver_chat_id = sender_chat_id`，消息回到对方窗口

### 7.3 并发模型

- 一个 IMClient 实例管理多个 ChatWindow
- 每个 ChatWindow 有独立的 `pending.json` / `chatbox.jsonl`
- SessionManager 收到通知后，按 chat_id 路由到对应 ServiceAgent session
- 同一个 ServiceAgent 实例并发处理，Claude SDK session 隔离对话记忆

## 8. 数据模型

### 8.1 ToolMeta（工具元数据）

```json
{
  "tool_id": "image_stitcher",
  "name": "图片拼接工具",
  "description": "将多张图片拼接成一张",
  "category": "cv",
  "backend_runtime": "local",
  "group_ids": [],
  "input_schema": {},
  "output_schema": {},
  "stream_support": false,
  "status": "active"
}
```

### 8.2 ToolSource（工具来源）

```json
{
  "type": "local",
  "host_dir": "tools/local/image_stitcher",
  "endpoint_path": "/",
  "http_method": "POST",
  "internal_port": 0
}
```

### 8.3 ToolRoute（运行状态）

```json
{
  "tool_id": "image_stitcher",
  "sources": [{"type": "local", "host_dir": "..."}],
  "active_source": 0,
  "state": "running",
  "pid": 12345,
  "port": 52341
}
```

### 8.4 BackendRuntime（后端执行环境枚举）

| 值 | 说明 |
|----|------|
| `local` | 本地 Python 运行时（纯 uv 子进程） |
| `docker` | Docker 容器运行时 |
| `remote` | 远程 API / 云端服务 |

### 8.5 ToolGroup（工具组）

```json
{
  "group_id": "runcomfy_lifecycle",
  "name": "RunComfy 生命周期管理",
  "description": "云端 ComfyUI 环境的完整生命周期",
  "category": "remote",
  "tool_ids": ["launch_comfy_env", "runcomfy_workflow_executor", "runcomfy_stop_env"],
  "usage_order": ["launch_comfy_env", "runcomfy_workflow_executor", "runcomfy_stop_env"],
  "usage_example": "先 launch 获取 server_id，再 run 执行 workflow，最后 stop 释放资源"
}
```

## 9. 目录结构

```
src/
├── tool_agent/
│   ├── __main__.py              # 入口：启动 Router + SessionManager + IM
│   ├── config.py                # 全局配置
│   ├── models.py                # 数据模型（ToolMeta, BackendRuntime 等）
│   ├── router/
│   │   ├── agent.py             # RouterAgent（常驻，调度 CodingAgent）
│   │   ├── server.py            # FastAPI 接口定义
│   │   ├── dispatcher.py        # 请求分发
│   │   └── status.py            # 工具状态管理 + 来源存储
│   ├── service/
│   │   ├── agent.py             # ServiceAgent（只读客服 + 任务书提交）
│   │   └── session.py           # SessionManager（chat_id 会话管理 + IM 接入）
│   ├── registry/
│   │   ├── registry.py          # 工具注册表
│   │   └── groups.py            # 工具组管理
│   ├── tool/
│   │   └── agent.py             # CodingAgent（自主编码部署）
│   └── runtime/
│       └── local_runner.py      # 本地 uv 运行器
├── im-client/                   # IM 通信客户端（独立模块）
│   ├── client.py                # IMClient + ChatWindow
│   ├── protocol.py              # 消息协议
│   ├── notifier.py              # 通知接口
│   └── tools.py                 # Agent 工具函数封装
data/
├── registry.json                # 工具注册表
├── sources.json                 # 工具来源
└── groups.json                  # 工具组配置
```

## 10. 启动流程

```python
async def main():
    router = Router()                          # RouterAgent 初始化
    session_mgr = SessionManager(router)       # 会话管理
    router.set_session_manager(session_mgr)    # 双向引用
    router.create_app(session_manager=session_mgr)

    await session_mgr.start_im("tool_agent", "ws://localhost:8000")  # IM 连接（可选）
    await router.start(port=8001)              # FastAPI 启动
```

启动命令：`uv run python -m tool_agent`

## 11. KnowHub 工具表集成

### 11.1 双向索引架构

Tool Agent 与 KnowHub 工具表通过双向索引互相关联：

```
Tool Agent Registry              KnowHub 工具表
┌─────────────────────┐         ┌──────────────────────────┐
│ tool_id: launch_env │◄────────│ id: tools/image_gen/     │
│ tool_slug_ids:      │         │     comfyui              │
│   ["comfyui"]       │────────►│ toolhub_items:           │
│                     │         │   [{launch_env: "..."},  │
│ group_ids:          │         │    {runcomfy_group: ...}]│
│   ["runcomfy_group"]│         └──────────────────────────┘
└─────────────────────┘
```

**字段说明**：
- `tool_slug_ids: list[str]` - Tool Agent 工具关联的 KnowHub tool_slug 列表
- `toolhub_items: list[dict]` - KnowHub 工具关联的 Tool Agent 工具/组列表

### 11.2 智能匹配机制

Router Agent 在 CodingAgent 注册完工具后，自动执行智能匹配：

**匹配规则**：
1. 工具名称/ID 包含 KnowHub 的 slug 或 title
2. 工具描述包含 KnowHub 描述的关键词
3. 分类匹配

**自动更新流程**：
```python
# router/agent.py:_sync_knowhub_after_register()
1. 遍历所有 registry 工具
2. 调用 _match_knowhub_tools() 智能匹配
3. 更新 registry.tool_slug_ids
4. 收集工具和组，更新 KnowHub.toolhub_items
5. 点亮 KnowHub 工具 status="已接入"
```

**相关文件**：
- `src/tool_agent/models.py:58` - ToolMeta.tool_slug_ids 字段定义
- `src/tool_agent/router/agent.py:115-217` - 智能匹配和同步逻辑
- `src/tool_agent/tool_table.py` - KnowHub API 客户端
- `docs/tool_table/tool-table-integration.md` - 详细集成文档

## 12. 里程碑

| 阶段    | 内容                                           | 状态      |
| ------- | ---------------------------------------------- | --------- |
| Phase 1 | Router + Registry + FastAPI + CodingAgent      | ✅ 已完成 |
| Phase 2 | LocalRunner + DockerRunner + 请求分发          | ✅ 已完成 |
| Phase 3 | 工具分类 + 工具组 + BackendRuntime 语义统一    | ✅ 已完成 |
| Phase 4 | ServiceAgent + SessionManager + IM Client 接入 | ✅ 已完成 |
| Phase 5 | KnowHub 工具表集成 + 智能匹配                  | ✅ 已完成 |
| Phase 6 | 冷热调度集成 + 健康检查集成                    | 🔲 待集成 |
| Phase 7 | 中间件集成（鉴权/缓存/计量）                   | 🔲 待集成 |
| Phase 8 | 自修复 + Browser-Use + 财务管理                | 🔲 待实现 |
