# Agent 发送给 Agent Manager 的数据结构文档 本文档详细说明 mcp-server 中**平台 Agent** 和**自定义 Agent** 发送给 Agent Manager 服务端的请求数据结构和参数说明。 ## 目录 1. [统一接口说明](#统一接口说明) 2. [平台 Agent 数据结构](#平台-agent-数据结构) 3. [自定义 Agent 数据结构](#自定义-agent-数据结构) 4. [请求参数详细说明](#请求参数详细说明) 5. [代码位置](#代码位置) --- ## 统一接口说明 无论是平台 Agent 还是自定义 Agent,最终都通过 **`POST /agents`** 接口发送请求到 Agent Manager。 **接口路径**: `POST {AGENT_MANAGER_URL}/agents` **代码位置**: `services/mcp-server/app/agent_manager_client.py` **统一方法**: `create_agent()` --- ## 平台 Agent 数据结构 ### 请求体结构 ```json { "name": "echo-agent-alice1234-abc123", "template": "echo_agent", "config": { "user_id": "alice", "cpu_request": "100m", "cpu_limit": "500m", "memory_request": "128Mi", "memory_limit": "512Mi", "replicas": 1 }, "env": { "LLM_BASE_URL": "https://litellm.graystone-fb459c5d.southeastasia.azurecontainerapps.io", "OPENAI_API_BASE": "https://litellm.graystone-fb459c5d.southeastasia.azurecontainerapps.io", "OPENAI_API_KEY": "sk-...", "MODEL_NAME": "gpt-4", "LITELLM_MODEL": "gpt-4" } } ``` ### 字段说明 | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | `name` | string | ✅ | Agent 实例名称(1-63字符,小写字母、数字、连字符) | | `template` | string | ✅ | 平台模板名称(如 `echo_agent`, `jina_search_agent`) | | `config` | object | ✅ | 资源配置对象 | | `config.user_id` | string | ✅ | 用户 ID(用于资源隔离和计费) | | `config.cpu_request` | string | ✅ | CPU 请求量(如 `"100m"`) | | `config.cpu_limit` | string | ✅ | CPU 限制量(如 `"500m"`) | | `config.memory_request` | string | ✅ | 内存请求量(如 `"128Mi"`) | | `config.memory_limit` | string | ✅ | 内存限制量(如 `"512Mi"`) | | `config.replicas` | integer | ✅ | 副本数量(平台 Agent 默认为 1) | | `env` | object | ✅ | 环境变量(至少包含 `LLM_BASE_URL`) | | `env.LLM_BASE_URL` | string | ✅ | LiteLLM 服务地址(固定值,自动注入) | | `env.OPENAI_API_BASE` | string | 否 | LiteLLM API 基础地址(如果用户指定了模型) | | `env.OPENAI_API_KEY` | string | 否 | LiteLLM API 密钥(如果用户指定了模型) | | `env.MODEL_NAME` | string | 否 | 模型名称(如果用户指定了模型) | | `env.LITELLM_MODEL` | string | 否 | LiteLLM 模型名称(如果用户指定了模型) | ### 代码实现位置 **主要调用位置**: - `services/mcp-server/app/routes/user.py` - `deploy_platform_agent()` (行 2261-2512) - `services/mcp-server/app/routes/user.py` - `deploy_platform_agent_instances()` (行 1310-1509) **关键代码片段**: ```808:847:services/mcp-server/app/agent_manager_client.py payload: Dict[str, Any] = { "name": name, "template": template } if config: payload["config"] = config.to_dict() # 构建环境变量,确保 LLM_BASE_URL 始终被传递(平台 Agent 和自定义 Agent 都需要) final_env = {"LLM_BASE_URL": LLM_BASE_URL} if env: # 用户传入的环境变量会覆盖默认值(但通常不应覆盖 LLM_BASE_URL) final_env.update(env) payload["env"] = final_env ``` **平台 Agent 创建示例**: ```2421:2445:services/mcp-server/app/routes/user.py # 创建平台 Agent 实例 agent_config = AgentConfig( user_id=str(user_id), cpu_request=quota.cpu_per_pod or "100m", cpu_limit=quota.cpu_per_pod or "500m", memory_request=quota.memory_per_pod or "128Mi", memory_limit=quota.memory_per_pod or "512Mi", replicas=1, # 平台 Agent 默认单副本 ) # 如果有环境变量,使用 create_agent;否则使用 create_platform_agent if env_vars: result = await client.create_agent( name=instance_name, template=req.agentType, config=agent_config, env=env_vars ) else: result = await client.create_platform_agent( name=instance_name, template=req.agentType, user_id=str(user_id), config=agent_config ) ``` --- ## 自定义 Agent 数据结构 ### 请求体结构 ```json { "name": "my-mysql-agent", "template": "mysql_agent", "config": { "user_id": "alice", "cpu_request": "1000m", "cpu_limit": "2000m", "memory_request": "1Gi", "memory_limit": "2Gi", "replicas": 1 }, "env": { "LLM_BASE_URL": "https://litellm.graystone-fb459c5d.southeastasia.azurecontainerapps.io", "FRAMEWORK_TYPE": "MCP", "MYSQL_HOST": "mysql.example.com", "MYSQL_USER": "root", "MYSQL_PASSWORD": "password123", "MYSQL_DATABASE": "mydb", "OPENAI_API_BASE": "https://litellm.graystone-fb459c5d.southeastasia.azurecontainerapps.io", "OPENAI_API_KEY": "sk-...", "MODEL_NAME": "gpt-4", "LITELLM_MODEL": "gpt-4", "TOOLS": "[\"tool-uuid-1\", \"tool-uuid-2\"]", "TOOLS_CONFIG": "[{\"id\": \"tool-uuid-1\", \"name\": \"mysql_query\", \"endpoint\": \"...\", ...}]", "AGENT_ID": "my-mysql-agent-1704067200", "AGENT_ROLE": "data_analyzer", "AGENT_CAPABILITIES": "[\"sql_query\", \"data_analysis\"]" } } ``` ### 字段说明 | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | `name` | string | ✅ | Agent 名称(1-63字符,小写字母、数字、连字符) | | `template` | string | ✅ | 自定义模板名称(如 `mysql_agent`, `postgresql_agent`) | | `config` | object | ✅ | 资源配置对象 | | `config.user_id` | string | ✅ | 用户 ID | | `config.cpu_request` | string | ✅ | CPU 请求量(用户自定义,如 `"1000m"`) | | `config.cpu_limit` | string | ✅ | CPU 限制量(用户自定义,如 `"2000m"`) | | `config.memory_request` | string | ✅ | 内存请求量(用户自定义,如 `"1Gi"`) | | `config.memory_limit` | string | ✅ | 内存限制量(用户自定义,如 `"2Gi"`) | | `config.replicas` | integer | ✅ | 副本数量(自定义 Agent 默认为 1) | | `env` | object | ✅ | 环境变量(必需,包含数据库连接、API Key 等) | | `env.LLM_BASE_URL` | string | ✅ | LiteLLM 服务地址(固定值,自动注入) | | `env.FRAMEWORK_TYPE` | string | ✅ | 框架类型(`MCP` / `A2A` / `langchain`) | | `env.ENDPOINT` | string | 否 | 用户自定义终结点 | | `env.API_KEY` | string | 否 | 用户 API 密钥 | | `env.MYSQL_HOST` | string | 否 | MySQL 主机地址(模板相关) | | `env.MYSQL_USER` | string | 否 | MySQL 用户名(模板相关) | | `env.MYSQL_PASSWORD` | string | 否 | MySQL 密码(模板相关) | | `env.MYSQL_DATABASE` | string | 否 | MySQL 数据库名(模板相关) | | `env.OPENAI_API_BASE` | string | 否 | LiteLLM API 基础地址(如果指定了模型) | | `env.OPENAI_API_KEY` | string | 否 | LiteLLM API 密钥(如果指定了模型或自动注入) | | `env.MODEL_NAME` | string | 否 | 模型名称(如果指定了模型) | | `env.LITELLM_MODEL` | string | 否 | LiteLLM 模型名称(如果指定了模型) | | `env.TOOLS` | string | 否 | 工具 ID 列表(JSON 字符串格式) | | `env.TOOLS_CONFIG` | string | 否 | 工具详细配置(JSON 字符串格式,包含 endpoint、method、schema 等) | | `env.AGENT_ID` | string | 否 | A2A 框架专用:Agent ID | | `env.AGENT_ROLE` | string | 否 | A2A 框架专用:Agent 角色(如 `data_analyzer`) | | `env.AGENT_CAPABILITIES` | string | 否 | A2A 框架专用:Agent 能力列表(JSON 字符串格式) | ### 环境变量构建优先级 自定义 Agent 的环境变量按以下优先级合并(从低到高): 1. **工具的 `env_config`**(如果选择了工具) 2. **请求中的 `envConfig`**(用户手动配置) 3. **系统自动注入**(如 `LLM_BASE_URL`、模型配置等) ### 代码实现位置 **主要调用位置**: - `services/mcp-server/app/routes/user.py` - `create_custom_agent()` (行 2871-3341) **关键代码片段**: ```3067:3087:services/mcp-server/app/routes/user.py # ========== 构建环境变量 ========== # 1. 先使用工具的环境变量配置作为基础 env_vars = tool_env_config.copy() # 2. 再合并请求中的 envConfig(请求中的优先) if req.envConfig: env_vars.update(req.envConfig) # 3. 注入框架模板类型 env_vars["FRAMEWORK_TYPE"] = framework_template if req.endpoint: env_vars["ENDPOINT"] = req.endpoint if req.apiKey: env_vars["API_KEY"] = req.apiKey logger.info( f"环境变量构建完成: tool_env_keys={list(tool_env_config.keys())}, " f"req_env_keys={list((req.envConfig or {}).keys())}, " f"final_env_keys={list(env_vars.keys())}" ) # ================================= ``` **工具配置传递**: ```3089:3145:services/mcp-server/app/routes/user.py # ========== 工具配置传递给 Agent Manager ========== import json if req.tools: # 1. 传递工具 ID 列表(JSON 字符串格式) env_vars["TOOLS"] = json.dumps(req.tools) # 2. 查询工具详情,构建完整工具配置 try: tool_ids = [] for tid in req.tools: try: tool_ids.append(PyUUID(tid)) except (ValueError, TypeError): logger.warning(f"无效的工具 ID 格式: {tid}") if tool_ids: tool_result = await db.execute( select(Tool).where( Tool.id.in_(tool_ids), or_( Tool.is_public == True, Tool.owner_id == PyUUID(user_id) ) ) ) tools = tool_result.scalars().all() # 构建工具配置列表(包含 Agent 运行时需要的信息) tools_config = [] for tool in tools: tool_config = { "id": str(tool.id), "name": tool.name, "description": tool.description, "endpoint": tool.endpoint, "method": tool.method, "schema": tool.schema, "timeout": tool.timeout, "auth_type": tool.auth_type, } # 如果是用户自己的工具,传递认证配置 if tool.owner_id and str(tool.owner_id) == user_id and tool.auth_config: tool_config["auth_config"] = tool.auth_config tools_config.append(tool_config) # 传递工具详细配置(供 Agent 运行时使用) if tools_config: env_vars["TOOLS_CONFIG"] = json.dumps(tools_config) logger.info( f"工具配置已准备: user_id={user_id}, tool_count={len(tools_config)}, " f"tool_names={[t['name'] for t in tools_config]}" ) except Exception as e: logger.warning(f"查询工具详情失败,仅传递工具 ID 列表: {str(e)}") # ================================================ ``` **A2A 框架配置**: ```3147:3168:services/mcp-server/app/routes/user.py # ========== A2A 框架配置 ========== if framework_template == "A2A": import time as time_module # 生成 Agent ID(使用名称和时间戳确保唯一性) agent_id = f"{req.name}-{int(time_module.time())}" env_vars["AGENT_ID"] = agent_id # 设置 Agent 角色 agent_role = req.agentRole or env_vars.get("AGENT_ROLE", "custom_agent") env_vars["AGENT_ROLE"] = agent_role # 设置 Agent 能力 capabilities = req.agentCapabilities or req.tools or [] if capabilities: env_vars["AGENT_CAPABILITIES"] = json.dumps(capabilities) logger.info( f"A2A 配置已准备: agent_id={agent_id}, agent_role={agent_role}, " f"capabilities={capabilities}" ) # ================================== ``` **自定义 Agent 创建调用**: ```3240:3260:services/mcp-server/app/routes/user.py try: client = get_agent_manager_client() # 创建 Agent 配置 agent_config = AgentConfig( user_id=str(user_id), cpu_request=req.cpuRequest, cpu_limit=req.cpuLimit or req.cpuRequest, memory_request=req.memoryRequest, memory_limit=req.memoryLimit or req.memoryRequest, replicas=1, # 自定义 Agent 默认单副本 ) # 创建自定义 Agent(使用从工具获取的模板名称) result = await client.create_custom_agent( name=req.name, template=template_name, # 使用从工具获取或请求中指定的模板 user_id=str(user_id), env_vars=env_vars, config=agent_config ) ``` --- ## 请求参数详细说明 ### AgentConfig 对象 **定义位置**: `services/mcp-server/app/agent_manager_client.py` (行 33-62) ```python @dataclass class AgentConfig: user_id: Optional[str] = None cpu_request: Optional[str] = "100m" cpu_limit: Optional[str] = "500m" memory_request: Optional[str] = "128Mi" memory_limit: Optional[str] = "512Mi" replicas: Optional[int] = 1 ``` **转换为字典方法**: ```47:62:services/mcp-server/app/agent_manager_client.py def to_dict(self) -> Dict[str, Any]: """Converts to API request format""" result = {} if self.user_id: result["user_id"] = self.user_id if self.cpu_request: result["cpu_request"] = self.cpu_request if self.cpu_limit: result["cpu_limit"] = self.cpu_limit if self.memory_request: result["memory_request"] = self.memory_request if self.memory_limit: result["memory_limit"] = self.memory_limit if self.replicas is not None: result["replicas"] = self.replicas return result ``` ### 环境变量说明 #### 固定环境变量 | 变量名 | 值 | 说明 | 来源 | |--------|-----|------|------| | `LLM_BASE_URL` | `https://litellm.graystone-fb459c5d.southeastasia.azurecontainerapps.io` | LiteLLM 服务地址 | 环境变量 `LLM_BASE_URL`,默认值见代码 | **代码位置**: `services/mcp-server/app/agent_manager_client.py` (行 20-21) ```20:21:services/mcp-server/app/agent_manager_client.py # LLM_BASE_URL - 所有 Agent(平台和自定义)都必须传递的固定参数 LLM_BASE_URL = os.getenv("LLM_BASE_URL", "https://litellm.graystone-fb459c5d.southeastasia.azurecontainerapps.io") ``` #### 可选环境变量(根据用户配置注入) | 变量名 | 说明 | 注入条件 | |--------|------|----------| | `OPENAI_API_BASE` | LiteLLM API 基础地址 | 用户指定了模型或自动注入 | | `OPENAI_API_KEY` | LiteLLM API 密钥 | 用户指定了模型或自动注入 | | `MODEL_NAME` | 模型名称 | 用户指定了模型 | | `LITELLM_MODEL` | LiteLLM 模型名称 | 用户指定了模型 | | `FRAMEWORK_TYPE` | 框架类型(MCP/A2A/langchain) | 自定义 Agent 必填 | | `ENDPOINT` | 用户自定义终结点 | 用户提供了 endpoint | | `API_KEY` | 用户 API 密钥 | 用户提供了 apiKey | | `TOOLS` | 工具 ID 列表(JSON 字符串) | 用户选择了工具 | | `TOOLS_CONFIG` | 工具详细配置(JSON 字符串) | 用户选择了工具 | | `AGENT_ID` | A2A Agent ID | 框架类型为 A2A | | `AGENT_ROLE` | A2A Agent 角色 | 框架类型为 A2A | | `AGENT_CAPABILITIES` | A2A Agent 能力列表(JSON 字符串) | 框架类型为 A2A | #### 模板相关环境变量 根据不同的模板类型,可能需要不同的环境变量。例如: - **MySQL Agent**: `MYSQL_HOST`, `MYSQL_USER`, `MYSQL_PASSWORD`, `MYSQL_DATABASE` - **PostgreSQL Agent**: `PG_HOST`, `PG_USER`, `PG_PASSWORD`, `PG_DATABASE` - **其他模板**: 参考 Agent Manager 的模板定义 **获取模板环境变量要求**: ```742:759:services/mcp-server/app/agent_manager_client.py async def get_template(self, template_name: str) -> TemplateInfo: """ Get template details Call: GET /templates/{template_name} Args: template_name: Template name Returns: Template information """ data = await self._request("GET", f"/templates/{template_name}") return TemplateInfo( template=data["template"], port=data.get("port"), env_info=data.get("env_info", {}) ) ``` ### 工具配置格式 #### TOOLS 环境变量 **格式**: JSON 字符串数组 **示例**: ```json ["tool-uuid-1", "tool-uuid-2", "tool-uuid-3"] ``` #### TOOLS_CONFIG 环境变量 **格式**: JSON 字符串数组,每个元素包含工具的完整配置 **示例**: ```json [ { "id": "tool-uuid-1", "name": "mysql_query", "description": "MySQL 查询工具", "endpoint": "https://api.example.com/mysql/query", "method": "POST", "schema": { "type": "object", "properties": { "query": {"type": "string"} } }, "timeout": 30, "auth_type": "bearer", "auth_config": { "token": "secret-token" } } ] ``` **代码位置**: `services/mcp-server/app/routes/user.py` (行 3117-3137) --- ## 代码位置 ### 核心文件 1. **Agent Manager 客户端** - 文件: `services/mcp-server/app/agent_manager_client.py` - 主要类: `AgentManagerClient` - 主要方法: `create_agent()`, `create_platform_agent()`, `create_custom_agent()` 2. **平台 Agent 路由** - 文件: `services/mcp-server/app/routes/user.py` - 主要函数: - `deploy_platform_agent()` (行 2261-2512) - `deploy_platform_agent_instances()` (行 1310-1509) 3. **自定义 Agent 路由** - 文件: `services/mcp-server/app/routes/user.py` - 主要函数: `create_custom_agent()` (行 2871-3341) 4. **数据模型定义** - 文件: `services/mcp-server/app/schemas.py` - 主要类: - `CreateCustomAgentRequest` (行 815-851) - `UsePlatformAgentRequest` (行 794-799) ### 关键方法调用链 #### 平台 Agent ``` deploy_platform_agent() └─> AgentManagerClient.create_agent() └─> AgentManagerClient._request("POST", "/agents", json=payload) ``` #### 自定义 Agent ``` create_custom_agent() └─> AgentManagerClient.create_custom_agent() └─> AgentManagerClient.create_agent() └─> AgentManagerClient._request("POST", "/agents", json=payload) ``` --- ## 总结 ### 平台 Agent vs 自定义 Agent 对比 | 特性 | 平台 Agent | 自定义 Agent | |------|-----------|-------------| | **模板来源** | 平台预定义模板 | 用户选择的数据存储模板 | | **环境变量** | 最少(仅 LLM_BASE_URL + 可选的模型配置) | 丰富(包含数据库连接、API Key、工具配置等) | | **资源配置** | 从配额获取 | 用户自定义 | | **框架类型** | 固定(由模板决定) | 用户选择(MCP/A2A/langchain) | | **工具配置** | 不支持 | 支持(通过 TOOLS 和 TOOLS_CONFIG) | | **A2A 配置** | 不支持 | 支持(如果 frameworkTemplate="A2A") | ### 共同点 1. 都通过 `POST /agents` 接口发送请求 2. 都包含 `name`, `template`, `config`, `env` 四个主要字段 3. 都自动注入 `LLM_BASE_URL` 环境变量 4. 都支持模型配置注入(如果用户指定了模型) --- **文档生成时间**: 2025-01-XX **代码版本**: 基于当前代码库状态