{
  "metadata": {
    "id": "ch35",
    "title": "第35章：企业级设计模式",
    "volume": "vol9",
    "volume_title": "Agent设计模式",
    "word_count": 1286,
    "difficulty": "advanced",
    "prerequisites": [
      "ch31",
      "ch32",
      "ch33",
      "ch34"
    ],
    "key_concepts": [
      "企业级Agent的特殊需求",
      "Agent Gateway模式",
      "API网关设计",
      "路由与负载均衡",
      "Agent Registry与发现",
      "服务注册",
      "多租户Agent架构",
      "租户隔离",
      "数据隔离",
      "Agent版本管理与回滚",
      "审计与合规模式",
      "操作审计",
      "PII处理",
      "高可用与容错模式",
      "多模型容错"
    ],
    "learning_objectives": [],
    "estimated_tokens": 772,
    "source_file": "vol9/ch35_企业级设计模式.md"
  },
  "overview": "将 Agent 从原型推向生产环境，面临的是一组截然不同的挑战：可靠性要求从\"基本能用\"提升到\"五个九\"可用性，安全从\"Demo够用\"升级到\"企业级合规\"，成本从\"不计代价\"转变为\"精打细算\"。本章将系统讲解企业级 Agent 系统的设计模式，涵盖 API 网关、多租户架构、版本管理、审计合规、高可用、成本管理、安全等核心主题。",
  "sections": [
    {
      "id": "35.1",
      "title": "35.1 企业级Agent的特殊需求",
      "level": 2,
      "content": "| 维度 | 原型阶段 | 企业级 |\n|------|---------|--------|\n| 可用性 | 90%+ | 99.9%+ |\n| 响应延迟 | <30秒 | <5秒 P95 |\n| 安全 | API Key | RBAC + 审计 + 加密 |\n| 多租户 | 单租户 | 1000+租户隔离 |\n| 成本 | 不关心 | 精确计量 + 预算控制 |\n| 部署 | 手动 | CI/CD + 蓝/绿 + 回滚 |\n| 监控 | 打印日志 | Dashboard + 告警 + SLO |",
      "subsections": []
    },
    {
      "id": "35.2",
      "title": "35.2 Agent Gateway模式",
      "level": 2,
      "content": "",
      "subsections": [
        {
          "id": "35.2.1",
          "title": "35.2.1 API网关设计",
          "content": ""
        },
        {
          "id": "35.2.2",
          "title": "35.2.2 路由与负载均衡",
          "content": ""
        }
      ]
    },
    {
      "id": "35.3",
      "title": "35.3 Agent Registry与发现",
      "level": 2,
      "content": "",
      "subsections": [
        {
          "id": "35.3.1",
          "title": "35.3.1 服务注册",
          "content": ""
        }
      ]
    },
    {
      "id": "35.4",
      "title": "35.4 多租户Agent架构",
      "level": 2,
      "content": "",
      "subsections": [
        {
          "id": "35.4.1",
          "title": "35.4.1 租户隔离",
          "content": ""
        },
        {
          "id": "35.4.2",
          "title": "35.4.2 数据隔离",
          "content": ""
        }
      ]
    },
    {
      "id": "35.5",
      "title": "35.5 Agent版本管理与回滚",
      "level": 2,
      "content": "",
      "subsections": []
    },
    {
      "id": "35.6",
      "title": "35.6 审计与合规模式",
      "level": 2,
      "content": "",
      "subsections": [
        {
          "id": "35.6.1",
          "title": "35.6.1 操作审计",
          "content": ""
        },
        {
          "id": "35.6.2",
          "title": "35.6.2 PII处理",
          "content": ""
        }
      ]
    },
    {
      "id": "35.7",
      "title": "35.7 高可用与容错模式",
      "level": 2,
      "content": "",
      "subsections": [
        {
          "id": "35.7.1",
          "title": "35.7.1 多模型容错",
          "content": ""
        },
        {
          "id": "35.7.2",
          "title": "35.7.2 优雅降级",
          "content": ""
        }
      ]
    },
    {
      "id": "35.8",
      "title": "35.8 成本管理模式",
      "level": 2,
      "content": "",
      "subsections": []
    },
    {
      "id": "35.9",
      "title": "35.9 企业级安全模式",
      "level": 2,
      "content": "",
      "subsections": [
        {
          "id": "35.9.1",
          "title": "35.9.1 RBAC权限控制",
          "content": ""
        },
        {
          "id": "35.9.2",
          "title": "35.9.2 零信任安全",
          "content": ""
        }
      ]
    },
    {
      "id": "最佳实践",
      "title": "最佳实践",
      "level": 2,
      "content": "1. **安全先行**：设计阶段就考虑安全、合规和隐私\n2. **配置外置**：Prompt、模型、工具列表通过配置管理\n3. **渐进部署**：金丝雀发布，先5%再全量\n4. **全面审计**：所有关键操作记录日志，保留90天\n5. **成本可视化**：实时展示每个租户的成本消耗",
      "subsections": []
    },
    {
      "id": "常见陷阱",
      "title": "常见陷阱",
      "level": 2,
      "content": "1. **忽略租户隔离**：多租户数据混存导致隐私泄露\n2. **硬编码配置**：变更需要重新部署\n3. **无回滚机制**：上线出问题无法快速回退\n4. **审计不足**：失败操作无日志，无法追溯\n5. **成本失控**：无预算限制导致成本爆炸",
      "subsections": []
    },
    {
      "id": "小结",
      "title": "小结",
      "level": 2,
      "content": "企业级 Agent 的核心要求是：**可靠性是基础，安全性是底线，成本可控是前提**。本章介绍的模式——网关、注册发现、多租户、版本管理、审计合规、高可用、成本管理、安全——构成了企业级 Agent 的基础设施骨架。",
      "subsections": []
    },
    {
      "id": "延伸阅读",
      "title": "延伸阅读",
      "level": 2,
      "content": "1. **书籍**: \"Designing Data-Intensive Applications\" (Martin Kleppmann)\n2. **书籍**: \"Microservices Patterns\" (Chris Richardson)\n3. **论文**: \"The Twelve-Factor App\"\n4. **NIST AI RMF**: AI风险管理框架\n5. **SOC 2**: 安全合规标准",
      "subsections": []
    }
  ],
  "code_blocks": [
    {
      "id": "code-1",
      "language": "python",
      "description": "",
      "code": "from dataclasses import dataclass\n\n@dataclass\nclass GatewayConfig:\n    max_requests_per_minute: int = 1000\n    max_concurrent_requests: int = 100\n    request_timeout: float = 60.0\n    auth_required: bool = True\n\nclass AgentGateway:\n    \"\"\"Agent API网关\"\"\"\n    \n    def __init__(self, config: GatewayConfig, agent):\n        self.config = config\n        self.agent = agent\n        self.rate_limiter = TokenBucketRateLimiter(\n            config.max_requests_per_minute\n        )\n        self.semaphore = asyncio.Semaphore(config.max_concurrent_requests)\n        self._middleware: list[Callable] = []\n    \n    def use(self, middleware: Callable):\n        self._middleware.append(middleware)\n        return self\n    \n    async def handle_request(self, request: dict) -> dict:\n        context = {\"request\": request, \"response\": None}\n        \n        for mw in self._middleware:\n            result = await mw(context)\n            if result is not None:\n                return result\n        \n        if not self.rate_limiter.acquire():\n            return {\"error\": \"rate_limit_exceeded\"}\n        \n        async with self.semaphore:\n            try:\n                result = await asyncio.wait_for(\n                    self.agent.run(request[\"input\"]),\n                    timeout=self.config.request_timeout\n                )\n                return {\"success\": True, \"result\": result}\n            except asyncio.TimeoutError:\n                return {\"error\": \"timeout\"}\n            except Exception as e:\n                return {\"error\": \"internal\", \"message\": str(e)}\n\n# 中间件\nasync def auth_middleware(ctx: dict) -> dict | None:\n    token = ctx[\"request\"].get(\"auth_token\")\n    if not token or not validate_token(token):\n        return {\"error\": \"unauthorized\"}\n    ctx[\"user\"] = decode_token(token)\n    return None\n\nasync def audit_middleware(ctx: dict) -> dict | None:\n    await audit_log.record({\n        \"user\": ctx.get(\"user\", {}).get(\"id\"),\n        \"action\": \"agent_request\",\n        \"timestamp\": datetime.now().isoformat(),\n    })\n    return None\n\nasync def pii_filter_middleware(ctx: dict) -> dict | None:\n    ctx[\"request\"][\"input\"] = sanitize_pii(ctx[\"request\"][\"input\"])\n    return None",
      "section_ref": "35.2.1",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-2",
      "language": "python",
      "description": "",
      "code": "class AgentRouter:\n    \"\"\"Agent路由器：根据任务类型路由到合适的Agent\"\"\"\n    \n    def __init__(self):\n        self._routes: dict[str, Agent] = {}\n    \n    def register(self, path: str, agent: Agent):\n        self._routes[path] = agent\n    \n    def route(self, path: str) -> Agent:\n        if path not in self._routes:\n            raise ValueError(f\"未找到路由: {path}\")\n        return self._routes[path]\n    \n    def route_by_capability(self, task: str) -> Agent:\n        task_type = classify_task(task)\n        routing_map = {\n            \"code\": \"/agents/code-agent\",\n            \"data\": \"/agents/data-agent\",\n            \"general\": \"/agents/general-agent\",\n        }\n        path = routing_map.get(task_type, \"/agents/general-agent\")\n        return self.route(path)",
      "section_ref": "35.2.2",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-3",
      "language": "python",
      "description": "",
      "code": "@dataclass\nclass AgentRegistration:\n    agent_id: str\n    name: str\n    version: str\n    endpoint: str\n    capabilities: list[str]\n    max_concurrent: int\n    health_check_url: str\n    registered_at: str = field(default_factory=lambda: datetime.now().isoformat())\n\nclass AgentRegistry:\n    \"\"\"Agent注册中心\"\"\"\n    \n    def __init__(self):\n        self._agents: dict[str, AgentRegistration] = {}\n    \n    async def register(self, reg: AgentRegistration):\n        self._agents[reg.agent_id] = reg\n    \n    async def discover(self, capability: str) -> list[AgentRegistration]:\n        return [\n            a for a in self._agents.values()\n            if capability in a.capabilities\n        ]\n    \n    async def health_check_all(self) -> dict[str, bool]:\n        results = {}\n        for aid, agent in self._agents.items():\n            try:\n                async with httpx.AsyncClient() as c:\n                    resp = await c.get(agent.health_check_url, timeout=5.0)\n                    results[aid] = resp.status_code == 200\n            except Exception:\n                results[aid] = False\n        return results",
      "section_ref": "35.3.1",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-4",
      "language": "python",
      "description": "",
      "code": "@dataclass\nclass Tenant:\n    tenant_id: str\n    name: str\n    plan: str  # free, pro, enterprise\n    limits: dict = field(default_factory=dict)\n    \n    def __post_init__(self):\n        if not self.limits:\n            self.limits = {\n                \"free\": {\"max_requests_per_day\": 100, \"max_tokens_per_request\": 4000, \"max_concurrent\": 2},\n                \"pro\": {\"max_requests_per_day\": 10000, \"max_tokens_per_request\": 32000, \"max_concurrent\": 10},\n                \"enterprise\": {\"max_requests_per_day\": -1, \"max_tokens_per_request\": 128000, \"max_concurrent\": 100},\n            }.get(self.plan, {})\n\nclass TenantManager:\n    \"\"\"租户管理器\"\"\"\n    \n    def __init__(self):\n        self._tenants: dict[str, Tenant] = {}\n    \n    async def check_limit(self, tenant_id: str, metric: str, value: int) -> bool:\n        tenant = self._tenants.get(tenant_id)\n        if not tenant:\n            return False\n        limit = tenant.limits.get(metric, -1)\n        if limit == -1:\n            return True\n        used = self._get_usage(tenant_id, metric)\n        return used + value <= limit",
      "section_ref": "35.4.1",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-5",
      "language": "python",
      "description": "",
      "code": "class TenantDataIsolator:\n    \"\"\"租户数据隔离：所有key添加租户前缀\"\"\"\n    \n    def isolate_key(self, tenant_id: str, key: str) -> str:\n        if not re.match(r'^[a-zA-Z0-9_-]+$', tenant_id):\n            raise ValueError(f\"无效的租户ID: {tenant_id}\")\n        return f\"tenant:{tenant_id}:{key}\"",
      "section_ref": "35.4.2",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-6",
      "language": "python",
      "description": "",
      "code": "class AgentVersionManager:\n    \"\"\"Agent版本管理\"\"\"\n    \n    def __init__(self):\n        self._active: dict[str, str] = {}\n        self._configs: dict[str, dict] = {}\n    \n    async def deploy(self, agent_id: str, version: str, \n                     config: dict, strategy: str = \"rolling\"):\n        self._configs[f\"{agent_id}:{version}\"] = config\n        \n        if strategy == \"blue_green\":\n            green = create_agent(config)\n            if await self._health_check(green):\n                old = self._active.get(agent_id)\n                self._active[agent_id] = version\n                self._configs[f\"{agent_id}:rollback\"] = old\n        else:\n            self._active[agent_id] = version\n    \n    async def rollback(self, agent_id: str) -> str:\n        old = self._configs.get(f\"{agent_id}:rollback\")\n        if old:\n            self._active[agent_id] = old\n            return old\n        raise ValueError(\"没有可回滚的版本\")",
      "section_ref": "35.5",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-7",
      "language": "python",
      "description": "",
      "code": "class AuditLogger:\n    \"\"\"操作审计日志\"\"\"\n    \n    async def log(self, event: dict):\n        entry = {\n            \"event_id\": str(uuid.uuid4()),\n            \"timestamp\": datetime.now().isoformat(),\n            \"actor_id\": event[\"actor_id\"],\n            \"action\": event[\"action\"],\n            \"resource_type\": event.get(\"resource_type\", \"agent\"),\n            \"input_hash\": hashlib.sha256(\n                json.dumps(event.get(\"input\", \"\"), sort_keys=True).encode()\n            ).hexdigest()[:16],\n            \"metadata\": event.get(\"metadata\", {}),\n        }\n        await self.storage.append(\"audit_log\", entry)\n\n# 必须审计的事件\nAUDIT_EVENTS = [\"agent.run\", \"tool.call\", \"config.change\", \"data.export\", \"data.delete\"]",
      "section_ref": "35.6.1",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-8",
      "language": "python",
      "description": "",
      "code": "class PIIGuard:\n    \"\"\"PII保护\"\"\"\n    \n    PATTERNS = {\n        \"phone\": r\"\\b1[3-9]\\d{9}\\b\",\n        \"email\": r\"\\b[\\w.-]+@[\\w.-]+\\.\\w+\\b\",\n        \"id_card\": r\"\\b\\d{17}[\\dXx]\\b\",\n    }\n    \n    def process(self, text: str, mode: str = \"mask\") -> tuple[str, list]:\n        \"\"\"mode: mask/remove/detect\"\"\"\n        detections = []\n        processed = text\n        for pii_type, pattern in self.PATTERNS.items():\n            for match in re.finditer(pattern, text):\n                detections.append({\"type\": pii_type, \"value\": match.group()})\n                if mode == \"mask\":\n                    processed = processed.replace(match.group(), match.group()[:2] + \"****\")\n                elif mode == \"remove\":\n                    processed = processed.replace(match.group(), f\"[{pii_type}_REDACTED]\")\n        return processed, detections",
      "section_ref": "35.6.2",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-9",
      "language": "python",
      "description": "",
      "code": "class MultiModelFallback:\n    \"\"\"多模型容错\"\"\"\n    \n    def __init__(self, models: list[dict]):\n        self.models = sorted(models, key=lambda m: m.get(\"priority\", 99))\n    \n    async def generate(self, messages: list[dict], **kwargs) -> str:\n        for model_cfg in self.models:\n            try:\n                client = self._get_client(model_cfg)\n                resp = await client.chat.completions.create(\n                    model=model_cfg[\"model\"], messages=messages, **kwargs\n                )\n                return resp.choices[0].message.content\n            except Exception as e:\n                print(f\"模型 {model_cfg['model']} 失败: {e}\")\n                continue\n        raise RuntimeError(\"所有模型均失败\")\n\n# 使用\nfallback = MultiModelFallback([\n    {\"model\": \"claude-3.5-sonnet\", \"priority\": 1, \"provider\": \"anthropic\"},\n    {\"model\": \"gpt-4o\", \"priority\": 2, \"provider\": \"openai\"},\n    {\"model\": \"gpt-4o-mini\", \"priority\": 3, \"provider\": \"openai\"},\n])",
      "section_ref": "35.7.1",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-10",
      "language": "python",
      "description": "",
      "code": "class DegradationManager:\n    \"\"\"优雅降级\"\"\"\n    \n    def __init__(self, agent):\n        self.agent = agent\n        self.level = 0  # 0=正常, 1=部分降级, 2=完全降级\n    \n    async def run(self, task: str) -> str:\n        if self.level == 0:\n            try:\n                return await self.agent.run(task)\n            except Exception:\n                self.level = 1\n        \n        if self.level == 1:\n            try:\n                return await self.agent.run_lite(task)\n            except Exception:\n                self.level = 2\n        \n        return \"服务暂时不可用，请稍后重试。\"",
      "section_ref": "35.7.2",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-11",
      "language": "python",
      "description": "",
      "code": "class CostManager:\n    \"\"\"成本管理\"\"\"\n    \n    def __init__(self):\n        self._budgets: dict[str, float] = {}\n        self._usage: dict[str, float] = {}\n    \n    def set_budget(self, tenant_id: str, daily_budget: float):\n        self._budgets[tenant_id] = daily_budget\n    \n    async def check_budget(self, tenant_id: str, est_cost: float) -> bool:\n        budget = self._budgets.get(tenant_id, float('inf'))\n        used = self._get_daily_usage(tenant_id)\n        return used + est_cost <= budget\n    \n    async def record_cost(self, tenant_id: str, model: str, tokens: int):\n        cost = self._calc_cost(model, tokens)\n        key = f\"{tenant_id}:{date.today().isoformat()}\"\n        self._usage[key] = self._usage.get(key, 0.0) + cost\n    \n    def get_report(self, tenant_id: str) -> dict:\n        budget = self._budgets.get(tenant_id, 0)\n        used = self._get_daily_usage(tenant_id)\n        return {\"budget\": budget, \"used\": round(used, 4), \n                \"remaining\": round(budget - used, 4),\n                \"percent\": (used / budget * 100) if budget else 0}",
      "section_ref": "35.8",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-12",
      "language": "python",
      "description": "",
      "code": "from enum import Enum\n\nclass Permission(Enum):\n    AGENT_RUN = \"agent:run\"\n    AGENT_CONFIG = \"agent:config\"\n    DATA_EXPORT = \"data:export\"\n    ADMIN = \"admin\"\n\nROLE_PERMISSIONS = {\n    \"viewer\": [Permission.AGENT_RUN],\n    \"operator\": [Permission.AGENT_RUN, Permission.AGENT_CONFIG],\n    \"admin\": [p for p in Permission],\n}\n\nclass RBACManager:\n    \"\"\"RBAC权限管理\"\"\"\n    \n    def __init__(self):\n        self._user_roles: dict[str, list[str]] = {}\n    \n    def assign_role(self, user_id: str, role: str):\n        self._user_roles.setdefault(user_id, []).append(role)\n    \n    def check(self, user_id: str, perm: Permission) -> bool:\n        for role in self._user_roles.get(user_id, []):\n            if perm in ROLE_PERMISSIONS.get(role, []):\n                return True\n        return False",
      "section_ref": "35.9.1",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-13",
      "language": "python",
      "description": "",
      "code": "class ZeroTrustGuard:\n    \"\"\"零信任安全守卫\"\"\"\n    \n    async def verify_every_request(self, request: dict) -> bool:\n        \"\"\"每个请求都验证：不信任任何上下文\"\"\"\n        checks = [\n            self._verify_identity(request),\n            self._verify_permissions(request),\n            self._verify_payload(request),\n            self._verify_rate(request),\n        ]\n        return all(checks)\n    \n    def _verify_identity(self, request) -> bool:\n        token = request.get(\"auth_token\")\n        return token is not None and validate_token(token)\n    \n    def _verify_permissions(self, request) -> bool:\n        user_id = request.get(\"user_id\")\n        action = request.get(\"action\")\n        return self.rbac.check(user_id, Permission(action))\n    \n    def _verify_payload(self, request) -> bool:\n        # 检查payload大小、内容\n        return len(json.dumps(request)) < 10 * 1024 * 1024",
      "section_ref": "35.9.2",
      "runnable": true,
      "dependencies": []
    }
  ],
  "tables": [
    {
      "headers": [
        "维度",
        "原型阶段",
        "企业级"
      ],
      "data": [
        [
          "可用性",
          "90%+",
          "99.9%+"
        ],
        [
          "响应延迟",
          "<30秒",
          "<5秒 P95"
        ],
        [
          "安全",
          "API Key",
          "RBAC + 审计 + 加密"
        ],
        [
          "多租户",
          "单租户",
          "1000+租户隔离"
        ],
        [
          "成本",
          "不关心",
          "精确计量 + 预算控制"
        ],
        [
          "部署",
          "手动",
          "CI/CD + 蓝/绿 + 回滚"
        ],
        [
          "监控",
          "打印日志",
          "Dashboard + 告警 + SLO"
        ]
      ]
    }
  ],
  "key_takeaways": [],
  "common_pitfalls": [],
  "related_chapters": [
    "ch31",
    "ch32",
    "ch33",
    "ch34",
    "ch36"
  ]
}