diff --git a/plans/agent-api-integration-plan.md b/plans/agent-api-integration-plan.md deleted file mode 100644 index 94afc79..0000000 --- a/plans/agent-api-integration-plan.md +++ /dev/null @@ -1,191 +0,0 @@ -# AI Agent Manager API 集成计划 - -## 概述 - -将项目中的 Agent 管理功能与新的 AI Agent Manager API 集成,实现真正的 Kubernetes Pod 部署和资源管控。 - -## 当前状态分析 - -### 现有实现 -- **Agent 数据模型** ([`models.py`](../services/mcp-server/models.py:122)):数据库级别的 Agent 记录 -- **Agent 路由** ([`agents.py`](../services/mcp-server/app/routes/agents.py:1)):CRUD 操作,无真正 K8s 部署 -- **资源管控** ([`resource_control.py`](../services/mcp-server/app/resource_control.py:1)):配额检查和速率限制 -- **部署功能** ([`user.py:deploy_agent`](../services/mcp-server/app/routes/user.py:327)):仅模拟,未实际调用 K8s - -### 新 API 能力 -- 真正的 Kubernetes Pod 创建/删除/查询 -- 模板系统(echo_agent, jina_search_agent, mysql_agent 等) -- 资源配置(cpu_request, cpu_limit, memory_request, memory_limit) -- Pod 状态监控和访问信息 - -## 架构设计 - -```mermaid -flowchart TB - subgraph Frontend[前端] - UI[用户界面] - end - - subgraph MCPServer[MCP Server] - AgentRoutes[Agent 路由] - ResourceControl[资源管控] - AgentClient[Agent Manager 客户端] - DB[(PostgreSQL)] - end - - subgraph K8sCluster[Kubernetes 集群] - AgentManager[AI Agent Manager API] - AgentPods[Agent Pods] - end - - UI --> AgentRoutes - AgentRoutes --> ResourceControl - ResourceControl --> AgentClient - AgentClient --> AgentManager - AgentManager --> AgentPods - AgentRoutes --> DB -``` - -## 实施任务清单 - -### 阶段一:创建 Agent Manager 客户端 - -- [x] **1.1** 创建 `services/mcp-server/app/agent_manager_client.py` - - 封装对 AI Agent Manager API 的 HTTP 调用 - - 支持健康检查、模板列表、创建/删除/查询 Agent - - 使用 httpx 异步客户端 - - 配置通过环境变量 `AGENT_MANAGER_URL` 设置 - -- [x] **1.2** 创建请求/响应模型(集成到 `schemas.py`) - - K8sResourceConfig(cpu_request, cpu_limit, memory_request, memory_limit, env) - - AgentStatusResponse(Pod 状态、IP、端点信息) - - AgentMetricsResponse(资源使用情况) - - TemplateInfo, TemplateListResponse - -### 阶段二:修改 Agent 路由 - -- [x] **2.1** 更新 `services/mcp-server/app/routes/agents.py` - - 修改 `create_agent` 函数: - - 保留资源管控检查 - - 调用 Agent Manager API 创建 Pod - - 同步更新数据库记录(添加 pod_name, pod_ip, template 等字段) - - 新增 `delete_agent` 函数:调用 API 删除 Pod - - 新增 `get_agent_status` 函数:获取 Pod 实时状态 - - 新增 `get_agent_metrics` 函数:获取资源使用情况 - - 新增 `list_templates` 和 `get_template` 函数 - -- [x] **2.2** 更新 Agent 数据模型 `services/mcp-server/models.py` - - 添加字段:`pod_name`, `pod_ip`, `template`, `service_port` - - 添加字段:`cpu_request`, `cpu_limit`, `memory_request`, `memory_limit` - - 添加字段:`k8s_status`(Pending, Running, Failed 等) - - 添加字段:`k8s_namespace`, `access_url`, `endpoints`, `env_config`, `pod_created_at` - -- [x] **2.3** 创建数据库迁移脚本 - - `services/mcp-server/migrations/004_add_k8s_agent_fields.sql` - -### 阶段三:更新资源管控 - -- [ ] **3.1** 更新 `services/mcp-server/app/resource_control.py` - - 添加 Agent 资源配额检查(用户可创建的 Agent 数量限制) - - 添加 CPU/内存总量限制检查 - - 集成 Agent Manager 的 metrics API 获取实际资源使用 - -- [x] **3.2** 更新 `services/mcp-server/app/routes/admin.py` - - 修改 `update_agent_config` 函数: - - 支持更新 cpu_request, cpu_limit, memory_request, memory_limit - - 注意:已运行的 Pod 需要重新创建才能更新资源配置 - -### 阶段四:更新用户侧功能 - -- [x] **4.1** 更新 `services/mcp-server/app/routes/user.py` - - 修改 `deploy_agent` 函数:调用 Agent Manager API - - 修改 `generate_tool` 函数:支持自定义资源配置(待完成) - -- [x] **4.2** 更新 `services/mcp-server/app/schemas.py` - - 更新 `UpdateAgentConfigRequest`:添加 K8s 资源配置字段 - -### 阶段五:模板管理 - -- [x] **5.1** 模板路由已集成到 `services/mcp-server/app/routes/agents.py` - - `GET /agents/templates`:获取可用模板列表 - - `GET /agents/templates/{name}`:获取模板详情和所需环境变量 - -- [ ] **5.2** 更新路由注册 `services/mcp-server/app/routes/__init__.py`(无需修改,已自动包含) - -### 阶段六:资源监控集成 - -- [ ] **6.1** 更新 `services/mcp-server/app/routes/resource_monitoring.py` - - 集成 Agent Manager 的 `/agents/{name}/metrics` API - - 提供实时 Pod 资源使用数据 - -- [ ] **6.2** 更新 `services/mcp-server/app/routes/monitoring.py` - - 添加 Agent Pod 健康状态监控 - - 添加 Agent Manager 服务健康检查 - -### 阶段七:配置和部署 - -- [x] **7.1** 更新环境变量配置 - - `.env.example`:添加 `AGENT_MANAGER_URL` - - `services/mcp-server/config.py`:添加配置项 - -- [ ] **7.2** 更新 Kubernetes 部署配置 - - `k8s/mcp-server.yaml`:添加环境变量 - - `k8s/configmap.yaml`:添加 Agent Manager URL 配置 - -- [ ] **7.3** 更新 Docker Compose 配置 - - `docker-compose.yml`:添加 Agent Manager 服务依赖 - -## API 映射关系 - -| MCP Server 功能 | AI Agent Manager API | 说明 | -|----------------|---------------------|------| -| 创建 Agent | `POST /agents` | 创建 K8s Pod | -| 删除 Agent | `DELETE /agents/{name}` | 删除 K8s Pod | -| 获取 Agent 状态 | `GET /agents/{name}/status` | 获取 Pod 状态和 IP | -| 获取资源使用 | `GET /agents/{name}/metrics` | 获取 CPU/内存配置 | -| 列出所有 Agent | `GET /agents` | 列出所有 Pod | -| 获取模板列表 | `GET /templates` | 获取可用模板 | -| 获取模板详情 | `GET /templates/{name}` | 获取模板所需参数 | - -## 资源配置映射 - -| 用户配置 | API 参数 | 默认值 | -|---------|---------|-------| -| CPU 请求 | `cpu_request` | `100m` | -| CPU 限制 | `cpu_limit` | `500m` | -| 内存请求 | `memory_request` | `128Mi` | -| 内存限制 | `memory_limit` | `512Mi` | - -## 需要新增的接口 - -根据业务需求,建议新增以下接口: - -1. **Agent 日志查询** - - `GET /agents/{name}/logs` - 获取 Pod 日志 - - 需要 Agent Manager API 支持 - -2. **Agent 重启** - - `POST /agents/{name}/restart` - 重启 Pod - - 可通过删除后重新创建实现 - -3. **Agent 扩缩容** - - `PUT /agents/{name}/scale` - 调整副本数 - - 需要 Agent Manager API 支持 replicas 参数 - -4. **批量操作** - - `POST /agents/batch/create` - 批量创建 - - `DELETE /agents/batch` - 批量删除 - -## 注意事项 - -1. **数据一致性**:数据库记录和 K8s Pod 状态需要保持同步 -2. **错误处理**:API 调用失败时需要回滚数据库操作 -3. **权限控制**:保留现有的资源管控和权限检查 -4. **向后兼容**:保留现有 API 接口格式,扩展返回字段 - -## 测试计划 - -- [ ] 单元测试:Agent Manager 客户端 -- [ ] 集成测试:创建/删除/查询 Agent 流程 -- [ ] 端到端测试:前端到 K8s Pod 完整流程 -- [ ] 性能测试:并发创建 Agent 场景 diff --git a/plans/agent-design-refactor-plan.md b/plans/agent-design-refactor-plan.md deleted file mode 100644 index e9107fb..0000000 --- a/plans/agent-design-refactor-plan.md +++ /dev/null @@ -1,374 +0,0 @@ -# Agent 设计重构计划 - -## 概述 - -根据业务需求重新设计 Agent 系统,明确区分**平台端 Agent** 和**自定义 Agent** 两种类型,并完善资源分配和监控机制。 - -## 当前问题分析 - -### 现有设计的问题 - -1. **Agent 类型定义模糊** - - 当前 [`Agent.type`](services/mcp-server/models.py:130) 字段只有 `platform` 和 `custom` 两个值 - - 但没有明确区分两种 Agent 的部署方式和资源管理逻辑 - -2. **资源分配逻辑不完整** - - 渠道的 [`custom_agent_cpu`](services/mcp-server/models.py:305) 和 [`custom_agent_memory`](services/mcp-server/models.py:306) 字段被当作"默认值"使用 - - 实际应该是"资源配额上限",租户在配额内创建多个自定义 Agent - -3. **资源统计不完整** - - [`get_admin_dashboard_stats`](services/mcp-server/app/routes/admin.py:375) 只统计了平台端 Agent - - 应该同时统计平台端 Agent + 自定义 Agent - -4. **健康监控不完整** - - [`monitor_agents`](services/mcp-server/app/routes/admin.py:1299) 只监控 `type == "platform"` 的 Agent - - 应该同时监控平台端 Agent + 自定义 Agent - -## 新设计方案 - -### 1. Agent 类型定义 - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ Agent 类型 │ -├─────────────────────────────────────────────────────────────────┤ -│ │ -│ ┌─────────────────────────┐ ┌─────────────────────────────┐ │ -│ │ 平台端 Agent │ │ 自定义 Agent │ │ -│ │ type=platform │ │ type=custom │ │ -│ ├─────────────────────────┤ ├─────────────────────────────┤ │ -│ │ - 平台打镜像到仓库 │ │ - 租户上传自己的程序 │ │ -│ │ - K8s 部署管理 │ │ - 在分配的资源配额内运行 │ │ -│ │ - 管理员分配给渠道 │ │ - 渠道分配资源配额给租户 │ │ -│ │ - 渠道分配给租户 │ │ - 租户可创建多个 Agent │ │ -│ └─────────────────────────┘ └─────────────────────────────┘ │ -│ │ -└─────────────────────────────────────────────────────────────────┘ -``` - -### 2. 资源分配流程 - -```mermaid -flowchart TB - subgraph Platform[平台层] - Admin[超级管理员] - PlatformAgents[平台端Agent镜像仓库] - CustomQuota[自定义Agent资源池] - end - - subgraph ChannelLayer[渠道层] - Channel[渠道] - ChannelPlatformAgents[分配的平台端Agent] - ChannelCustomQuota[分配的自定义Agent配额] - end - - subgraph TenantLayer[租户层] - Tenant[租户] - TenantPlatformAgents[可用的平台端Agent] - TenantCustomAgents[创建的自定义Agent] - end - - Admin -->|分配平台端Agent| Channel - Admin -->|分配自定义Agent配额| Channel - PlatformAgents --> ChannelPlatformAgents - CustomQuota --> ChannelCustomQuota - - Channel -->|分配平台端Agent| Tenant - Channel -->|分配自定义Agent配额| Tenant - ChannelPlatformAgents --> TenantPlatformAgents - ChannelCustomQuota --> TenantCustomAgents - - Tenant -->|使用| TenantPlatformAgents - Tenant -->|在配额内创建多个| TenantCustomAgents -``` - -### 3. 数据模型修改 - -#### 3.1 Channel 模型修改 - -当前字段: -- `custom_agent_cpu` - 自定义 Agent CPU(当前作为默认值) -- `custom_agent_memory` - 自定义 Agent 内存(当前作为默认值) - -修改为: -- `custom_agent_cpu_quota` - 自定义 Agent CPU 配额上限 -- `custom_agent_memory_quota` - 自定义 Agent 内存配额上限 - -#### 3.2 新增 TenantCustomAgentQuota 模型 - -```python -class TenantCustomAgentQuota(BaseModel, Base): - """租户自定义 Agent 资源配额""" - __tablename__ = "tenant_custom_agent_quotas" - - tenant_id = Column(GUID, ForeignKey users.id, nullable=False, unique=True) - - # 配额上限(由渠道分配) - cpu_quota = Column(Numeric 12 2, default=0) # CPU 核心数上限 - memory_quota = Column(Numeric 12 2, default=0) # 内存 GB 上限 - - # 已使用量(由系统计算) - cpu_used = Column(Numeric 12 2, default=0) # 已使用 CPU - memory_used = Column(Numeric 12 2, default=0) # 已使用内存 - agent_count = Column(Integer, default=0) # 已创建的自定义 Agent 数量 -``` - -#### 3.3 Agent 模型增强 - -在 [`Agent`](services/mcp-server/models.py:125) 模型中添加: - -```python -# 自定义 Agent 特有字段 -image_url = Column(String 500) # 用户上传的镜像地址 -program_path = Column(String 500) # 程序路径 -runtime_type = Column(String 50) # 运行时类型:python, nodejs, docker 等 -``` - -### 4. API 修改 - -#### 4.1 渠道资源管理 API - -修改 [`allocate_channel_resources`](services/mcp-server/app/routes/admin.py:875): - -```python -# 请求体增加 -class ChannelResourceAllocation: - # 现有字段... - customAgentQuota: CustomAgentQuotaConfig # 新增 - -class CustomAgentQuotaConfig: - cpuQuota: float # CPU 配额上限 - memoryQuota: float # 内存配额上限 -``` - -#### 4.2 租户资源分配 API - -修改 [`allocate_tenant_resources`](services/mcp-server/app/routes/channel.py:193): - -```python -# 请求体增加 -class AllocateResourcesRequest: - # 现有字段... - customAgentQuota: Optional[CustomAgentQuotaConfig] # 新增 -``` - -#### 4.3 自定义 Agent 创建 API - -修改用户创建自定义 Agent 的逻辑,增加配额检查: - -```python -async def create_custom_agent: - # 1. 检查租户的自定义 Agent 配额 - quota = await get_tenant_custom_agent_quota tenant_id - - # 2. 检查请求的资源是否超过剩余配额 - remaining_cpu = quota.cpu_quota - quota.cpu_used - remaining_memory = quota.memory_quota - quota.memory_used - - if request.cpu > remaining_cpu or request.memory > remaining_memory: - raise HTTPException 400, 资源配额不足 - - # 3. 创建 Agent 并更新已使用量 - agent = create_agent... - quota.cpu_used += request.cpu - quota.memory_used += request.memory - quota.agent_count += 1 -``` - -#### 4.4 资源统计 API - -修改 [`get_admin_dashboard_stats`](services/mcp-server/app/routes/admin.py:375): - -```python -# 统计所有 Agent(平台端 + 自定义) -total_agents = await db.execute select func.count Agent.id - -# 分别统计 -platform_agents = await db.execute select func.count Agent.id where Agent.type == platform -custom_agents = await db.execute select func.count Agent.id where Agent.type == custom - -# 资源统计也要包含两种类型 -total_cpu = sum of all agents cpu -total_memory = sum of all agents memory -``` - -#### 4.5 健康监控 API - -修改 [`monitor_agents`](services/mcp-server/app/routes/admin.py:1299): - -```python -# 监控所有 Agent(移除 type == platform 的过滤条件) -result = await db.execute select Agent # 不再过滤 type - -# 返回数据增加 type 字段,便于前端区分 -data = [ - { - id: str agent.id, - name: agent.name, - type: agent.type, # 新增:platform 或 custom - # ...其他字段 - } -] -``` - -### 5. 前端展示修改 - -#### 5.1 平台资源分配统计 - -在概览页面展示: -- 平台端 Agent 数量和资源使用 -- 自定义 Agent 数量和资源使用 -- 总计资源使用 - -#### 5.2 Agent 健康监控 - -在监控页面: -- 支持按类型筛选(全部/平台端/自定义) -- 显示 Agent 类型标签 -- 分别展示两种类型的健康状态统计 - -## 实施任务清单 - -### 阶段一:数据模型修改 ✅ 已完成 - -- [x] **1.1** 修改 [`Channel`](services/mcp-server/models.py:311) 模型 ✅ - - 添加 `custom_agent_cpu_quota` 字段(配额上限) - - 添加 `custom_agent_memory_quota` 字段(配额上限) - - 保留旧字段 `custom_agent_cpu/memory` 作为向后兼容 - - 添加字段注释说明这是配额上限 - -- [x] **1.2** 创建 `TenantCustomAgentQuota` 模型 ✅ - - 新增表 `tenant_custom_agent_quotas`(第974-1004行) - - 包含配额上限(cpu_quota, memory_quota)和已使用量(cpu_used, memory_used, agent_count)字段 - -- [x] **1.3** 创建 `ChannelCustomAgentQuota` 模型 ✅ - - 新增表 `channel_custom_agent_quotas`(第1007-1030行) - - 包含配额上限和已分配量字段 - -- [x] **1.4** 增强 [`Agent`](services/mcp-server/models.py:125) 模型 ✅ - - 添加 `image_url` 字段(自定义 Agent 镜像地址,第170行) - - 添加 `program_path` 字段(程序路径,第171行) - - 添加 `runtime_type` 字段(运行时类型,第172行) - - 添加 `health_status` 字段(健康状态,第179行) - - 添加 `last_health_check` 字段(最后健康检查时间,第180行) - - 添加 `health_message` 字段(健康状态消息,第181行) - - 添加 `idx_agent_health_status` 索引(第206行) - -- [x] **1.5** 创建数据库迁移脚本 ✅ - - `migrations/005_refactor_agent_quota_system.sql`(180行完整迁移脚本) - -### 阶段二:API 修改 ✅ 已完成 - -- [x] **2.1** 修改渠道资源管理 API ✅ - - 更新 [`ChannelResourceAllocation`](services/mcp-server/app/schemas.py:372) schema - 添加 customAgentQuota 字段 - - 更新 [`allocate_channel_resources`](services/mcp-server/app/routes/admin.py:924) 逻辑 - 支持配额分配 - -- [x] **2.2** 修改租户资源分配 API ✅ - - 更新 [`AllocateResourcesRequest`](services/mcp-server/app/schemas.py:298) schema - 添加 customAgentQuota 字段 - - 更新 [`allocate_tenant_resources`](services/mcp-server/app/routes/channel.py:193) 逻辑 - 支持配额分配和验证 - - 添加租户配额记录创建/更新逻辑 - -- [x] **2.3** 修改自定义 Agent 创建 API ✅ - - 在 [`generate_tool`](services/mcp-server/app/routes/user.py:287) 中添加配额检查 - - 创建 Agent 后更新已使用量 - - 在 [`delete_agent`](services/mcp-server/app/routes/agents.py:396) 中释放配额 - -- [x] **2.4** 新增配额查询 API ✅ - - `GET /api/user/custom-agent-quota` - 租户查询自己的配额使用情况 ([`get_my_custom_agent_quota`](services/mcp-server/app/routes/user.py:227)) - - `GET /api/channel/tenants/{tenant_id}/custom-agent-quota` - 渠道查询租户配额 ([`get_tenant_custom_agent_quota`](services/mcp-server/app/routes/channel.py:796)) - -### 阶段三:资源统计修改 ✅ 已完成 - -- [x] **3.1** 修改 [`get_admin_dashboard_stats`](services/mcp-server/app/routes/admin.py:375) ✅ - - 统计所有 Agent(平台端 + 自定义) - - 分别返回两种类型的数量和资源使用(platformAgents, customAgents) - - 返回总计资源使用(totalAllocatedCpu, totalAllocatedMemory) - -- [x] **3.2** 修改 [`get_platform_overview`](services/mcp-server/app/routes/resource_monitoring.py:31) ✅ - - 包含自定义 Agent 的统计 - - 返回 platformAgents 和 customAgents 分类统计 - - 返回 totalResources 总资源使用 - -- [x] **3.3** 新增资源分配统计 API ✅ - - `GET /api/admin/resources/allocation-stats` - 返回详细的资源分配统计 - - 实现:[`get_resource_allocation_stats`](services/mcp-server/app/routes/admin.py:1064) - -### 阶段四:健康监控修改 ✅ 已完成 - -- [x] **4.1** 修改 [`monitor_agents`](services/mcp-server/app/routes/admin.py:1477) ✅ - - 移除 `type == "platform"` 过滤条件,查询所有活跃 Agent - - 返回数据增加 `type` 字段 - - 支持按类型筛选参数(agent_type) - - 支持按健康状态筛选参数(health_status) - - 返回汇总统计(summary) - -- [x] **4.2** 增强自定义 Agent 健康检查 ✅ - - 在 Agent 模型中添加 health_status, last_health_check, health_message 字段 - - monitor_agents API 支持查询和筛选自定义 Agent 的健康状态 - - 注:实际的健康检查逻辑需要后台任务定期执行(可后续实现) - -- [x] **4.3** 统一健康状态定义 ✅ - - 在 Agent 模型中添加 health_status 字段 - - 定义统一的健康状态枚举:healthy, warning, critical, unknown - - 平台端和自定义 Agent 使用相同的状态定义 - -### 阶段五:前端适配 - -- [ ] **5.1** 更新概览页面 - - 展示平台端 Agent + 自定义 Agent 的资源统计 - - 添加类型区分的图表 - -- [ ] **5.2** 更新资源管理页面 - - 渠道资源管理增加自定义 Agent 配额设置 - - 租户资源分配增加自定义 Agent 配额设置 - -- [ ] **5.3** 更新监控页面 - - Agent 健康监控支持类型筛选 - - 显示 Agent 类型标签 - -## 数据迁移策略 - -1. **向后兼容**:保留旧字段名,添加新字段,逐步迁移 -2. **默认值处理**:现有渠道的 `custom_agent_cpu/memory` 值迁移为配额上限 -3. **租户配额初始化**:为现有租户创建配额记录,初始值从渠道继承 - -## 注意事项 - -1. **资源配额检查**:创建自定义 Agent 时必须检查配额 -2. **配额释放**:删除自定义 Agent 时必须释放配额 -3. **并发控制**:配额更新需要考虑并发场景 -4. **审计日志**:配额变更需要记录审计日志 - -## 问题修复记录 - -### 2026-01-04: 渠道配额显示问题修复 - -**问题描述**: -- 通过 API 更新渠道的自定义 Agent 配额后,数据库中 `custom_agent_cpu_quota` 和 `custom_agent_memory_quota` 字段正确更新 -- 但渠道列表 API (`/api/admin/channels`) 返回的 `customAgentCpu` 和 `customAgentMemory` 仍然显示旧值 - -**根本原因**: -- Channel 模型中同时存在新旧两组字段: - - 新字段:`custom_agent_cpu_quota`, `custom_agent_memory_quota` - - 旧字段:`custom_agent_cpu`, `custom_agent_memory` -- API 代码中部分地方使用新字段,部分地方使用旧字段,导致不一致 - -**修复方案**: -1. 修改 [`admin_channels`](services/mcp-server/app/routes/frontend_integration.py:933) 函数 - - 优先使用新字段 `custom_agent_cpu_quota`,如果为空则回退到旧字段 - - 添加调试日志便于排查 - -2. 修改 [`admin_get_channel_resources`](services/mcp-server/app/routes/frontend_integration.py:1020) 函数 - - 同样优先使用新字段,回退到旧字段 - -3. 修改 [`admin_update_channel_resources`](services/mcp-server/app/routes/frontend_integration.py:1063) 函数 - - 同时更新新旧两组字段,确保数据一致性 - - 添加日志记录更新操作 - - 返回更新后的配额值便于验证 - -## 测试计划 - -- [ ] 单元测试:配额检查逻辑 -- [ ] 集成测试:完整的资源分配流程 -- [ ] 端到端测试:从渠道分配到租户创建 Agent 的完整流程 -- [ ] 性能测试:大量 Agent 场景下的统计性能 diff --git a/plans/aks-agent-execution-plan.md b/plans/aks-agent-execution-plan.md deleted file mode 100644 index 89fd9e9..0000000 --- a/plans/aks-agent-execution-plan.md +++ /dev/null @@ -1,740 +0,0 @@ -# AKS Agent 执行方案设计 - -## 1. 问题分析 - -### 当前状态 - -``` -用户请求 → MCP Server → 本地 MCP 协议处理 → 工具执行 - ↓ - (未使用 AKS Pod 的 access_url) -``` - -**问题**:虽然 AKS 部署后返回了 `access_url` 和 `endpoints`,但当前代码并没有使用这些 URL 来调用 AKS 中运行的 Pod。 - -### 目标状态 - -``` -用户请求 → MCP Server → 判断 Agent 类型 → 转发到 AKS Pod → 返回结果 - ↓ - 本地执行(无 K8s 部署) -``` - ---- - -## 2. 架构设计 - -### 2.1 整体架构图 - -```mermaid -flowchart TB - subgraph Client[客户端] - User[用户] - end - - subgraph MCPServer[MCP Server] - API[API Gateway] - Router[Agent Router] - LocalHandler[本地 MCP Handler] - K8sProxy[K8s Agent Proxy] - end - - subgraph AKS[Azure Kubernetes Service] - Pod1[Agent Pod 1] - Pod2[Agent Pod 2] - Pod3[Agent Pod N] - end - - subgraph AgentManager[Agent Manager Service] - AM[Agent Manager API] - end - - User --> API - API --> Router - Router -->|无 K8s 部署| LocalHandler - Router -->|有 K8s 部署| K8sProxy - K8sProxy --> Pod1 - K8sProxy --> Pod2 - K8sProxy --> Pod3 - - AM -.->|管理| Pod1 - AM -.->|管理| Pod2 - AM -.->|管理| Pod3 -``` - -### 2.2 执行流程图 - -```mermaid -sequenceDiagram - participant User as 用户 - participant API as MCP Server API - participant Router as Agent Router - participant DB as 数据库 - participant Proxy as K8s Proxy - participant Pod as AKS Agent Pod - participant Local as 本地 Handler - - User->>API: POST /agents/{id}/execute - API->>DB: 获取 Agent 信息 - DB-->>API: Agent 数据 - - API->>Router: 路由决策 - - alt Agent 有 access_url - Router->>Proxy: 转发请求 - Proxy->>Pod: HTTP POST /execute - Pod-->>Proxy: 执行结果 - Proxy-->>API: 返回结果 - else Agent 无 K8s 部署 - Router->>Local: 本地执行 - Local-->>API: 执行结果 - end - - API->>DB: 记录执行和计费 - API-->>User: 返回结果 -``` - ---- - -## 3. 详细设计 - -### 3.1 新增组件:K8s Agent Proxy - -**文件位置**: `services/mcp-server/app/k8s_agent_proxy.py` - -```python -""" -K8s Agent Proxy - 负责转发请求到 AKS 部署的 Agent Pod -""" - -import httpx -import structlog -from typing import Dict, Any, Optional -from dataclasses import dataclass -from datetime import datetime - -logger = structlog.get_logger(__name__) - - -@dataclass -class ProxyConfig: - """代理配置""" - timeout: float = 30.0 - max_retries: int = 3 - retry_delay: float = 1.0 - health_check_interval: int = 30 - - -@dataclass -class ProxyResult: - """代理执行结果""" - success: bool - result: Optional[Dict[str, Any]] = None - error: Optional[str] = None - execution_time_ms: float = 0.0 - pod_name: Optional[str] = None - status_code: Optional[int] = None - - -class K8sAgentProxy: - """K8s Agent 代理类""" - - def __init__(self, config: Optional[ProxyConfig] = None): - self.config = config or ProxyConfig() - self._client: Optional[httpx.AsyncClient] = None - - async def _get_client(self) -> httpx.AsyncClient: - """获取或创建 HTTP 客户端""" - if self._client is None or self._client.is_closed: - self._client = httpx.AsyncClient( - timeout=self.config.timeout, - headers={"Content-Type": "application/json"} - ) - return self._client - - async def execute( - self, - access_url: str, - request_data: Dict[str, Any], - pod_name: Optional[str] = None, - headers: Optional[Dict[str, str]] = None - ) -> ProxyResult: - """ - 转发执行请求到 AKS Agent Pod - - Args: - access_url: Agent Pod 的访问 URL - request_data: MCP 请求数据 - pod_name: Pod 名称(用于日志) - headers: 额外的请求头 - - Returns: - ProxyResult: 执行结果 - """ - start_time = datetime.utcnow() - - try: - client = await self._get_client() - - # 构建完整的执行 URL - execute_url = f"{access_url.rstrip('/')}/execute" - - logger.info( - "转发请求到 AKS Agent", - url=execute_url, - pod_name=pod_name, - method=request_data.get("method") - ) - - # 合并请求头 - request_headers = {"Content-Type": "application/json"} - if headers: - request_headers.update(headers) - - # 发送请求(带重试) - response = await self._request_with_retry( - client, execute_url, request_data, request_headers - ) - - execution_time = (datetime.utcnow() - start_time).total_seconds() * 1000 - - if response.status_code == 200: - result_data = response.json() - return ProxyResult( - success=True, - result=result_data, - execution_time_ms=execution_time, - pod_name=pod_name, - status_code=response.status_code - ) - else: - error_detail = response.text - try: - error_detail = response.json() - except Exception: - pass - - return ProxyResult( - success=False, - error=f"Pod 返回错误: {response.status_code} - {error_detail}", - execution_time_ms=execution_time, - pod_name=pod_name, - status_code=response.status_code - ) - - except httpx.TimeoutException as e: - execution_time = (datetime.utcnow() - start_time).total_seconds() * 1000 - logger.error("请求 AKS Agent 超时", pod_name=pod_name, error=str(e)) - return ProxyResult( - success=False, - error=f"请求超时: {str(e)}", - execution_time_ms=execution_time, - pod_name=pod_name - ) - - except httpx.ConnectError as e: - execution_time = (datetime.utcnow() - start_time).total_seconds() * 1000 - logger.error("无法连接到 AKS Agent", pod_name=pod_name, error=str(e)) - return ProxyResult( - success=False, - error=f"连接失败: {str(e)}", - execution_time_ms=execution_time, - pod_name=pod_name - ) - - except Exception as e: - execution_time = (datetime.utcnow() - start_time).total_seconds() * 1000 - logger.error("转发请求失败", pod_name=pod_name, error=str(e)) - return ProxyResult( - success=False, - error=f"执行失败: {str(e)}", - execution_time_ms=execution_time, - pod_name=pod_name - ) - - async def _request_with_retry( - self, - client: httpx.AsyncClient, - url: str, - data: Dict[str, Any], - headers: Dict[str, str] - ) -> httpx.Response: - """带重试的请求""" - import asyncio - - last_exception = None - for attempt in range(self.config.max_retries): - try: - response = await client.post(url, json=data, headers=headers) - return response - except (httpx.TimeoutException, httpx.ConnectError) as e: - last_exception = e - if attempt < self.config.max_retries - 1: - await asyncio.sleep(self.config.retry_delay * (attempt + 1)) - logger.warning( - f"重试请求 {attempt + 1}/{self.config.max_retries}", - url=url, - error=str(e) - ) - raise last_exception - - async def health_check(self, access_url: str) -> bool: - """检查 Agent Pod 健康状态""" - try: - client = await self._get_client() - health_url = f"{access_url.rstrip('/')}/health" - response = await client.get(health_url, timeout=5.0) - return response.status_code == 200 - except Exception: - return False - - async def close(self): - """关闭客户端""" - if self._client and not self._client.is_closed: - await self._client.aclose() - self._client = None - - -# 全局代理实例 -_k8s_proxy: Optional[K8sAgentProxy] = None - - -def get_k8s_agent_proxy() -> K8sAgentProxy: - """获取全局 K8s Agent 代理实例""" - global _k8s_proxy - if _k8s_proxy is None: - _k8s_proxy = K8sAgentProxy() - return _k8s_proxy - - -async def close_k8s_agent_proxy(): - """关闭全局代理""" - global _k8s_proxy - if _k8s_proxy: - await _k8s_proxy.close() - _k8s_proxy = None -``` - -### 3.2 修改 Agent 执行端点 - -**文件位置**: `services/mcp-server/app/routes/agents.py` - -修改 `execute_agent` 函数: - -```python -@router.post("/{agent_id}/execute", response_model=ExecutionResult) -async def execute_agent( - agent_id: str, - request: MCPRequest, - db: AsyncSession = Depends(get_db), - current_user: dict = Depends(get_current_user), - session_id: Optional[str] = None, -) -> ExecutionResult: - """ - 执行 Agent 请求。 - - 如果 Agent 部署在 AKS 中,请求将被转发到对应的 Pod。 - 否则,请求将在本地执行。 - """ - state = get_state() - - try: - agent_uuid = uuid.UUID(agent_id) - user_id = uuid.UUID(current_user["user_id"]) - except ValueError as exc: - raise HTTPException(status_code=400, detail="Invalid agent ID or user ID") from exc - - agent = await db.get(Agent, agent_uuid) - if not agent: - raise HTTPException(status_code=404, detail="Agent not found") - - # 权限检查 - if agent.owner_id != user_id and current_user.get("role") != "super_admin": - raise HTTPException(status_code=403, detail="Access denied") - - # 资源管控检查 - await enforce_resource_control( - user_id=str(user_id), - resource_type="agent", - resource_id=agent_id, - estimated_cost=Decimal("0.01"), - db=db - ) - - start_time = time.time() - execution_id = str(uuid.uuid4()) - - try: - # ========== 路由决策:K8s Pod 或本地执行 ========== - if agent.access_url and agent.k8s_status == "Running": - # 转发到 AKS Agent Pod - result = await _execute_on_k8s_pod( - agent=agent, - request=request, - execution_id=execution_id, - user_id=str(user_id) - ) - else: - # 本地执行 - result = await _execute_locally( - agent=agent, - request=request, - execution_id=execution_id, - user_id=str(user_id), - db=db - ) - # ================================================ - - duration = time.time() - start_time - - # 记录执行和计费 - await _record_execution_and_billing( - db=db, - agent=agent, - request=request, - result=result, - execution_id=execution_id, - start_time=start_time, - duration=duration, - session_id=session_id - ) - - return result - - except Exception as exc: - duration = time.time() - start_time - logger.error("执行Agent任务失败", error=str(exc)) - raise HTTPException(status_code=500, detail=str(exc)) from exc - - -async def _execute_on_k8s_pod( - agent: Agent, - request: MCPRequest, - execution_id: str, - user_id: str -) -> ExecutionResult: - """转发请求到 AKS Agent Pod""" - from ..k8s_agent_proxy import get_k8s_agent_proxy - - proxy = get_k8s_agent_proxy() - - # 构建请求数据 - request_data = { - "jsonrpc": request.jsonrpc, - "id": str(request.id), - "method": request.method, - "params": request.params or {}, - "metadata": { - "execution_id": execution_id, - "user_id": user_id, - "agent_id": str(agent.id) - } - } - - # 转发请求 - proxy_result = await proxy.execute( - access_url=agent.access_url, - request_data=request_data, - pod_name=agent.pod_name - ) - - if proxy_result.success: - return ExecutionResult( - execution_id=execution_id, - success=True, - result=proxy_result.result, - execution_time=proxy_result.execution_time_ms, - started_at=datetime.utcnow(), - completed_at=datetime.utcnow() - ) - else: - return ExecutionResult( - execution_id=execution_id, - success=False, - error=proxy_result.error, - execution_time=proxy_result.execution_time_ms, - started_at=datetime.utcnow(), - completed_at=datetime.utcnow() - ) - - -async def _execute_locally( - agent: Agent, - request: MCPRequest, - execution_id: str, - user_id: str, - db: AsyncSession -) -> ExecutionResult: - """本地执行 MCP 请求""" - state = get_state() - handler = state.mcp_handler - - if not handler: - raise HTTPException(status_code=500, detail="MCP handler not initialized") - - return await handler.execute_request( - str(agent.id), - request, - user_id=user_id, - db_session=db - ) -``` - -### 3.3 AKS Agent Pod 端点规范 - -每个部署在 AKS 中的 Agent Pod 需要实现以下端点: - -| 端点 | 方法 | 描述 | -|-----|------|------| -| `/health` | GET | 健康检查 | -| `/execute` | POST | 执行 MCP 请求 | -| `/status` | GET | 获取 Agent 状态 | -| `/metrics` | GET | 获取资源使用指标 | - -#### 3.3.1 `/execute` 端点请求格式 - -```json -{ - "jsonrpc": "2.0", - "id": "request-uuid", - "method": "tools/call", - "params": { - "name": "tool_name", - "arguments": {} - }, - "metadata": { - "execution_id": "exec-uuid", - "user_id": "user-uuid", - "agent_id": "agent-uuid" - } -} -``` - -#### 3.3.2 `/execute` 端点响应格式 - -```json -{ - "success": true, - "result": { - "content": [ - { - "type": "text", - "text": "执行结果" - } - ] - }, - "execution_time_ms": 150.5, - "resource_usage": { - "cpu_ms": 50, - "memory_mb": 128 - } -} -``` - ---- - -## 4. 数据库变更 - -### 4.1 Agent 表新增字段(已存在) - -当前 `Agent` 模型已包含必要字段: - -| 字段 | 类型 | 描述 | -|-----|------|------| -| `access_url` | String(500) | Pod 访问 URL | -| `pod_name` | String(100) | Pod 名称 | -| `pod_ip` | String(45) | Pod IP | -| `k8s_status` | String(20) | Pod 状态 | -| `service_port` | Integer | Service 端口 | -| `endpoints` | JSON | 端点字典 | - -### 4.2 新增执行记录字段 - -在 `Execution` 表中添加: - -```python -# 执行位置 -execution_location = Column(String(20), default="local") # local, k8s -pod_name = Column(String(100)) # 执行的 Pod 名称 -``` - ---- - -## 5. 配置变更 - -### 5.1 环境变量 - -```bash -# K8s Agent Proxy 配置 -K8S_PROXY_TIMEOUT=30.0 -K8S_PROXY_MAX_RETRIES=3 -K8S_PROXY_RETRY_DELAY=1.0 -K8S_PROXY_HEALTH_CHECK_INTERVAL=30 -``` - -### 5.2 应用配置 - -在 `config.py` 中添加: - -```python -class K8sProxyConfig: - timeout: float = float(os.getenv("K8S_PROXY_TIMEOUT", "30.0")) - max_retries: int = int(os.getenv("K8S_PROXY_MAX_RETRIES", "3")) - retry_delay: float = float(os.getenv("K8S_PROXY_RETRY_DELAY", "1.0")) - health_check_interval: int = int(os.getenv("K8S_PROXY_HEALTH_CHECK_INTERVAL", "30")) -``` - ---- - -## 6. 实施计划 - -### 6.1 任务清单 - -- [ ] **Phase 1: 基础设施** - - [ ] 创建 `k8s_agent_proxy.py` 模块 - - [ ] 添加配置项 - - [ ] 编写单元测试 - -- [ ] **Phase 2: 路由逻辑** - - [ ] 修改 `execute_agent` 端点 - - [ ] 实现路由决策逻辑 - - [ ] 添加本地执行回退 - -- [ ] **Phase 3: 监控和日志** - - [ ] 添加执行位置记录 - - [ ] 添加 Prometheus 指标 - - [ ] 完善日志记录 - -- [ ] **Phase 4: 健康检查** - - [ ] 实现 Pod 健康检查 - - [ ] 添加自动故障转移 - - [ ] 实现连接池管理 - -- [ ] **Phase 5: 测试和文档** - - [ ] 集成测试 - - [ ] 性能测试 - - [ ] 更新 API 文档 - -### 6.2 文件变更清单 - -| 文件 | 操作 | 描述 | -|-----|------|------| -| `services/mcp-server/app/k8s_agent_proxy.py` | 新增 | K8s Agent 代理模块 | -| `services/mcp-server/app/routes/agents.py` | 修改 | 添加路由逻辑 | -| `services/mcp-server/config.py` | 修改 | 添加代理配置 | -| `services/mcp-server/app/lifecycle.py` | 修改 | 添加代理生命周期管理 | -| `services/mcp-server/models.py` | 修改 | 添加执行位置字段 | - ---- - -## 7. 错误处理 - -### 7.1 错误场景和处理策略 - -| 场景 | 处理策略 | -|-----|---------| -| Pod 不可达 | 重试 3 次后返回错误 | -| Pod 返回 5xx | 记录错误,返回给用户 | -| 请求超时 | 返回超时错误,建议重试 | -| Pod 状态非 Running | 回退到本地执行或返回错误 | -| access_url 为空 | 使用本地执行 | - -### 7.2 故障转移策略 - -```python -async def execute_with_fallback(agent, request, ...): - """带故障转移的执行""" - - # 1. 尝试 K8s Pod 执行 - if agent.access_url and agent.k8s_status == "Running": - result = await _execute_on_k8s_pod(...) - if result.success: - return result - - # 2. K8s 执行失败,检查是否可以本地执行 - if agent.tools and not agent.template: - logger.warning("K8s 执行失败,回退到本地执行") - return await _execute_locally(...) - - # 3. 本地执行 - return await _execute_locally(...) -``` - ---- - -## 8. 监控指标 - -### 8.1 新增 Prometheus 指标 - -```python -# K8s Agent 执行指标 -k8s_agent_requests_total = Counter( - "k8s_agent_requests_total", - "Total K8s agent requests", - ["pod_name", "status"] -) - -k8s_agent_request_duration = Histogram( - "k8s_agent_request_duration_seconds", - "K8s agent request duration", - ["pod_name"] -) - -k8s_agent_health_status = Gauge( - "k8s_agent_health_status", - "K8s agent health status", - ["pod_name"] -) -``` - -### 8.2 日志格式 - -```json -{ - "timestamp": "2024-01-01T00:00:00Z", - "level": "INFO", - "message": "转发请求到 AKS Agent", - "execution_id": "exec-uuid", - "agent_id": "agent-uuid", - "pod_name": "my-agent-abc123", - "access_url": "http://my-agent.ai-agents.svc.cluster.local:8080", - "method": "tools/call", - "execution_location": "k8s" -} -``` - ---- - -## 9. 安全考虑 - -### 9.1 网络安全 - -- Pod 间通信使用 K8s 内部网络 -- 不暴露 Pod 到公网 -- 使用 NetworkPolicy 限制访问 - -### 9.2 认证授权 - -- 请求中携带 `user_id` 和 `execution_id` -- Pod 可验证请求来源 -- 支持 mTLS(可选) - -### 9.3 数据安全 - -- 敏感数据不在日志中记录 -- 请求/响应数据加密传输 -- 执行结果脱敏存储 - ---- - -## 10. 总结 - -本方案实现了 MCP Server 与 AKS Agent Pod 的集成,主要特点: - -1. **智能路由**:根据 Agent 配置自动选择执行位置 -2. **故障转移**:K8s 执行失败时可回退到本地 -3. **可观测性**:完整的日志、指标和追踪 -4. **安全性**:网络隔离和认证机制 -5. **可扩展性**:支持多 Pod 负载均衡(未来) - -通过此方案,用户可以透明地使用部署在 AKS 中的 Agent,无需关心底层执行细节。 diff --git a/plans/database-migration-plan.md b/plans/database-migration-plan.md deleted file mode 100644 index ef1f8e7..0000000 --- a/plans/database-migration-plan.md +++ /dev/null @@ -1,166 +0,0 @@ -# 数据库迁移计划:postgres → taiji - -**创建时间**: 2025-12-31 -**目标**: 将 postgres 库的表结构和数据完全覆盖到 taiji 库 - ---- - -## 📋 任务概述 - -将 Azure PostgreSQL 服务器上的 `postgres` 数据库(新结构)完全复制到 `taiji` 数据库(旧结构),包括: -- 表结构 -- 索引 -- 约束 -- 数据 -- 序列 - ---- - -## 🔄 迁移流程图 - -```mermaid -flowchart TD - A[开始迁移] --> B[连接 postgres 源数据库] - B --> C[连接 taiji 目标数据库] - C --> D[备份 taiji 数据库 - 可选] - D --> E[删除 taiji 中的所有表] - E --> F[从 postgres 获取表结构] - F --> G[在 taiji 中创建表] - G --> H[创建索引和约束] - H --> I[复制数据] - I --> J[同步序列值] - J --> K[验证迁移结果] - K --> L[完成] -``` - ---- - -## ✅ 任务清单 - -### 1. 准备工作 -- [ ] 确认数据库连接信息正确 -- [ ] 确认 postgres 库中有最新的表结构 -- [ ] 备份 taiji 库现有数据(可选但推荐) - -### 2. 创建迁移脚本 -- [ ] 修改现有 `copy_database.py` 脚本,交换源和目标数据库 -- [ ] 或创建新脚本 `sync_postgres_to_taiji.py` - -### 3. 脚本功能实现 -- [ ] 连接源数据库(postgres) -- [ ] 连接目标数据库(taiji) -- [ ] 获取 postgres 库所有表列表 -- [ ] 删除 taiji 库中的所有现有表(CASCADE) -- [ ] 复制表结构(DDL) -- [ ] 复制索引定义 -- [ ] 复制数据 -- [ ] 同步序列值 - -### 4. 验证和测试 -- [ ] 验证表数量一致 -- [ ] 验证数据行数一致 -- [ ] 验证索引创建成功 -- [ ] 测试应用连接 taiji 库正常工作 - ---- - -## 📝 技术细节 - -### 数据库连接信息 - -```python -DB_HOST = "taijipda.postgres.database.azure.com" -DB_USER = "taiji" -DB_PASSWORD = "By@123456." -DB_PORT = 5432 - -# 源数据库(新结构) -SOURCE_DB = "postgres" - -# 目标数据库(需要更新) -TARGET_DB = "taiji" -``` - -### 主要表列表(基于 models.py) - -| 表名 | 说明 | -|------|------| -| users | 用户表(租户使用者) | -| agents | Agent表(平台Agent和自定义Agent) | -| tools | 工具表 | -| sessions | 会话表 | -| executions | 执行记录表 | -| api_keys | API密钥表 | -| billing | 计费详情表 | -| balances | 用户余额表 | -| billing_records | 计费记录表 | -| channels | 渠道合作伙伴表 | -| model_providers | 模型供应商表 | -| resource_allocations | 资源分配表 | -| applications | 申请审批表 | -| workflows | 工作流表 | -| audit_logs | 审计日志表 | -| channel_agent_quotas | 渠道Agent配额表 | -| provider_models | 模型提供商表 | -| token_blacklist | Token黑名单表 | -| resource_usage | 资源使用记录表 | -| quota_alerts | 配额预警记录表 | -| model_pricing | 模型定价配置表 | -| provider_health_checks | 供应商健康检查记录表 | -| agent_traces | Agent执行轨迹表 | -| billing_events | 计费事件表 | -| channel_provider_access | 渠道供应商授权表 | -| provider_applications | 供应商使用申请表 | -| gateway_apis | 网关API定义表 | -| data_templates | 数据模板表 | -| recharge_records | 充值记录表 | - ---- - -## ⚠️ 注意事项 - -1. **数据丢失风险**: 此操作会删除 taiji 库中的所有现有数据,请确保已备份 -2. **外键约束**: 删除表时使用 CASCADE 处理外键依赖 -3. **序列同步**: 确保序列值正确同步,避免主键冲突 -4. **连接中断**: 迁移过程中确保网络稳定 -5. **应用停机**: 建议在迁移期间停止连接 taiji 库的应用服务 - ---- - -## 🚀 执行步骤 - -1. **运行迁移脚本**: - ```bash - cd /home/taiji/tools/taiji-AI-PAD - python scripts/sync_postgres_to_taiji.py - ``` - -2. **验证迁移结果**: - ```bash - # 连接 taiji 库检查表 - psql "host=taijipda.postgres.database.azure.com port=5432 dbname=taiji user=taiji password=By@123456. sslmode=require" - - # 查看所有表 - \dt - - # 检查数据行数 - SELECT COUNT(*) FROM users; - SELECT COUNT(*) FROM agents; - ``` - -3. **更新应用配置**(如需要): - 确保应用的 DATABASE_URL 指向 taiji 库 - ---- - -## 📊 预期结果 - -迁移完成后: -- taiji 库将拥有与 postgres 库完全相同的表结构 -- 所有数据将从 postgres 库复制到 taiji 库 -- 索引和约束将正确创建 -- 序列值将同步 - ---- - -**下一步**: 切换到 Code 模式创建迁移脚本 diff --git a/plans/mcp-server-refactor-requirements.md b/plans/mcp-server-refactor-requirements.md new file mode 100644 index 0000000..cc36398 --- /dev/null +++ b/plans/mcp-server-refactor-requirements.md @@ -0,0 +1,662 @@ +# MCP Server 重构需求文档 + +## 1. 概述 + +### 1.1 服务定位 + +MCP Server 是平台的核心业务服务,负责: +- 用户认证与授权 +- 渠道和租户管理 +- Agent 资源分配与配额管理 +- 计费与账单 +- 与 Agent Manager 的集成 +- 工具和工作流管理 + +### 1.2 系统架构 + +```mermaid +flowchart TB + subgraph Frontend[前端] + AdminUI[管理员控制台] + ChannelUI[渠道控制台] + UserUI[用户控制台] + end + + subgraph MCPServer[MCP Server] + subgraph Auth[认证授权] + AuthModule[认证模块] + PermModule[权限模块] + end + + subgraph Business[业务模块] + ChannelMgmt[渠道管理] + TenantMgmt[租户管理] + AgentMgmt[Agent管理] + QuotaMgmt[配额管理] + end + + subgraph Billing[计费模块] + BillingCalc[计费计算] + BillingRecord[计费记录] + end + + subgraph Integration[集成模块] + AMClient[Agent Manager客户端] + ProviderClient[供应商客户端] + end + + DB[(PostgreSQL)] + end + + subgraph External[外部服务] + AgentManager[Agent Manager] + ModelProviders[模型供应商] + end + + Frontend --> MCPServer + MCPServer --> External + Business --> DB + Billing --> DB +``` + +### 1.3 调用链路 + +``` +前端 → MCP Server(认证、权限、配额、计费)→ Agent Manager(K8s 操作) +``` + +--- + +## 2. 现有功能模块 + +### 2.1 路由模块清单 + +| 模块 | 文件 | 功能 | 重构优先级 | +|------|------|------|-----------| +| 认证 | `auth.py` | 登录、注册、Token管理 | 保留 | +| 管理员 | `admin.py` | 超级管理员功能 | 重构 | +| 渠道 | `channel.py` | 渠道管理、资源分配 | 重构 | +| 用户 | `user.py` | 租户功能、Agent使用 | 重构 | +| Agent | `agents.py` | Agent CRUD、K8s集成 | **重点重构** | +| 计费 | `billing_admin.py` | 计费管理 | 保留 | +| 配额 | `quota_management.py` | 配额管理 | 重构 | +| 监控 | `monitoring.py` | 系统监控 | 保留 | +| 资源监控 | `resource_monitoring.py` | 资源使用监控 | 重构 | +| 前端集成 | `frontend_integration.py` | 前端API适配 | 重构 | +| 工具 | `tools.py` | 工具管理 | 保留 | +| 会话 | `sessions.py` | 会话管理 | 保留 | +| 健康检查 | `health.py` | 服务健康检查 | 保留 | + +### 2.2 数据模型清单 + +| 模型 | 说明 | 重构内容 | +|------|------|----------| +| User | 用户/租户 | 新增平台Agent配额字段 | +| Channel | 渠道 | 已有自定义Agent配额字段 | +| Agent | Agent | 区分平台/自定义类型 | +| ResourceAllocation | 资源分配 | 新增平台Agent分配 | +| ChannelAgentQuota | 渠道Agent配额 | 重构为平台Agent配额 | +| TenantCustomAgentQuota | 租户自定义Agent配额 | 保留 | +| ChannelCustomAgentQuota | 渠道自定义Agent配额 | 保留 | + +--- + +## 3. Agent 相关功能重构 + +### 3.1 平台 Agent 管理 + +#### 3.1.1 管理员功能 + +| 功能 | API | 说明 | +|------|-----|------| +| 查看平台Agent模板列表 | `GET /api/admin/platform-agents/templates` | 从Agent Manager获取 | +| 设置平台Agent配置 | `PUT /api/admin/platform-agents/templates/{name}/config` | 设置CPU/内存/最大Pod数 | +| 分配平台Agent给渠道 | `POST /api/admin/channels/{id}/platform-agents` | 分配Pod数量配额 | +| 查看平台Agent分配情况 | `GET /api/admin/platform-agents/allocations` | 查看所有分配 | +| 查看平台Agent运行状态 | `GET /api/admin/platform-agents/status` | 从Agent Manager获取 | + +**分配平台Agent给渠道请求体**: + +```json +{ + "templateName": "jina_search_agent", + "podQuota": 10, + "description": "分配Jina搜索Agent给渠道A" +} +``` + +#### 3.1.2 渠道功能 + +| 功能 | API | 说明 | +|------|-----|------| +| 查看已分配的平台Agent | `GET /api/channel/platform-agents` | 查看渠道拥有的配额 | +| 分配平台Agent给租户 | `POST /api/channel/tenants/{id}/platform-agents` | 分配Pod数量配额 | +| 查看租户平台Agent使用情况 | `GET /api/channel/tenants/{id}/platform-agents/usage` | 查看使用统计 | + +**分配平台Agent给租户请求体**: + +```json +{ + "templateName": "jina_search_agent", + "podQuota": 3, + "description": "分配给租户使用" +} +``` + +#### 3.1.3 租户功能 + +| 功能 | API | 说明 | +|------|-----|------| +| 查看可用的平台Agent | `GET /api/user/platform-agents` | 查看已分配的Agent | +| 使用平台Agent | `POST /api/user/platform-agents/{template}/use` | 创建Pod实例 | +| 停止平台Agent | `DELETE /api/user/platform-agents/{name}` | 删除Pod实例 | +| 查看平台Agent状态 | `GET /api/user/platform-agents/{name}/status` | 查看Pod状态 | +| 查看配额使用情况 | `GET /api/user/platform-agents/quota` | 查看配额和使用量 | + +**使用平台Agent请求体**: + +```json +{ + "name": "my-jina-search-001", + "queryParams": { + "searchType": "semantic", + "maxResults": 10 + } +} +``` + +### 3.2 自定义 Agent 管理 + +#### 3.2.1 管理员功能 + +| 功能 | API | 说明 | +|------|-----|------| +| 查看自定义Agent模板列表 | `GET /api/admin/custom-agents/templates` | 从Agent Manager获取 | +| 分配自定义Agent资源给渠道 | `POST /api/admin/channels/{id}/custom-agent-quota` | 分配CPU/内存配额 | +| 查看自定义Agent资源分配 | `GET /api/admin/custom-agents/allocations` | 查看所有分配 | + +**分配自定义Agent资源给渠道请求体**: + +```json +{ + "cpuQuota": 8, + "memoryQuota": 16, + "description": "分配自定义Agent资源给渠道A" +} +``` + +#### 3.2.2 渠道功能 + +| 功能 | API | 说明 | +|------|-----|------| +| 查看自定义Agent资源配额 | `GET /api/channel/custom-agent-quota` | 查看渠道配额 | +| 分配自定义Agent资源给租户 | `POST /api/channel/tenants/{id}/custom-agent-quota` | 分配CPU/内存配额 | +| 查看租户自定义Agent使用情况 | `GET /api/channel/tenants/{id}/custom-agents` | 查看租户创建的Agent | + +**分配自定义Agent资源给租户请求体**: + +```json +{ + "cpuQuota": 4, + "memoryQuota": 8, + "description": "分配自定义Agent资源给租户" +} +``` + +#### 3.2.3 租户功能 + +| 功能 | API | 说明 | +|------|-----|------| +| 查看自定义Agent模板 | `GET /api/user/custom-agents/templates` | 查看可用模板 | +| 创建自定义Agent | `POST /api/user/custom-agents` | 创建并启动Agent | +| 更新自定义Agent配置 | `PUT /api/user/custom-agents/{name}` | 更新环境变量等 | +| 删除自定义Agent | `DELETE /api/user/custom-agents/{name}` | 删除Agent | +| 查看自定义Agent状态 | `GET /api/user/custom-agents/{name}/status` | 查看Pod状态 | +| 查看配额使用情况 | `GET /api/user/custom-agent-quota` | 查看配额和使用量 | +| 扩缩容自定义Agent | `PUT /api/user/custom-agents/{name}/scale` | 调整Pod数量 | + +**创建自定义Agent请求体**: + +```json +{ + "name": "my-openai-agent", + "template": "openai_agent_template", + "envVars": { + "OPENAI_API_KEY": "sk-xxx", + "OPENAI_API_BASE": "https://api.openai.com/v1", + "MODEL_NAME": "gpt-4" + }, + "resourceConfig": { + "cpuRequest": "200m", + "cpuLimit": "1000m", + "memoryRequest": "256Mi", + "memoryLimit": "1Gi" + }, + "scalingConfig": { + "minReplicas": 2, + "maxReplicas": 4 + } +} +``` + +--- + +## 4. 配额管理重构 + +### 4.1 平台 Agent 配额 + +#### 4.1.1 数据模型 + +```python +class PlatformAgentQuota(BaseModel, Base): + """平台 Agent 配额分配""" + __tablename__ = "platform_agent_quotas" + + # 分配目标 + target_id = Column(GUID(), nullable=False) # 渠道ID或租户ID + target_type = Column(String(20), nullable=False) # channel, tenant + + # Agent模板 + template_name = Column(String(100), nullable=False) # 平台Agent模板名称 + + # 配额 + pod_quota = Column(Integer, nullable=False, default=0) # Pod数量配额 + pod_used = Column(Integer, default=0) # 已使用Pod数量 + + # 分配信息 + allocated_by = Column(GUID(), ForeignKey("users.id")) # 分配人 + allocated_at = Column(DateTime, default=datetime.utcnow) + + __table_args__ = ( + Index("idx_platform_agent_quota_target", target_id, target_type), + Index("idx_platform_agent_quota_template", template_name), + UniqueConstraint("target_id", "target_type", "template_name", name="uq_platform_agent_quota"), + ) +``` + +#### 4.1.2 配额检查流程 + +```mermaid +flowchart TD + A[用户请求使用平台Agent] --> B[验证用户身份] + B --> C[获取用户的平台Agent配额] + C --> D{配额是否充足?} + D -->|是| E[调用Agent Manager创建Pod] + D -->|否| F[返回配额不足错误] + E --> G{创建成功?} + G -->|是| H[更新已使用配额] + G -->|否| I[返回创建失败错误] + H --> J[返回成功] +``` + +### 4.2 自定义 Agent 配额 + +#### 4.2.1 现有数据模型 + +已有 `TenantCustomAgentQuota` 和 `ChannelCustomAgentQuota` 模型,保留使用。 + +#### 4.2.2 配额检查流程 + +```mermaid +flowchart TD + A[用户创建自定义Agent] --> B[验证用户身份] + B --> C[获取用户的自定义Agent配额] + C --> D[计算请求的资源总量] + D --> E{资源是否充足?} + E -->|是| F[调用Agent Manager创建Pod] + E -->|否| G[返回资源不足错误] + F --> H{创建成功?} + H -->|是| I[更新已使用资源] + H -->|否| J[返回创建失败错误] + I --> K[返回成功] +``` + +--- + +## 5. 与 Agent Manager 集成 + +### 5.1 客户端重构 + +现有 `agent_manager_client.py` 需要重构以支持新的 API: + +```python +class AgentManagerClient: + """Agent Manager API 客户端""" + + # 模板管理 + async def list_platform_templates(self) -> List[TemplateInfo] + async def list_custom_templates(self) -> List[TemplateInfo] + async def get_template(self, name: str) -> TemplateInfo + + # 平台 Agent 管理 + async def create_platform_agent( + self, + name: str, + template: str, + owner_id: str, + channel_id: str, + config: AgentConfig + ) -> AgentCreateResult + + async def delete_platform_agent(self, name: str) -> Dict + async def get_platform_agent_status(self, name: str) -> AgentStatusResult + async def list_platform_agents(self, owner_id: str = None) -> List[Dict] + + # 自定义 Agent 管理 + async def create_custom_agent( + self, + name: str, + template: str, + owner_id: str, + channel_id: str, + env_vars: Dict[str, str], + config: AgentConfig, + scaling_config: ScalingConfig + ) -> AgentCreateResult + + async def update_custom_agent_env(self, name: str, env_vars: Dict[str, str]) -> Dict + async def delete_custom_agent(self, name: str) -> Dict + async def get_custom_agent_status(self, name: str) -> AgentStatusResult + async def scale_custom_agent(self, name: str, replicas: int) -> Dict + async def list_custom_agents(self, owner_id: str = None) -> List[Dict] + + # 统计 + async def get_stats() -> Dict +``` + +### 5.2 调用时序 + +#### 5.2.1 使用平台 Agent + +```mermaid +sequenceDiagram + participant User as 用户 + participant MCP as MCP Server + participant AM as Agent Manager + participant K8s as Kubernetes + + User->>MCP: POST /api/user/platform-agents/{template}/use + MCP->>MCP: 验证身份和权限 + MCP->>MCP: 检查配额 + MCP->>AM: POST /platform-agents + AM->>K8s: 创建Pod + K8s-->>AM: Pod创建成功 + AM-->>MCP: 返回Agent信息 + MCP->>MCP: 更新配额使用量 + MCP->>MCP: 记录计费信息 + MCP-->>User: 返回Agent信息 +``` + +#### 5.2.2 创建自定义 Agent + +```mermaid +sequenceDiagram + participant User as 用户 + participant MCP as MCP Server + participant AM as Agent Manager + participant K8s as Kubernetes + + User->>MCP: POST /api/user/custom-agents + MCP->>MCP: 验证身份和权限 + MCP->>MCP: 检查资源配额 + MCP->>MCP: 验证环境变量 + MCP->>AM: POST /custom-agents + AM->>K8s: 创建Secret + AM->>K8s: 创建Deployment + K8s-->>AM: 资源创建成功 + AM-->>MCP: 返回Agent信息 + MCP->>MCP: 更新资源使用量 + MCP->>MCP: 记录计费信息 + MCP-->>User: 返回Agent信息 +``` + +--- + +## 6. 计费重构 + +### 6.1 计费规则 + +#### 6.1.1 平台 Agent 计费 + +| 计费项 | 计算方式 | 说明 | +|--------|----------|------| +| Pod 运行时间 | 运行秒数 × 单价 | 按秒计费 | +| 请求次数 | 请求数 × 单价 | 可选 | + +#### 6.1.2 自定义 Agent 计费 + +| 计费项 | 计算方式 | 说明 | +|--------|----------|------| +| CPU 使用 | CPU核心数 × 运行秒数 × 单价 | 按实际使用计费 | +| 内存使用 | 内存GB × 运行秒数 × 单价 | 按实际使用计费 | +| 请求次数 | 请求数 × 单价 | 可选 | + +### 6.2 计费记录 + +```python +class AgentBillingRecord(BaseModel, Base): + """Agent 计费记录""" + __tablename__ = "agent_billing_records" + + user_id = Column(GUID(), ForeignKey("users.id"), nullable=False) + channel_id = Column(GUID(), ForeignKey("channels.id")) + agent_name = Column(String(100), nullable=False) + agent_type = Column(String(20), nullable=False) # platform, custom + template_name = Column(String(100), nullable=False) + + # 使用量 + duration_seconds = Column(Integer, nullable=False) # 运行时长 + cpu_seconds = Column(sa.Float, default=0) # CPU秒数 + memory_gb_seconds = Column(sa.Float, default=0) # 内存GB秒数 + request_count = Column(Integer, default=0) # 请求次数 + + # 费用 + cost = Column(sa.Numeric(12, 4), nullable=False) + currency = Column(String(10), default="EU") + + # 时间 + period_start = Column(DateTime, nullable=False) + period_end = Column(DateTime, nullable=False) +``` + +--- + +## 7. 权限控制 + +### 7.1 角色权限矩阵 + +| 功能 | super_admin | admin | channel_admin | user | +|------|-------------|-------|---------------|------| +| 管理平台Agent模板 | ✓ | ✓ | - | - | +| 分配平台Agent给渠道 | ✓ | ✓ | - | - | +| 分配自定义Agent资源给渠道 | ✓ | ✓ | - | - | +| 分配平台Agent给租户 | - | - | ✓ | - | +| 分配自定义Agent资源给租户 | - | - | ✓ | - | +| 使用平台Agent | - | - | - | ✓ | +| 创建自定义Agent | - | - | - | ✓ | +| 查看自己的Agent | - | - | ✓ | ✓ | + +### 7.2 权限检查 + +```python +# 权限定义 +PERMISSIONS = { + # 平台 Agent + "platform_agent:admin": ["super_admin", "admin"], + "platform_agent:allocate_channel": ["super_admin", "admin"], + "platform_agent:allocate_tenant": ["channel_admin"], + "platform_agent:use": ["user"], + + # 自定义 Agent + "custom_agent:admin": ["super_admin", "admin"], + "custom_agent:allocate_channel": ["super_admin", "admin"], + "custom_agent:allocate_tenant": ["channel_admin"], + "custom_agent:create": ["user"], + "custom_agent:manage": ["user"], +} +``` + +--- + +## 8. 数据库迁移 + +### 8.1 新增表 + +```sql +-- 平台 Agent 配额表 +CREATE TABLE platform_agent_quotas ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + target_id UUID NOT NULL, + target_type VARCHAR(20) NOT NULL, + template_name VARCHAR(100) NOT NULL, + pod_quota INTEGER NOT NULL DEFAULT 0, + pod_used INTEGER DEFAULT 0, + allocated_by UUID REFERENCES users(id), + allocated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + UNIQUE(target_id, target_type, template_name) +); + +CREATE INDEX idx_platform_agent_quota_target ON platform_agent_quotas(target_id, target_type); +CREATE INDEX idx_platform_agent_quota_template ON platform_agent_quotas(template_name); + +-- Agent 计费记录表 +CREATE TABLE agent_billing_records ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + user_id UUID NOT NULL REFERENCES users(id), + channel_id UUID REFERENCES channels(id), + agent_name VARCHAR(100) NOT NULL, + agent_type VARCHAR(20) NOT NULL, + template_name VARCHAR(100) NOT NULL, + duration_seconds INTEGER NOT NULL, + cpu_seconds FLOAT DEFAULT 0, + memory_gb_seconds FLOAT DEFAULT 0, + request_count INTEGER DEFAULT 0, + cost NUMERIC(12, 4) NOT NULL, + currency VARCHAR(10) DEFAULT 'EU', + period_start TIMESTAMP NOT NULL, + period_end TIMESTAMP NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +CREATE INDEX idx_agent_billing_user ON agent_billing_records(user_id); +CREATE INDEX idx_agent_billing_channel ON agent_billing_records(channel_id); +CREATE INDEX idx_agent_billing_period ON agent_billing_records(period_start, period_end); +``` + +### 8.2 修改现有表 + +```sql +-- 在 users 表添加平台 Agent 相关字段(如果需要) +-- 注意:平台 Agent 配额通过 platform_agent_quotas 表管理 + +-- 在 agents 表确保有必要的字段 +ALTER TABLE agents ADD COLUMN IF NOT EXISTS owner_channel_id UUID REFERENCES channels(id); +``` + +--- + +## 9. API 变更汇总 + +### 9.1 新增 API + +| 方法 | 路径 | 说明 | +|------|------|------| +| GET | /api/admin/platform-agents/templates | 获取平台Agent模板列表 | +| PUT | /api/admin/platform-agents/templates/{name}/config | 设置平台Agent配置 | +| POST | /api/admin/channels/{id}/platform-agents | 分配平台Agent给渠道 | +| GET | /api/admin/platform-agents/allocations | 查看平台Agent分配情况 | +| GET | /api/channel/platform-agents | 查看渠道的平台Agent配额 | +| POST | /api/channel/tenants/{id}/platform-agents | 分配平台Agent给租户 | +| GET | /api/user/platform-agents | 查看可用的平台Agent | +| POST | /api/user/platform-agents/{template}/use | 使用平台Agent | +| DELETE | /api/user/platform-agents/{name} | 停止平台Agent | +| GET | /api/user/platform-agents/{name}/status | 查看平台Agent状态 | +| GET | /api/user/platform-agents/quota | 查看平台Agent配额 | + +### 9.2 修改 API + +| 方法 | 路径 | 变更说明 | +|------|------|----------| +| POST | /api/user/custom-agents | 增加配额检查,调用Agent Manager | +| DELETE | /api/user/custom-agents/{name} | 释放配额,调用Agent Manager | +| GET | /api/admin/dashboard/stats | 增加平台Agent统计 | +| GET | /api/admin/resources/agents | 区分平台/自定义Agent | + +### 9.3 废弃 API + +| 方法 | 路径 | 说明 | +|------|------|------| +| POST | /api/user/agents/deploy | 改用 /api/user/platform-agents/{template}/use | + +--- + +## 10. 实施计划 + +### 阶段一:数据模型和迁移 + +- [ ] 创建 `PlatformAgentQuota` 模型 +- [ ] 创建 `AgentBillingRecord` 模型 +- [ ] 创建数据库迁移脚本 +- [ ] 执行迁移 + +### 阶段二:Agent Manager 客户端重构 + +- [ ] 重构 `agent_manager_client.py` +- [ ] 添加平台Agent API支持 +- [ ] 添加自定义Agent API支持 +- [ ] 添加单元测试 + +### 阶段三:管理员功能 + +- [ ] 实现平台Agent模板管理API +- [ ] 实现平台Agent分配给渠道API +- [ ] 实现自定义Agent资源分配给渠道API +- [ ] 更新管理员Dashboard统计 + +### 阶段四:渠道功能 + +- [ ] 实现渠道查看平台Agent配额API +- [ ] 实现渠道分配平台Agent给租户API +- [ ] 实现渠道分配自定义Agent资源给租户API +- [ ] 更新渠道Dashboard + +### 阶段五:租户功能 + +- [ ] 实现租户查看可用平台Agent API +- [ ] 实现租户使用平台Agent API +- [ ] 重构租户创建自定义Agent API +- [ ] 实现配额查询API + +### 阶段六:计费集成 + +- [ ] 实现Agent计费记录 +- [ ] 集成计费到Agent使用流程 +- [ ] 实现计费统计API + +### 阶段七:测试和文档 + +- [ ] 单元测试 +- [ ] 集成测试 +- [ ] API文档更新 +- [ ] 前端对接测试 + +--- + +## 11. 注意事项 + +1. **向后兼容**:保留现有API,新增API使用新路径 +2. **配额一致性**:确保配额检查和更新的原子性 +3. **错误处理**:Agent Manager调用失败时的回滚处理 +4. **日志记录**:所有配额变更需要审计日志 +5. **性能考虑**:配额检查需要高效,避免频繁数据库查询 + +--- + +## 12. 版本历史 + +| 版本 | 日期 | 说明 | +|------|------|------| +| v1.0 | 2026-01-04 | 初始版本 |