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

16 KiB
Raw Blame History

数据工具与自定义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 模型,添加字段:

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 接口:

@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 接口的工具处理逻辑:

@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 响应格式:

@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 数据库迁移

需要创建数据库迁移脚本,添加新字段:

-- 添加 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

请求参数:

interface CreateToolRequest {
  name: string;           // 工具名称(必填)
  description?: string;   // 工具描述
  template: string;       // 模板名称(必填,来自 dataTemplates[].template)
  envConfig: Record<string, string>;  // 环境变量配置(必填,根据模板 env_info 填写)
}

请求示例(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"
  }
}

请求示例(PostgreSQL 工具):

{
  "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"
  }
}

响应示例:

{
  "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

请求参数变化:

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;
}

请求示例:

{
  "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 创建工具

# 创建 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(选择工具)

# 创建 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"
  }'

如有问题,请联系大智开发团队。