Files
taiji-AI-PAD/docs/agent-domain-access-改动计划.md
T
2026-01-14 13:42:36 +00:00

15 KiB
Raw Blame History

Agent 域名访问改动计划

版本: 2026-01-14 v1
状态: ✅ 已完成
相关服务: mcp-server, agent-manager 完成时间: 2026-01-14


📋 背景与需求

业务变更说明

  1. Agent Manager 服务升级:部署好的每个 Pod 现在会自动绑定域名和外网 IP
  2. 访问方式变更:租户后续将使用域名访问属于自己的平台 Agent 和自定义 Agent
  3. 数据存储需求:需要记录 Agent Manager 返回的访问信息(domain、external_ip 等)

Agent Manager 返回的 access_info 结构

{
  "access_info": {
    "external_ip": "135.171.210.24",
    "ip_url": "http://135.171.210.24:80",
    "domain": "my-agent.taijiagent.com",
    "domain_url": "http://my-agent.taijiagent.com",
    "recommended": "http://my-agent.taijiagent.com"
  }
}

🔍 当前代码分析

1. 数据库模型现状

Agent 模型 (models.py:125)

class Agent(BaseModel, Base):
    # ... 已有字段
    access_url = Column(String(500))  # 访问 URL(单个字段)
    endpoints = Column(JSON, default=dict)  # 端点信息
    # ❌ 缺少 domain、external_ip 等字段

AgentBillingRecord 模型 (models.py:1157)

class AgentBillingRecord(BaseModel, Base):
    # ... 已有字段
    agent_name = Column(String(100), nullable=False)
    # ❌ 缺少 access_info 相关字段(domain、external_ip、access_url)

2. Agent Manager Client 现状

AgentCreateResult (agent_manager_client.py:97)

@dataclass
class AgentCreateResult:
    name: str
    namespace: str
    status: str
    access_info: Optional[Dict[str, Any]] = None  # ✅ 已有,但未完整使用

AgentStatusResult (agent_manager_client.py:119)

@dataclass
class AgentStatusResult:
    # ❌ 缺少 domain、external_ip 等字段
    access_url: Optional[str] = None  # 只有单个 access_url
    endpoints: Optional[List[str]] = None

3. 创建 Agent 代码现状

平台 Agent 创建 (user.py:1427-1439)

result = await client.create_agent(...)
# 创建 Agent 记录时
agent = Agent(
    name=instance_name,
    # ❌ 未保存 result.access_info 中的 domain、external_ip
)

自定义 Agent 创建 (user.py:3146-3157)

result = await client.create_custom_agent(...)
# ❌ 响应中只返回了 accessInfo,未持久化 domain 到数据库
return SuccessResponse(
    data={
        "accessInfo": result.access_info,  # 只是透传,未存储
    }
)

4. 查询 Agent 列表代码现状

用户 Agent 资源查询 (user.py:3904-3999)

@router.get("/resources/agents")
async def get_user_agents_info(...):
    # 从 Agent Manager 获取状态
    agent_status = await client.get_agent_status(record.agent_name)
    agent_info["accessUrl"] = agent_status.access_url  # ❌ 只返回 access_url
    # ❌ 缺少 domain、external_ip 等字段

✅ 改动方案

阶段一:数据库模型改动

1.1 修改 AgentBillingRecord 模型

文件: services/mcp-server/models.py

class AgentBillingRecord(BaseModel, Base):
    # ... 已有字段
    
    # ========== 新增:访问信息字段 ==========
    external_ip = Column(String(45), nullable=True)  # 外网 IP 地址
    domain = Column(String(255), nullable=True)  # 域名
    domain_url = Column(String(500), nullable=True)  # 域名访问地址
    access_url = Column(String(500), nullable=True)  # 推荐访问地址
    service_port = Column(Integer, nullable=True)  # 服务端口
    namespace = Column(String(100), nullable=True)  # K8s 命名空间

1.2 创建数据库迁移脚本

文件: services/mcp-server/alembic/versions/xxxx_add_agent_access_info.py

"""Add agent access info fields

Revision ID: xxxx
"""

def upgrade():
    op.add_column('agent_billing_records', 
        sa.Column('external_ip', sa.String(45), nullable=True))
    op.add_column('agent_billing_records', 
        sa.Column('domain', sa.String(255), nullable=True))
    op.add_column('agent_billing_records', 
        sa.Column('domain_url', sa.String(500), nullable=True))
    op.add_column('agent_billing_records', 
        sa.Column('access_url', sa.String(500), nullable=True))
    op.add_column('agent_billing_records', 
        sa.Column('service_port', sa.Integer, nullable=True))
    op.add_column('agent_billing_records', 
        sa.Column('namespace', sa.String(100), nullable=True))
    
    # 添加索引(可选,用于按域名查询)
    op.create_index('idx_agent_billing_domain', 'agent_billing_records', ['domain'])

def downgrade():
    op.drop_index('idx_agent_billing_domain', 'agent_billing_records')
    op.drop_column('agent_billing_records', 'namespace')
    op.drop_column('agent_billing_records', 'service_port')
    op.drop_column('agent_billing_records', 'access_url')
    op.drop_column('agent_billing_records', 'domain_url')
    op.drop_column('agent_billing_records', 'domain')
    op.drop_column('agent_billing_records', 'external_ip')

阶段二:Agent Manager Client 改动

2.1 修改 AgentStatusResult

文件: services/mcp-server/app/agent_manager_client.py

@dataclass
class AgentStatusResult:
    # ... 已有字段
    
    # ========== 新增:访问信息字段 ==========
    external_ip: Optional[str] = None  # 外网 IP
    domain: Optional[str] = None  # 域名
    domain_url: Optional[str] = None  # 域名访问地址

2.2 修改 get_agent_status 方法解析逻辑

文件: services/mcp-server/app/agent_manager_client.py

在 get_agent_status 方法中,需要解析 Agent Manager 返回的 access_info:

async def get_agent_status(self, name: str) -> AgentStatusResult:
    # ... 现有逻辑
    
    # 解析 access_info
    access_info = data.get("access_info", {})
    
    return AgentStatusResult(
        # ... 现有字段
        external_ip=access_info.get("external_ip"),
        domain=access_info.get("domain"),
        domain_url=access_info.get("domain_url"),
        access_url=access_info.get("recommended") or access_info.get("domain_url"),
    )

阶段三:创建 Agent 代码改动

3.1 平台 Agent 创建改动

文件: services/mcp-server/app/routes/user.py

位置: list_platform_agents / deploy_platform_agent 函数

# 在创建 billing_record 时保存 access_info
billing_record = AgentBillingRecord(
    # ... 已有字段
    
    # ========== 新增:保存访问信息 ==========
    external_ip=result.access_info.get("external_ip") if result.access_info else None,
    domain=result.access_info.get("domain") if result.access_info else None,
    domain_url=result.access_info.get("domain_url") if result.access_info else None,
    access_url=result.access_info.get("recommended") if result.access_info else None,
    service_port=result.service_port,
    namespace=result.namespace,
)

3.2 自定义 Agent 创建改动

文件: services/mcp-server/app/routes/user.py

位置: create_custom_agent 函数(约第 3146-3213 行)

# 在创建 billing_record 时保存 access_info
billing_record = AgentBillingRecord(
    # ... 已有字段
    
    # ========== 新增:保存访问信息 ==========
    external_ip=result.access_info.get("external_ip") if result.access_info else None,
    domain=result.access_info.get("domain") if result.access_info else None,
    domain_url=result.access_info.get("domain_url") if result.access_info else None,
    access_url=result.access_info.get("recommended") if result.access_info else None,
    service_port=result.service_port,
    namespace=result.namespace,
)

阶段四:查询 Agent 列表改动

4.1 用户 Agent 资源查询改动

文件: services/mcp-server/app/routes/user.py

位置: get_user_agents_info 函数(约第 3904-3999 行)

@router.get("/resources/agents", response_model=SuccessResponse)
async def get_user_agents_info(...):
    for record in billing_records:
        agent_info = {
            # ... 已有字段
            
            # ========== 新增:访问信息字段(优先使用数据库存储的值) ==========
            "externalIp": record.external_ip,
            "domain": record.domain,
            "domainUrl": record.domain_url,
            "accessUrl": record.access_url,  # 推荐访问地址
        }
        
        # 从 Agent Manager 获取最新状态(实时更新 IP 等信息)
        if agent_manager_available and client:
            try:
                agent_status = await client.get_agent_status(record.agent_name)
                # 更新实时状态
                agent_info["status"] = agent_status.status
                agent_info["healthStatus"] = agent_status.health_status
                agent_info["podIp"] = agent_status.pod_ip
                
                # 更新访问信息(如果 Agent Manager 返回了新的值)
                if agent_status.external_ip:
                    agent_info["externalIp"] = agent_status.external_ip
                if agent_status.domain:
                    agent_info["domain"] = agent_status.domain
                if agent_status.domain_url:
                    agent_info["domainUrl"] = agent_status.domain_url
                if agent_status.access_url:
                    agent_info["accessUrl"] = agent_status.access_url
            except Exception as e:
                logger.warning(f"获取 Agent {record.agent_name} 状态失败: {e}")

4.2 自定义 Agent 列表查询改动

文件: services/mcp-server/app/routes/user.py

位置: list_my_custom_agents 函数(约第 3462-3516 行)

同样需要添加 domain 等字段的返回。


阶段五:响应模型改动

5.1 添加/修改 Schema

文件: services/mcp-server/app/schemas.py 或 services/mcp-server/schemas.py

class AgentAccessInfo(BaseModel):
    """Agent 访问信息"""
    external_ip: Optional[str] = Field(None, description="外网 IP 地址")
    domain: Optional[str] = Field(None, description="域名")
    domain_url: Optional[str] = Field(None, description="域名访问地址")
    ip_url: Optional[str] = Field(None, description="IP 访问地址")
    recommended: Optional[str] = Field(None, description="推荐访问地址")


class AgentResourceInfo(BaseModel):
    """用户 Agent 资源信息"""
    name: str
    template: str
    templateName: Optional[str] = None
    status: str
    healthStatus: str
    
    # Pod 信息
    podIp: Optional[str] = None
    hostIp: Optional[str] = None
    nodeName: Optional[str] = None
    
    # ========== 新增:访问信息 ==========
    externalIp: Optional[str] = Field(None, description="外网 IP 地址")
    domain: Optional[str] = Field(None, description="域名")
    domainUrl: Optional[str] = Field(None, description="域名访问地址")
    accessUrl: Optional[str] = Field(None, description="推荐访问地址(域名优先)")
    
    # 资源配置
    servicePort: Optional[int] = None
    namespace: str = "ai-agents"
    cpu: Optional[str] = None
    memory: Optional[str] = None
    replicas: int = 1
    
    # 运行信息
    startTime: Optional[str] = None
    runningSeconds: int = 0
    endpoints: Optional[List[str]] = None

📄 接口文档更新

GET /api/user/resources/agents 响应更新

{
  "success": true,
  "data": {
    "platformAgents": [
      {
        "name": "echo-agent-b00a7b8e-fa5a66",
        "template": "echo_agent",
        "templateName": "echo_agent",
        "status": "Running",
        "healthStatus": "healthy",
        "podIp": "10.244.2.103",
        "externalIp": "135.171.210.24",
        "domain": "echo-agent-b00a7b8e-fa5a66.taijiagent.com",
        "domainUrl": "http://echo-agent-b00a7b8e-fa5a66.taijiagent.com",
        "accessUrl": "http://echo-agent-b00a7b8e-fa5a66.taijiagent.com",
        "servicePort": 80,
        "namespace": "agent-echo-agent-b00a7b8e-fa5a66",
        "cpu": "100m",
        "memory": "256Mi",
        "replicas": 1,
        "startTime": "2026-01-11T15:17:17.579421",
        "runningSeconds": 227937
      }
    ],
    "customAgents": [
      {
        "name": "my-mysql-agent",
        "template": "mysql_agent",
        "templateName": "MCP",
        "status": "Running",
        "healthStatus": "healthy",
        "podIp": "10.244.1.61",
        "externalIp": "135.171.210.25",
        "domain": "my-mysql-agent.taijiagent.com",
        "domainUrl": "http://my-mysql-agent.taijiagent.com",
        "accessUrl": "http://my-mysql-agent.taijiagent.com",
        "servicePort": 80,
        "namespace": "agent-my-mysql-agent",
        "cpu": "500m",
        "memory": "1Gi",
        "replicas": 1,
        "startTime": "2026-01-13T07:32:52.290231",
        "runningSeconds": 83003
      }
    ],
    "summary": {
      "totalPlatformAgents": 1,
      "totalCustomAgents": 1
    }
  },
  "message": "Agent 列表获取成功"
}

📝 改动文件清单

序号 文件路径 改动类型 改动说明
1 services/mcp-server/models.py 修改 AgentBillingRecord 添加访问信息字段
2 services/mcp-server/alembic/versions/xxx.py 新增 数据库迁移脚本
3 services/mcp-server/app/agent_manager_client.py 修改 AgentStatusResult 添加 domain 等字段
4 services/mcp-server/app/routes/user.py 修改 创建 Agent 时保存 access_info
5 services/mcp-server/app/routes/user.py 修改 查询 Agent 列表返回 domain 等字段
6 services/mcp-server/app/schemas.py 修改 添加/修改响应模型
7 Docs/用户资源信息查询接口文档.md 修改 更新接口文档
8 Docs/数据工具与自定义Agent-前端接口文档.md 修改 更新接口文档

🔄 实施步骤

Step 1: 数据库改动(需要停机)

  1. 备份数据库
  2. 执行数据库迁移脚本
  3. 验证迁移结果

Step 2: 代码改动

  1. 修改 models.py
  2. 修改 agent_manager_client.py
  3. 修改 user.py 中的创建 Agent 逻辑
  4. 修改 user.py 中的查询 Agent 逻辑
  5. 修改响应模型

Step 3: 测试验证

  1. 单元测试
  2. 集成测试(创建 Agent → 查询列表 → 访问域名)
  3. 前端联调

Step 4: 文档更新

  1. 更新 API 接口文档
  2. 更新前端接口文档

⚠️ 注意事项

  1. 向后兼容:新增字段均为可选(nullable=True),不影响现有数据
  2. 域名生效时间:域名 DNS 解析可能有延迟(通常 1-5 分钟)
  3. 访问优先级:推荐使用 accessUrl(域名优先),Pod IP 会随重启变化
  4. 安全考虑:域名访问可能需要配置 HTTPS(后续考虑)

📊 预估工时

阶段 工时估算
数据库改动 0.5 天
Agent Manager Client 改动 0.5 天
创建 Agent 代码改动 1 天
查询 Agent 列表改动 0.5 天
测试与联调 1 天
文档更新 0.5 天
总计 4 天

文档编写: AI Assistant
最后更新: 2026-01-14