Files
taiji-AI-PAD/Docs/功能修复/数据工具与自定义Agent-功能修复文档.md
T

480 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 数据工具与自定义Agent - 功能修复文档
> **创建日期**: 2026-01-13
> **状态**: 待修复
> **优先级**: 高
---
## 1. 问题概述
### 当前实现与预期业务逻辑不一致
**预期业务逻辑**:
1. 前端获取 `dataTemplates`(Agent 模板列表,如 `mysql_agent`、`postgresql_agent`)
2. 用户选择模板,根据模板的 `env_info` 填写配置值(如 MySQL 连接信息),保存为**工具**
3. 用户创建自定义 Agent 时选择已创建的工具
4. MCP-Server 从工具中获取模板类型和配置,传递给 Agent Manager 创建对应的 Agent
**当前实现问题**:
- Tool 模型设计为通用 API 调用配置(endpoint、method、schema)
- **缺少 `template` 字段**:无法关联 Agent 模板
- **缺少 `env_config` 字段**:无法存储模板所需的环境变量配置
- 创建 Agent 时,工具只作为附加的 API 能力,而不是决定 Agent 类型的关键信息
---
## 2. 正确的业务流程
```
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 正确的业务流程 │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ ① 获取模板列表 ② 创建工具(基于模板) ③ 创建Agent(选择工具) │
│ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │
│ │ GET │ │ POST │ │ POST │ │
│ │ /templates │──────→│ /tools/create │───────────→│ /custom-agents│ │
│ └───────────────┘ └───────────────┘ └───────────────┘ │
│ │ │ │ │
│ ↓ ↓ ↓ │
│ 返回 dataTemplates 保存到 Tool 表 从工具获取 template │
│ [mysql_agent, - template: mysql_agent 和 envConfig, │
│ postgresql_agent] - envConfig: { 传递给 Agent Manager │
│ MYSQL_HOST: "...", │
│ 含 env_info: MYSQL_USER: "...", │
│ - required ... │
│ - optional } │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
```
### 关键概念
| 概念 | 说明 |
|------|------|
| **模板 (template)** | Agent Manager 提供的镜像类型,如 `mysql_agent`,包含 `env_info` 定义所需配置 |
| **工具 (Tool)** | 用户基于模板创建的配置实例,包含 `template` + 填写好的 `envConfig` |
| **自定义 Agent** | 根据工具的模板类型和配置创建的 K8s Pod |
---
## 3. 需要修改的内容
### 3.1 数据库模型修改
**文件**: `services/mcp-server/models.py`
**修改 Tool 模型,添加字段**:
```python
class Tool(BaseModel, Base):
"""工具模型"""
__tablename__ = "tools"
name = Column(String(100), nullable=False)
description = Column(Text)
category = Column(String(50)) # database, api, function 等
# ========== 新增:模板相关字段 ==========
template = Column(String(100)) # 模板名称,如 "mysql_agent", "postgresql_agent"
env_config = Column(JSON, default=dict) # 环境变量配置,根据模板 env_info 填写
# =========================================
# 工具定义(保留,用于自定义 API 工具)
schema = Column(JSON) # 改为可空,模板工具不需要
endpoint = Column(String(500))
method = Column(String(10), default="POST")
# ... 其他字段保持不变
```
### 3.2 创建工具接口修改
**文件**: `services/mcp-server/app/routes/user.py`
**修改 `POST /api/user/tools/create` 接口**:
```python
@router.post("/tools/create", response_model=SuccessResponse)
async def create_tool(
req: dict,
principal: dict = Depends(require_auth),
db: AsyncSession = Depends(get_db)
):
"""
创建工具(基于模板)
请求体示例(MySQL 工具):
{
"name": "my-mysql-tool",
"description": "我的MySQL数据库连接工具",
"template": "mysql_agent",
"envConfig": {
"MYSQL_HOST": "mysql.example.com",
"MYSQL_USER": "root",
"MYSQL_PASSWORD": "password123",
"MYSQL_DATABASE": "mydb",
"MYSQL_PORT": "3306",
"OPENAI_API_KEY": "sk-xxx"
}
}
"""
user_id = principal.get("user_id")
# 验证模板名称
template_name = req.get("template")
if template_name:
# 从 Agent Manager 获取模板列表并验证
try:
from app.agent_manager_client import get_agent_manager_client, AgentManagerError
client = get_agent_manager_client()
custom_templates = await client.list_custom_templates()
template_names = [t.template for t in custom_templates]
if template_name not in template_names:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"无效的模板名称: {template_name}。支持的模板: {', '.join(template_names)}"
)
except AgentManagerError:
pass # Agent Manager 不可用时跳过验证
# 检查工具名称是否已存在
result = await db.execute(
select(Tool).where(
and_(
Tool.owner_id == user_id,
Tool.name == req.get("name")
)
)
)
existing_tool = result.scalar_one_or_none()
if existing_tool:
raise HTTPException(
status_code=status.HTTP_409_CONFLICT,
detail=f"工具名称 '{req.get('name')}' 已存在"
)
# 创建工具
tool = Tool(
name=req.get("name"),
description=req.get("description"),
category="database" if template_name else req.get("type", "api"),
template=template_name, # 新增
env_config=req.get("envConfig", {}), # 新增
schema=req.get("config", {}).get("schema") if not template_name else None,
endpoint=req.get("config", {}).get("endpoint") if not template_name else None,
method=req.get("config", {}).get("method", "GET") if not template_name else None,
auth_config={"apiKey": req.get("config", {}).get("apiKey")} if req.get("config", {}).get("apiKey") else {},
owner_id=user_id,
is_active=True,
is_public=False,
)
db.add(tool)
await db.commit()
await db.refresh(tool)
return SuccessResponse(
data={
"id": str(tool.id),
"name": tool.name,
"template": tool.template,
},
message="工具创建成功"
)
```
### 3.3 创建自定义 Agent 接口修改
**文件**: `services/mcp-server/app/routes/user.py`
**修改 `POST /api/user/custom-agents` 接口的工具处理逻辑**:
```python
@router.post("/custom-agents", response_model=SuccessResponse)
async def create_custom_agent(
req: CreateCustomAgentRequest,
principal: dict = Depends(require_auth),
db: AsyncSession = Depends(get_db)
):
"""
创建自定义 Agent
新逻辑:从选中的工具获取模板类型和环境变量配置
"""
# ... 配额检查等代码保持不变 ...
# ========== 新增:从工具获取模板和配置 ==========
template_name = req.template # 默认使用请求中的 template
env_vars = req.envConfig or {}
if req.tools and len(req.tools) > 0:
# 查询第一个工具(主工具,决定 Agent 类型)
primary_tool_id = req.tools[0]
try:
tool_result = await db.execute(
select(Tool).where(
Tool.id == PyUUID(primary_tool_id),
or_(
Tool.is_public == True,
Tool.owner_id == PyUUID(user_id)
)
)
)
primary_tool = tool_result.scalar_one_or_none()
if primary_tool and primary_tool.template:
# 使用工具的模板类型
template_name = primary_tool.template
# 合并工具的环境变量配置
if primary_tool.env_config:
env_vars = {**primary_tool.env_config, **env_vars}
logger.info(
f"从工具获取配置: tool_id={primary_tool_id}, "
f"template={template_name}, env_keys={list(env_vars.keys())}"
)
except Exception as e:
logger.warning(f"查询工具失败: {str(e)}")
# ================================================
# 验证模板
try:
client = get_agent_manager_client()
custom_templates = await client.list_custom_templates()
template_names = [t.template for t in custom_templates]
if template_name not in template_names:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"无效的模板名称: {template_name}。支持的模板: {', '.join(template_names)}"
)
except AgentManagerError as e:
logger.warning(f"无法获取模板列表,跳过验证: {str(e)}")
# ... 后续代码使用 template_name 和 env_vars 创建 Agent ...
```
### 3.4 获取用户工具列表接口修改
**文件**: `services/mcp-server/app/routes/user.py`
**修改 `GET /api/user/tools` 响应格式**:
```python
@router.get("/tools", response_model=SuccessResponse)
async def get_user_tools(
principal: dict = Depends(require_auth),
db: AsyncSession = Depends(get_db)
):
"""获取用户创建的所有工具"""
user_id = principal.get("user_id")
result = await db.execute(
select(Tool)
.where(Tool.owner_id == user_id)
.order_by(desc(Tool.created_at))
)
tools = result.scalars().all()
tools_data = []
for tool in tools:
tools_data.append({
"id": str(tool.id),
"name": tool.name,
"description": tool.description,
"template": tool.template, # 新增
"category": tool.category,
"envConfig": tool.env_config, # 新增(注意:敏感信息如密码应脱敏)
"created_at": tool.created_at.isoformat() if tool.created_at else None,
"updated_at": tool.updated_at.isoformat() if tool.updated_at else None,
"is_active": tool.is_active,
})
return SuccessResponse(data={"tools": tools_data})
```
### 3.5 数据库迁移
需要创建数据库迁移脚本,添加新字段:
```sql
-- 添加 template 字段
ALTER TABLE tools ADD COLUMN template VARCHAR(100);
-- 添加 env_config 字段
ALTER TABLE tools ADD COLUMN env_config JSON DEFAULT '{}';
-- 创建索引
CREATE INDEX idx_tool_template ON tools(template);
```
---
## 4. 更新后的接口文档
### 4.1 创建工具(基于模板)
**接口**: `POST /api/user/tools/create`
**请求参数**:
```typescript
interface CreateToolRequest {
name: string; // 工具名称(必填)
description?: string; // 工具描述
template: string; // 模板名称(必填,来自 dataTemplates[].template)
envConfig: Record<string, string>; // 环境变量配置(必填,根据模板 env_info 填写)
}
```
**请求示例(MySQL 工具)**:
```json
{
"name": "my-mysql-tool",
"description": "我的MySQL数据库连接工具",
"template": "mysql_agent",
"envConfig": {
"MYSQL_HOST": "mysql.example.com",
"MYSQL_USER": "root",
"MYSQL_PASSWORD": "password123",
"MYSQL_DATABASE": "mydb",
"MYSQL_PORT": "3306",
"OPENAI_API_KEY": "sk-xxx"
}
}
```
**请求示例(PostgreSQL 工具)**:
```json
{
"name": "my-pgsql-tool",
"description": "我的PostgreSQL数据库连接工具",
"template": "postgresql_agent",
"envConfig": {
"POSTGRES_HOST": "postgres.example.com",
"POSTGRES_USER": "postgres",
"POSTGRES_PASSWORD": "password123",
"POSTGRES_DATABASE": "mydb",
"POSTGRES_PORT": "5432",
"OPENAI_API_KEY": "sk-xxx"
}
}
```
**响应示例**:
```json
{
"success": true,
"data": {
"id": "d14cd898-e2cf-4150-a7f9-53b962c1c9a2",
"name": "my-mysql-tool",
"template": "mysql_agent"
},
"message": "工具创建成功"
}
```
### 4.2 创建自定义 Agent(选择工具)
**接口**: `POST /api/user/custom-agents`
**请求参数变化**:
```typescript
interface CreateCustomAgentRequest {
name: string; // Agent名称(必填)
tools: string[]; // 工具ID列表(必填,第一个工具决定 Agent 类型)
// 以下参数变为可选(可从工具自动获取)
template?: string; // 模板名称(可选,默认从工具获取)
envConfig?: Record<string, string>; // 额外环境变量(可选,会与工具配置合并)
// 资源配置
cpuRequest?: string; // 默认 "100m"
memoryRequest?: string; // 默认 "128Mi"
// 其他可选参数
frameworkTemplate?: string; // 默认 "MCP"
model?: string;
}
```
**请求示例**:
```json
{
"name": "my-mysql-agent",
"tools": ["d14cd898-e2cf-4150-a7f9-53b962c1c9a2"],
"cpuRequest": "500m",
"memoryRequest": "1Gi",
"model": "gpt-4"
}
```
**说明**:
- `template` 和 `envConfig` 从工具自动获取
- 请求中的 `envConfig` 会与工具配置合并(请求中的优先)
---
## 5. 修改检查清单
- [ ] **models.py**: 添加 `template` 和 `env_config` 字段到 Tool 模型
- [ ] **数据库迁移**: 创建迁移脚本添加新字段
- [ ] **user.py - create_tool**: 修改创建工具接口,支持 template 和 envConfig
- [ ] **user.py - create_custom_agent**: 修改创建 Agent 接口,从工具获取模板和配置
- [ ] **user.py - get_user_tools**: 修改响应格式,包含 template 和 envConfig
- [ ] **schemas.py**: 更新请求/响应模型定义
- [ ] **接口文档**: 更新前端接口文档
---
## 6. 测试用例
### 6.1 创建工具
```bash
# 创建 MySQL 工具
curl -X POST /api/user/tools/create \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "my-mysql-tool",
"template": "mysql_agent",
"envConfig": {
"MYSQL_HOST": "mysql.example.com",
"MYSQL_USER": "root",
"MYSQL_PASSWORD": "password123",
"MYSQL_DATABASE": "mydb"
}
}'
```
### 6.2 创建 Agent(选择工具)
```bash
# 创建 Agent,选择已创建的工具
curl -X POST /api/user/custom-agents \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "my-mysql-agent",
"tools": ["d14cd898-e2cf-4150-a7f9-53b962c1c9a2"],
"cpuRequest": "500m",
"memoryRequest": "1Gi"
}'
```
---
**如有问题,请联系大智开发团队。**