第19章 Agentic Workflow 设计模式 —— 系统设计的万能框架

📖 AI Agent 全栈学习课程 · 可运行讲义

1. 掌握 7 种核心 Agentic 设计模式及其适用场景2. 理解每种模式的执行流程、代价和权衡3. 能用 LangGraph 实现关键模式4. 建立系统设计题的模式选择框架5. 学会避免 Top 3 常见错误🎤 「你用过哪些 Agent 设计模式?」—— 必须能说出 4+ 种并对比🎤 「Reflection 模式怎么实现?和纯 LLM 有什么区别?」🎤 「Routing 和 Orchestrator-Worker 的区别?」🎤 「什么时候不该用 Agent?」—— Anthropic 核心理念

第19章:Agentic Workflow 设计模式 —— 系统设计的万能框架

========================================================

 

 

 

综合 Andrew Ng (4模式) + Anthropic (5模式) + 业界 (7模式) 体系

参考: https://www.anthropic.com/engineering/building-effective-agents

 

 

19.1 Workflows vs Agents —— 先搞清楚概念

 

Anthropic 的核心区分(面试必考!):

 

Workflows(工作流):

LLM 按预定义路径执行,由代码控制流程。
→ 步骤可预测时使用

 

Agents(智能体):

LLM 动态决定自己的流程和工具使用。
→ 步骤不可预测时使用

 

关键原则(面试金句):

"When building applications with LLMs, we recommend finding the

simplest solution possible, and only increasing complexity when

needed. This might mean not building agentic systems at all."

 

19.2 设计模式全景图

 

1. ReAct推理-行动循环,最通用(Ch3/Ch8 已深入讲过)
2. Reflection自我批评 → 迭代改进(本章19.3)
3. Routing按任务特征路由到不同处理器(本章19.4)
4. Planning先制定计划再执行(本章19.5)
5. Orchestrator协调者分发任务给专业 Worker(本章19.6)
6. Evaluator评估-优化双循环(本章19.7)
7. Human-in-关键节点人工确认(本章19.8)
the-Loop

 

快速选择矩阵(面试时脱口而出!):

任务特征推荐模式
输出质量 > 速度Reflection
多种类型但可分类的任务Routing
复杂的多步骤任务Planning + ReAct
可分解为独立子任务Orchestrator-Worker
需要通过评测指标迭代优化Evaluator-Optimizer
涉及资金/数据安全的操作Human-in-the-Loop
路径不可预测的复杂推理纯 ReAct Agent
简单、步骤固定的任务不需要 Agent!直接用 LLM 调用
📝 对应的代码实现
💻 代码 (5 行)
import json
import time
import re
from typing import Optional
from dataclasses import dataclass, field

19.3 Reflection 模式 —— 自我批评,迭代改进

 

核心理念:

不满足于 LLM 的第一次输出,让 LLM 自己批评自己,然后改进。

 

流程:

初版生成 → 自我审查 → 发现不足 → 修订 → 再审查 → ... → 达标输出

 

为什么「双 Agent」比「单 Agent 自省」更好?

  • LLM 对自己的输出有「确认偏误」
  • 换成另一个 Agent(不同的 system prompt)来审查更客观
  • Generator + Critic 两个角色分离
  •  

    类比:

    就像作家写完初稿后,自己很难发现错字

    需要一个编辑来审阅

    📝 对应的代码实现
    💻 代码 (110 行)
    generatecritiquerunReflectionAgent
    import json
    import time
    import re
    from typing import Optional
    from dataclasses import dataclass, field
    
    class ReflectionAgent:
        """Reflection 模式实现 —— Generator + Critic 双角色。
    
        流程:
          Generator 生成 → Critic 审查 → 如果不够好 → Generator 修订 → ...
        """
    
        def __init__(self, quality_threshold: int = 8, max_rounds: int = 3):
            """
            Args:
                quality_threshold: 质量阈值(1-10),达到即停止。
                max_rounds: 最大迭代轮数。
            """
            self.threshold = quality_threshold
            self.max_rounds = max_rounds
    
        def generate(self, task: str, previous: str = "",
                     feedback: str = "") -> str:
            """Generator:生成/修订输出(模拟)。"""
            if not previous:
                return self._generate_initial(task)
            return self._revise(task, previous, feedback)
    
        def critique(self, output: str, task: str) -> dict:
            """Critic:以角色分离的方式审查输出。
    
            真实实现中用不同的 system prompt 或不同的模型。
            """
            issues = []
            score = 10
    
            # 规则检查(模拟 LLM-as-Critic)
            if len(output) < 50:
                issues.append("输出太短,缺乏细节")
                score -= 3
    
            if task.lower() in output.lower():
                pass  # 回应了任务
            else:
                issues.append("没有直接回应任务要求")
                score -= 2
    
            # 检查是否包含推测性语言
            uncertain_patterns = ["可能", "也许", "大概", "似乎"]
            uncertain_count = sum(
                1 for p in uncertain_patterns if p in output
            )
            if uncertain_count >= 3:
                issues.append(f"包含 {uncertain_count} 处不确定表述")
                score -= 1
    
            # 检查结构
            if "\n" not in output or len(output.split("\n")) < 3:
                issues.append("缺少段落结构,可读性差")
                score -= 1
    
            return {
                "score": max(1, score),
                "issues": issues,
                "passed": score >= self.threshold,
            }
    
        def run(self, task: str) -> dict:
            """执行完整的 Reflection 循环。
    
            Returns:
                包含最终输出和迭代记录的字典。
            """
            history = []
            output = self.generate(task)
    
            for round_num in range(1, self.max_rounds + 1):
                review = self.critique(output, task)
                history.append({
                    "round": round_num,
                    "score": review["score"],
                    "issues": review["issues"],
                })
    
                if review["passed"]:
                    break
    
                if round_num < self.max_rounds:
                    feedback = ";".join(review["issues"])
                    output = self.generate(
                        task, previous=output, feedback=feedback
                    )
    
            return {
                "task": task,
                "final_output": output,
                "history": history,
                "rounds": len(history),
                "passed": history[-1]["score"] >= self.threshold,
            }
    
        def _generate_initial(self, task: str) -> str:
            return f"关于「{task}」,AI Agent 是一种能够自主感知环境、" \
                   f"做出决策并执行行动的智能系统。"
    
        def _revise(self, task: str, previous: str, feedback: str) -> str:
            return f"修订版(收到反馈: {feedback}):\n{previous}\n" \
                   f"补充说明:AI Agent 主要由 LLM、规划器、记忆系统和" \
                   f"工具调用四部分组成,通过 ReAct 循环协调工作。"

    19.4 Routing 模式 —— 分类 → 分发

     

    核心理念:

    不同的任务需要不同的处理方式,先用 LLM 分类再路由。

     

    流程:

    用户输入 → 分类 Agent → 路由到专门的 Handler → 返回结果

     

    适用场景:

  • 客服系统(投诉/咨询/售后 分到不同的 Agent)
  • 代码工具(需求/调试/代码审查 分到不同的流程)
  • 智能助手(简单问答/复杂推理/工具调用 分到不同的模式)
  •  

    关键决策:

  • 路由的依据是什么?(关键词/语义/复杂度评分?)
  • 每个路由目标用不同模型、不同 prompt、不同工具集
  • 可以实现成本优化(简单问题用小模型,复杂问题用大模型)
  • 📝 对应的代码实现
    💻 代码 (58 行)
    classifyrouteRoutingAgent
    import json
    import time
    import re
    from typing import Optional
    from dataclasses import dataclass, field
    
    class RoutingAgent:
        """Routing 模式 —— 根据任务特征选择最合适的处理器。"""
    
        ROUTE_TABLE = {
            "简单问答": {"model": "小模型", "max_tokens": 256},
            "代码相关": {"model": "大模型", "max_tokens": 2048, "tools": ["code_exec"]},
            "数据分析": {"model": "大模型", "max_tokens": 4096, "tools": ["sql", "chart"]},
            "复杂推理": {"model": "大模型", "max_tokens": 8192, "tools": ["search", "calculator"]},
            "安全敏感": {"model": "审核模型", "human_review": True},
        }
    
        class="d">@staticmethod
        def classify(task: str) -> str:
            """分类器:分析任务特征,决定路由目标。
    
            真实实现中用 LLM 做分类:
              prompt = f"将以下任务分类为 [简单问答/代码相关/数据分析/复杂推理/安全敏感]: {task}"
            """
            task_lower = task.lower()
    
            if any(w in task_lower for w in ["代码", "debug", "写一个", "实现"]):
                return "代码相关"
            if any(w in task_lower for w in ["分析", "统计", "趋势", "报表", "数据"]):
                return "数据分析"
            if any(w in task_lower for w in ["删除", "密码", "转账", "admin"]):
                return "安全敏感"
            if len(task) > 100 or any(
                w in task_lower for w in ["为什么", "如何", "解释", "原因"]
            ):
                return "复杂推理"
            return "简单问答"
    
        class="d">@staticmethod
        def route(task: str) -> dict:
            """路由:分类 → 选择配置 → 返回处理方案。
    
            Returns:
                包含路由决策的字典。
            """
            category = RoutingAgent.classify(task)
            config = RoutingAgent.ROUTE_TABLE[category].copy()
            config["category"] = category
            config["task"] = task
            config["estimated_cost"] = _estimate_cost(config)
            return config
    
    
    def _estimate_cost(config: dict) -> float:
        """估算处理成本(模拟)。"""
        base = {"简单问答": 0.001, "代码相关": 0.01,
                "数据分析": 0.05, "复杂推理": 0.10, "安全敏感": 0.02}
        return base.get(config["category"], 0.01)

    19.5 Planning 模式 —— 先规划,再执行

     

    和 Ch3 中 Plan-Execute 的关系:

    这是更高层的抽象,规划出来的每个子步骤可以由 ReAct Agent 执行。

     

    核心理念:

    复杂任务 → 分解为子步骤 → 每个子步骤独立执行 → 汇总结果

     

    关键洞察:

  • 规划用 LLM(灵活),执行按计划(可靠)
  • 规划不是「一次性」的 —— 执行中可以根据反馈调整计划
  • 规划质量取决于分解粒度(太粗执行不了,太细浪费 token)
  • 📝 对应的代码实现
    💻 代码 (70 行)
    decomposeexecute_planPlanningAgent
    import json
    import time
    import re
    from typing import Optional
    from dataclasses import dataclass, field
    
    class PlanningAgent:
        """Planning 模式 —— 任务分解 + 分步执行。"""
    
        class="d">@staticmethod
        def decompose(task: str) -> list[dict]:
            """任务分解:将复杂任务拆成子步骤。
    
            真实实现用 LLM:
              f"将以下任务分解为 3-6 个可独立执行的子步骤: {task}"
            """
            # 模拟分解逻辑
            if "分析" in task and "写" in task:
                return [
                    {"id": 1, "action": "research", "desc": "搜索相关资料"},
                    {"id": 2, "action": "analyze", "desc": "分析关键信息",
                     "depends_on": [1]},
                    {"id": 3, "action": "outline", "desc": "制定文章大纲",
                     "depends_on": [2]},
                    {"id": 4, "action": "write", "desc": "撰写初稿",
                     "depends_on": [3]},
                    {"id": 5, "action": "review", "desc": "自我审查并修订",
                     "depends_on": [4]},
                ]
            if "搭建" in task or "构建" in task:
                return [
                    {"id": 1, "action": "analyze", "desc": "分析需求和约束"},
                    {"id": 2, "action": "design", "desc": "设计架构",
                     "depends_on": [1]},
                    {"id": 3, "action": "implement", "desc": "编码实现",
                     "depends_on": [2]},
                    {"id": 4, "action": "test", "desc": "编写测试",
                     "depends_on": [3]},
                    {"id": 5, "action": "document", "desc": "编写文档",
                     "depends_on": [4]},
                ]
            return [
                {"id": 1, "action": "execute", "desc": task},
            ]
    
        class="d">@staticmethod
        def execute_plan(plan: list[dict]) -> list[dict]:
            """按计划执行(模拟)。
    
            真实实现中每个步骤调用 ReAct Agent 或直接调 LLM。
            """
            results = []
            for step in plan:
                deps = step.get("depends_on", [])
                # 检查依赖是否完成
                dep_results = [r for r in results if r["id"] in deps]
                if deps and len(dep_results) != len(deps):
                    results.append({
                        **step, "status": "blocked",
                        "reason": f"依赖步骤 {deps} 未完成",
                    })
                    continue
    
                # 模拟执行
                results.append({
                    **step,
                    "status": "completed",
                    "output": f"已完成: {step['desc']}",
                })
            return results

    19.6 Orchestrator-Worker 模式

     

    核心理念:

    一个聪明的 Orchestrator(有状态)管理多个无状态 Worker。

    Worker 之间不直接通信,通过 Orchestrator 协调。

     

    这是 Claude Code 1.0.60+ SubAgent 系统的本质(参见 Ch8)。

     

    对比 Planning 模式:

    Planning:预先分解,固定执行

    Orchestrator-Worker:动态分配,Worker 独立运行

     

    关键特性:

  • Orchestrator 有状态(记住任务上下文)
  • Worker 无状态(每次只处理一个子任务)
  • Worker 之间隔离(可以并行,可以不同权限)
  • 易于水平扩展(加 Worker 即可)
  • 📝 对应的代码实现
    💻 代码 (91 行)
    register_workerorchestrateOrchestratorWorker
    import json
    import time
    import re
    from typing import Optional
    from dataclasses import dataclass, field
    
    class OrchestratorWorker:
        """Orchestrator-Worker 模式实现。"""
    
        def __init__(self):
            self.workers = {}  # {name: {permissions, handler}}
            self.task_state = {}  # 全局任务状态
    
        def register_worker(self, name: str, permissions: list[str]):
            """注册一个 Worker。
    
            Args:
                name: Worker 名称。
                permissions: 拥有的权限列表。
            """
            self.workers[name] = {
                "permissions": permissions,
                "status": "idle",
                "completed_tasks": 0,
            }
    
        def orchestrate(self, task: str) -> dict:
            """Orchestrator:分析任务 → 分解 → 分配给 Worker。
    
            Returns:
                完整的执行记录。
            """
            # 第1步:Orchestrator 分析任务
            subtasks = self._decompose(task)
    
            # 第2步:分配给 Worker
            results = []
            for sub in subtasks:
                worker = self._select_worker(sub)
                if worker is None:
                    results.append({**sub, "status": "unassigned"})
                    continue
    
                # Worker 执行(模拟)
                self.workers[worker]["status"] = "working"
                result = self._execute(sub, worker)
                self.workers[worker]["status"] = "idle"
                self.workers[worker]["completed_tasks"] += 1
                results.append(result)
    
            return {
                "task": task,
                "subtasks": len(subtasks),
                "results": results,
                "workers_used": len(set(r.get("worker") for r in results)),
            }
    
        def _decompose(self, task: str) -> list[dict]:
            """Orchestrator 分解任务。"""
            if "代码" in task and "文档" in task:
                return [
                    {"id": 1, "type": "code", "desc": "编写代码"},
                    {"id": 2, "type": "docs", "desc": "编写文档"},
                    {"id": 3, "type": "test", "desc": "运行测试"},
                ]
            if "全栈" in task:
                return [
                    {"id": 1, "type": "frontend", "desc": "前端开发"},
                    {"id": 2, "type": "backend", "desc": "后端开发"},
                    {"id": 3, "type": "database", "desc": "数据库设计"},
                ]
            return [{"id": 1, "type": "general", "desc": task}]
    
        def _select_worker(self, subtask: dict) -> Optional[str]:
            """根据子任务类型选择合适的 Worker。"""
            type_map = {
                "code": "coder", "docs": "writer", "test": "tester",
                "frontend": "frontend_dev", "backend": "backend_dev",
                "database": "db_admin", "general": "general_assistant",
            }
            target = type_map.get(subtask["type"], "general_assistant")
            return target if target in self.workers else None
    
        def _execute(self, subtask: dict, worker: str) -> dict:
            return {
                **subtask,
                "worker": worker,
                "permissions": self.workers[worker]["permissions"],
                "status": "completed",
                "output": f"[{worker}] 已完成: {subtask['desc']}",
            }

    19.7 Evaluator-Optimizer 模式

     

    核心理念:

    和 Reflection 类似但不同:

  • Reflection: 同一 LLM 生成 + 批评
  • Evaluator-Optimizer: 独立评测 + 独立优化,评测标准更客观
  •  

    适用场景:

  • 翻译质量优化(BLEU 评分驱动)
  • 代码性能优化(Benchmark 评分驱动)
  • Prompt 自动优化(准确率评分驱动)
  •  

    这个模式是 DSPy(Ch22 待讲)的核心思想。

    19.8 Human-in-the-Loop 模式

     

    核心理念:

    不是所有操作都应该自动执行。在关键节点引入人工确认。

     

    触发时机:

    ✗ 资金操作(转账、下单)

    ✗ 内容发布(发送邮件、发布文章)

    ✗ 数据删除

    ✗ 系统配置变更

    ✓ 查询类操作 → 自动执行

     

    这是 Ch18 Agent 安全的分级确认机制的扩展。

    19.9 Top 3 常见错误(Tina Huang + Anthropic 总结)

     

    错误 1: 过度工程化 (Over-Engineering)

    症状:用 Multi-Agent 做单步就能完成的事

    解法:先问「这真的需要 Agent 吗?」

     

    错误 2: 糟糕的 Prompt (Bad Prompting)

    症状:复杂架构但 prompt 写得很随意

    解法:先投入时间优化 prompt,再考虑架构

     

    错误 3: 糟糕的系统设计 (Poor System Design)

    症状:没有架构图、数据流不清晰、难以调试

    解法:选好架构模式 → 画架构图 → 定义数据流 → 设置错误处理

     

     

    19.10 系统设计题的答题框架

     

    面试官:「设计一个智能客服系统」

     

    标准回答结构:

  • 场景分析(任务特征分类)
  • 模式选择(主模式 + 辅助模式)
  • 架构设计(画图!)
  • 关键决策说明(为什么选这个模式)
  • 风险与权衡
  •  

    示例回答:

    「智能客服有3类请求:FAQ(70%)、工单操作(20%)、投诉(10%)。

    用 Routing 模式分流:FAQ 走 RAG + 小模型;工单走 Tool Use;

    投诉需要升级(Human-in-the-Loop)。

    在工单处理中用 Reflection 确保回复质量。

    敏感操作(退款)需要双重确认。」

    📝 对应的代码实现
    💻 代码 (54 行)
    demo_all_patterns
    import json
    import time
    import re
    from typing import Optional
    from dataclasses import dataclass, field
    
    def demo_all_patterns():
        """演示所有设计模式。"""
        print("=" * 60)
        print("  Agentic Workflow 设计模式综合演示")
        print("=" * 60)
    
        # Reflection
        print("\n  ── Reflection 模式 ──")
        agent = ReflectionAgent(quality_threshold=8, max_rounds=3)
        result = agent.run("解释 AI Agent 的核心组成")
        print(f"  任务: {result['task']}")
        print(f"  轮数: {result['rounds']}")
        for h in result["history"]:
            icon = "✅" if h["score"] >= 8 else "🔄"
            print(f"    {icon} 第{h['round']}轮: {h['score']}/10 | {h['issues']}")
    
        # Routing
        print("\n  ── Routing 模式 ──")
        test_tasks = [
            "帮我写一个 Python 快速排序函数",
            "分析最近一个月的销售数据趋势",
            "什么是机器学习?",
            "删除用户 admin 的所有数据",
        ]
        for task in test_tasks:
            decision = RoutingAgent.route(task)
            print(f"  「{task[:30]}...」→ {decision['category']} "
                  f"| 模型: {decision.get('model','')} "
                  f"| 成本: ${decision.get('estimated_cost', 0):.3f}")
    
        # Planning
        print("\n  ── Planning 模式 ──")
        plan = PlanningAgent.decompose("分析AI Agent市场并写一份报告")
        print(f"  分解为 {len(plan)} 个步骤:")
        for step in plan:
            deps = f" (依赖步骤 {step['depends_on']})" if step.get("depends_on") else ""
            print(f"    Step {step['id']}: {step['desc']}{deps}")
    
        # Orchestrator-Worker
        print("\n  ── Orchestrator-Worker 模式 ──")
        ow = OrchestratorWorker()
        ow.register_worker("coder", ["read", "write", "execute"])
        ow.register_worker("writer", ["read", "write"])
        ow.register_worker("tester", ["execute"])
        result = ow.orchestrate("开发一个功能并写文档,确保代码和文档都完整")
        print(f"  子任务: {result['subtasks']} | 使用 Worker: {result['workers_used']}")
        for r in result["results"]:
            print(f"    [{r.get('worker', '?')}] {r['desc']} → {r['status']}")

    19.11 本章总结

     

    核心要点回顾:

     

  • Workflow ≠ Agent
  • Workflow: 代码控制流程
  • Agent: LLM 控制流程
  • 能不用 Agent 就不用(Anthropic 核心原则)
  •  

  • 7 种核心模式
  • ReAct: 最通用,默认选择
  • Reflection: 质量优先场景
  • Routing: 多种任务类型
  • Planning: 复杂多步骤
  • Orchestrator-Worker: 可并行子任务
  • Evaluator-Optimizer: 量化优化
  • Human-in-the-Loop: 安全关键操作
  •  

  • 系统设计答题框架
  • 场景分析 → 模式选择 → 架构设计 → 关键决策 → 风险权衡

     

    面试速记:

    "你用过哪些 Agent 设计模式?"

    → 说出 4+ 种 + 每种的使用场景 + 对比

    → 重点说 Reflection(双角色分离)和 Routing(成本优化)

    → 结尾:Anthropic 原则「简单优先,够用就好」

    📝 对应的代码实现
    💻 代码 (29 行)
    import json
    import time
    import re
    from typing import Optional
    from dataclasses import dataclass, field
    
    if __name__ == "__main__":
        print("╔══════════════════════════════════════════════════════╗")
        print("║  第19章:Agentic Workflow 设计模式                     ║")
        print("║  Reflection · Routing · Planning · Orchestrator      ║")
        print("╚══════════════════════════════════════════════════════╝")
    
        demo_all_patterns()
    
        print("\n▶ 模式选择速查表")
        print("-" * 50)
        choices = [
            ("输出质量 > 速度", "Reflection"),
            ("多种可分类任务", "Routing"),
            ("复杂多步骤任务", "Planning + ReAct"),
            ("可并行子任务", "Orchestrator-Worker"),
            ("量化优化", "Evaluator-Optimizer"),
            ("安全关键操作", "Human-in-the-Loop"),
            ("简单固定步骤", "直接 LLM(不用 Agent)"),
        ]
        for scene, pattern in choices:
            print(f"  {scene:20s} → {pattern}")
    
        print("\n✅ 第19章完成!")

    📦 完整源代码 (653 行)
    """
    第19章:Agentic Workflow 设计模式 —— 系统设计的万能框架
    ========================================================
    
    📌 本章目标:
      1. 掌握 7 种核心 Agentic 设计模式及其适用场景
      2. 理解每种模式的执行流程、代价和权衡
      3. 能用 LangGraph 实现关键模式
      4. 建立系统设计题的模式选择框架
      5. 学会避免 Top 3 常见错误
    
    📌 面试高频点:
      - 「你用过哪些 Agent 设计模式?」—— 必须能说出 4+ 种并对比
      - 「Reflection 模式怎么实现?和纯 LLM 有什么区别?」
      - 「Routing 和 Orchestrator-Worker 的区别?」
      - 「什么时候不该用 Agent?」—— Anthropic 核心理念
    
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    综合 Andrew Ng (4模式) + Anthropic (5模式) + 业界 (7模式) 体系
    参考: https://www.anthropic.com/engineering/building-effective-agents
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    
    
    19.1 Workflows vs Agents —— 先搞清楚概念
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    
    Anthropic 的核心区分(面试必考!):
    
      Workflows(工作流):
        LLM 按预定义路径执行,由代码控制流程。
        → 步骤可预测时使用
    
      Agents(智能体):
        LLM 动态决定自己的流程和工具使用。
        → 步骤不可预测时使用
    
    关键原则(面试金句):
      "When building applications with LLMs, we recommend finding the
       simplest solution possible, and only increasing complexity when
       needed. This might mean not building agentic systems at all."
    
    19.2 设计模式全景图
    ━━━━━━━━━━━━━━━━━━
    
    ┌──────────────────────────────────────────────────────────────┐
    │                  Agentic Design Patterns                       │
    ├────────────┬─────────────────────────────────────────────────┤
    │ 1. ReAct   │ 推理-行动循环,最通用(Ch3/Ch8 已深入讲过)       │
    │ 2. Reflection│ 自我批评 → 迭代改进(本章19.3)                │
    │ 3. Routing  │ 按任务特征路由到不同处理器(本章19.4)           │
    │ 4. Planning │ 先制定计划再执行(本章19.5)                    │
    │ 5. Orchestrator│ 协调者分发任务给专业 Worker(本章19.6)       │
    │ 6. Evaluator │ 评估-优化双循环(本章19.7)                   │
    │ 7. Human-in- │ 关键节点人工确认(本章19.8)                  │
    │    the-Loop │                                                 │
    └────────────┴─────────────────────────────────────────────────┘
    
    快速选择矩阵(面试时脱口而出!):
    ┌────────────────────────────┬──────────────────────────────┐
    │         任务特征             │         推荐模式              │
    ├────────────────────────────┼──────────────────────────────┤
    │ 输出质量 > 速度             │ Reflection                   │
    │ 多种类型但可分类的任务       │ Routing                      │
    │ 复杂的多步骤任务            │ Planning + ReAct             │
    │ 可分解为独立子任务          │ Orchestrator-Worker          │
    │ 需要通过评测指标迭代优化    │ Evaluator-Optimizer          │
    │ 涉及资金/数据安全的操作     │ Human-in-the-Loop            │
    │ 路径不可预测的复杂推理      │ 纯 ReAct Agent               │
    │ 简单、步骤固定的任务        │ 不需要 Agent!直接用 LLM 调用  │
    └────────────────────────────┴──────────────────────────────┘
    """
    
    import json
    import time
    import re
    from typing import Optional
    from dataclasses import dataclass, field
    
    
    """
    19.3 Reflection 模式 —— 自我批评,迭代改进
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    
    核心理念:
      不满足于 LLM 的第一次输出,让 LLM 自己批评自己,然后改进。
    
    流程:
      初版生成 → 自我审查 → 发现不足 → 修订 → 再审查 → ... → 达标输出
    
    为什么「双 Agent」比「单 Agent 自省」更好?
      - LLM 对自己的输出有「确认偏误」
      - 换成另一个 Agent(不同的 system prompt)来审查更客观
      - Generator + Critic 两个角色分离
    
    类比:
      就像作家写完初稿后,自己很难发现错字
      需要一个编辑来审阅
    """
    
    
    class ReflectionAgent:
        """Reflection 模式实现 —— Generator + Critic 双角色。
    
        流程:
          Generator 生成 → Critic 审查 → 如果不够好 → Generator 修订 → ...
        """
    
        def __init__(self, quality_threshold: int = 8, max_rounds: int = 3):
            """
            Args:
                quality_threshold: 质量阈值(1-10),达到即停止。
                max_rounds: 最大迭代轮数。
            """
            self.threshold = quality_threshold
            self.max_rounds = max_rounds
    
        def generate(self, task: str, previous: str = "",
                     feedback: str = "") -> str:
            """Generator:生成/修订输出(模拟)。"""
            if not previous:
                return self._generate_initial(task)
            return self._revise(task, previous, feedback)
    
        def critique(self, output: str, task: str) -> dict:
            """Critic:以角色分离的方式审查输出。
    
            真实实现中用不同的 system prompt 或不同的模型。
            """
            issues = []
            score = 10
    
            # 规则检查(模拟 LLM-as-Critic)
            if len(output) < 50:
                issues.append("输出太短,缺乏细节")
                score -= 3
    
            if task.lower() in output.lower():
                pass  # 回应了任务
            else:
                issues.append("没有直接回应任务要求")
                score -= 2
    
            # 检查是否包含推测性语言
            uncertain_patterns = ["可能", "也许", "大概", "似乎"]
            uncertain_count = sum(
                1 for p in uncertain_patterns if p in output
            )
            if uncertain_count >= 3:
                issues.append(f"包含 {uncertain_count} 处不确定表述")
                score -= 1
    
            # 检查结构
            if "\n" not in output or len(output.split("\n")) < 3:
                issues.append("缺少段落结构,可读性差")
                score -= 1
    
            return {
                "score": max(1, score),
                "issues": issues,
                "passed": score >= self.threshold,
            }
    
        def run(self, task: str) -> dict:
            """执行完整的 Reflection 循环。
    
            Returns:
                包含最终输出和迭代记录的字典。
            """
            history = []
            output = self.generate(task)
    
            for round_num in range(1, self.max_rounds + 1):
                review = self.critique(output, task)
                history.append({
                    "round": round_num,
                    "score": review["score"],
                    "issues": review["issues"],
                })
    
                if review["passed"]:
                    break
    
                if round_num < self.max_rounds:
                    feedback = ";".join(review["issues"])
                    output = self.generate(
                        task, previous=output, feedback=feedback
                    )
    
            return {
                "task": task,
                "final_output": output,
                "history": history,
                "rounds": len(history),
                "passed": history[-1]["score"] >= self.threshold,
            }
    
        def _generate_initial(self, task: str) -> str:
            return f"关于「{task}」,AI Agent 是一种能够自主感知环境、" \
                   f"做出决策并执行行动的智能系统。"
    
        def _revise(self, task: str, previous: str, feedback: str) -> str:
            return f"修订版(收到反馈: {feedback}):\n{previous}\n" \
                   f"补充说明:AI Agent 主要由 LLM、规划器、记忆系统和" \
                   f"工具调用四部分组成,通过 ReAct 循环协调工作。"
    
    
    """
    19.4 Routing 模式 —— 分类 → 分发
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    
    核心理念:
      不同的任务需要不同的处理方式,先用 LLM 分类再路由。
    
    流程:
      用户输入 → 分类 Agent → 路由到专门的 Handler → 返回结果
    
    适用场景:
      - 客服系统(投诉/咨询/售后 分到不同的 Agent)
      - 代码工具(需求/调试/代码审查 分到不同的流程)
      - 智能助手(简单问答/复杂推理/工具调用 分到不同的模式)
    
    关键决策:
      - 路由的依据是什么?(关键词/语义/复杂度评分?)
      - 每个路由目标用不同模型、不同 prompt、不同工具集
      - 可以实现成本优化(简单问题用小模型,复杂问题用大模型)
    """
    
    
    class RoutingAgent:
        """Routing 模式 —— 根据任务特征选择最合适的处理器。"""
    
        ROUTE_TABLE = {
            "简单问答": {"model": "小模型", "max_tokens": 256},
            "代码相关": {"model": "大模型", "max_tokens": 2048, "tools": ["code_exec"]},
            "数据分析": {"model": "大模型", "max_tokens": 4096, "tools": ["sql", "chart"]},
            "复杂推理": {"model": "大模型", "max_tokens": 8192, "tools": ["search", "calculator"]},
            "安全敏感": {"model": "审核模型", "human_review": True},
        }
    
        class="d">@staticmethod
        def classify(task: str) -> str:
            """分类器:分析任务特征,决定路由目标。
    
            真实实现中用 LLM 做分类:
              prompt = f"将以下任务分类为 [简单问答/代码相关/数据分析/复杂推理/安全敏感]: {task}"
            """
            task_lower = task.lower()
    
            if any(w in task_lower for w in ["代码", "debug", "写一个", "实现"]):
                return "代码相关"
            if any(w in task_lower for w in ["分析", "统计", "趋势", "报表", "数据"]):
                return "数据分析"
            if any(w in task_lower for w in ["删除", "密码", "转账", "admin"]):
                return "安全敏感"
            if len(task) > 100 or any(
                w in task_lower for w in ["为什么", "如何", "解释", "原因"]
            ):
                return "复杂推理"
            return "简单问答"
    
        class="d">@staticmethod
        def route(task: str) -> dict:
            """路由:分类 → 选择配置 → 返回处理方案。
    
            Returns:
                包含路由决策的字典。
            """
            category = RoutingAgent.classify(task)
            config = RoutingAgent.ROUTE_TABLE[category].copy()
            config["category"] = category
            config["task"] = task
            config["estimated_cost"] = _estimate_cost(config)
            return config
    
    
    def _estimate_cost(config: dict) -> float:
        """估算处理成本(模拟)。"""
        base = {"简单问答": 0.001, "代码相关": 0.01,
                "数据分析": 0.05, "复杂推理": 0.10, "安全敏感": 0.02}
        return base.get(config["category"], 0.01)
    
    
    """
    19.5 Planning 模式 —— 先规划,再执行
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    
    和 Ch3 中 Plan-Execute 的关系:
      这是更高层的抽象,规划出来的每个子步骤可以由 ReAct Agent 执行。
    
    核心理念:
      复杂任务 → 分解为子步骤 → 每个子步骤独立执行 → 汇总结果
    
    关键洞察:
      1. 规划用 LLM(灵活),执行按计划(可靠)
      2. 规划不是「一次性」的 —— 执行中可以根据反馈调整计划
      3. 规划质量取决于分解粒度(太粗执行不了,太细浪费 token)
    """
    
    
    class PlanningAgent:
        """Planning 模式 —— 任务分解 + 分步执行。"""
    
        class="d">@staticmethod
        def decompose(task: str) -> list[dict]:
            """任务分解:将复杂任务拆成子步骤。
    
            真实实现用 LLM:
              f"将以下任务分解为 3-6 个可独立执行的子步骤: {task}"
            """
            # 模拟分解逻辑
            if "分析" in task and "写" in task:
                return [
                    {"id": 1, "action": "research", "desc": "搜索相关资料"},
                    {"id": 2, "action": "analyze", "desc": "分析关键信息",
                     "depends_on": [1]},
                    {"id": 3, "action": "outline", "desc": "制定文章大纲",
                     "depends_on": [2]},
                    {"id": 4, "action": "write", "desc": "撰写初稿",
                     "depends_on": [3]},
                    {"id": 5, "action": "review", "desc": "自我审查并修订",
                     "depends_on": [4]},
                ]
            if "搭建" in task or "构建" in task:
                return [
                    {"id": 1, "action": "analyze", "desc": "分析需求和约束"},
                    {"id": 2, "action": "design", "desc": "设计架构",
                     "depends_on": [1]},
                    {"id": 3, "action": "implement", "desc": "编码实现",
                     "depends_on": [2]},
                    {"id": 4, "action": "test", "desc": "编写测试",
                     "depends_on": [3]},
                    {"id": 5, "action": "document", "desc": "编写文档",
                     "depends_on": [4]},
                ]
            return [
                {"id": 1, "action": "execute", "desc": task},
            ]
    
        class="d">@staticmethod
        def execute_plan(plan: list[dict]) -> list[dict]:
            """按计划执行(模拟)。
    
            真实实现中每个步骤调用 ReAct Agent 或直接调 LLM。
            """
            results = []
            for step in plan:
                deps = step.get("depends_on", [])
                # 检查依赖是否完成
                dep_results = [r for r in results if r["id"] in deps]
                if deps and len(dep_results) != len(deps):
                    results.append({
                        **step, "status": "blocked",
                        "reason": f"依赖步骤 {deps} 未完成",
                    })
                    continue
    
                # 模拟执行
                results.append({
                    **step,
                    "status": "completed",
                    "output": f"已完成: {step['desc']}",
                })
            return results
    
    
    """
    19.6 Orchestrator-Worker 模式
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    
    核心理念:
      一个聪明的 Orchestrator(有状态)管理多个无状态 Worker。
      Worker 之间不直接通信,通过 Orchestrator 协调。
    
    这是 Claude Code 1.0.60+ SubAgent 系统的本质(参见 Ch8)。
    
    对比 Planning 模式:
      Planning:预先分解,固定执行
      Orchestrator-Worker:动态分配,Worker 独立运行
    
    关键特性:
      1. Orchestrator 有状态(记住任务上下文)
      2. Worker 无状态(每次只处理一个子任务)
      3. Worker 之间隔离(可以并行,可以不同权限)
      4. 易于水平扩展(加 Worker 即可)
    """
    
    
    class OrchestratorWorker:
        """Orchestrator-Worker 模式实现。"""
    
        def __init__(self):
            self.workers = {}  # {name: {permissions, handler}}
            self.task_state = {}  # 全局任务状态
    
        def register_worker(self, name: str, permissions: list[str]):
            """注册一个 Worker。
    
            Args:
                name: Worker 名称。
                permissions: 拥有的权限列表。
            """
            self.workers[name] = {
                "permissions": permissions,
                "status": "idle",
                "completed_tasks": 0,
            }
    
        def orchestrate(self, task: str) -> dict:
            """Orchestrator:分析任务 → 分解 → 分配给 Worker。
    
            Returns:
                完整的执行记录。
            """
            # 第1步:Orchestrator 分析任务
            subtasks = self._decompose(task)
    
            # 第2步:分配给 Worker
            results = []
            for sub in subtasks:
                worker = self._select_worker(sub)
                if worker is None:
                    results.append({**sub, "status": "unassigned"})
                    continue
    
                # Worker 执行(模拟)
                self.workers[worker]["status"] = "working"
                result = self._execute(sub, worker)
                self.workers[worker]["status"] = "idle"
                self.workers[worker]["completed_tasks"] += 1
                results.append(result)
    
            return {
                "task": task,
                "subtasks": len(subtasks),
                "results": results,
                "workers_used": len(set(r.get("worker") for r in results)),
            }
    
        def _decompose(self, task: str) -> list[dict]:
            """Orchestrator 分解任务。"""
            if "代码" in task and "文档" in task:
                return [
                    {"id": 1, "type": "code", "desc": "编写代码"},
                    {"id": 2, "type": "docs", "desc": "编写文档"},
                    {"id": 3, "type": "test", "desc": "运行测试"},
                ]
            if "全栈" in task:
                return [
                    {"id": 1, "type": "frontend", "desc": "前端开发"},
                    {"id": 2, "type": "backend", "desc": "后端开发"},
                    {"id": 3, "type": "database", "desc": "数据库设计"},
                ]
            return [{"id": 1, "type": "general", "desc": task}]
    
        def _select_worker(self, subtask: dict) -> Optional[str]:
            """根据子任务类型选择合适的 Worker。"""
            type_map = {
                "code": "coder", "docs": "writer", "test": "tester",
                "frontend": "frontend_dev", "backend": "backend_dev",
                "database": "db_admin", "general": "general_assistant",
            }
            target = type_map.get(subtask["type"], "general_assistant")
            return target if target in self.workers else None
    
        def _execute(self, subtask: dict, worker: str) -> dict:
            return {
                **subtask,
                "worker": worker,
                "permissions": self.workers[worker]["permissions"],
                "status": "completed",
                "output": f"[{worker}] 已完成: {subtask['desc']}",
            }
    
    
    """
    19.7 Evaluator-Optimizer 模式
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    
    核心理念:
      和 Reflection 类似但不同:
      - Reflection: 同一 LLM 生成 + 批评
      - Evaluator-Optimizer: 独立评测 + 独立优化,评测标准更客观
    
    适用场景:
      - 翻译质量优化(BLEU 评分驱动)
      - 代码性能优化(Benchmark 评分驱动)
      - Prompt 自动优化(准确率评分驱动)
    
    这个模式是 DSPy(Ch22 待讲)的核心思想。
    """
    
    
    """
    19.8 Human-in-the-Loop 模式
    ━━━━━━━━━━━━━━━━━━━━━━━━━━
    
    核心理念:
      不是所有操作都应该自动执行。在关键节点引入人工确认。
    
    触发时机:
      ✗ 资金操作(转账、下单)
      ✗ 内容发布(发送邮件、发布文章)
      ✗ 数据删除
      ✗ 系统配置变更
      ✓ 查询类操作 → 自动执行
    
    这是 Ch18 Agent 安全的分级确认机制的扩展。
    """
    
    
    """
    19.9 Top 3 常见错误(Tina Huang + Anthropic 总结)
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    
    错误 1: 过度工程化 (Over-Engineering)
      症状:用 Multi-Agent 做单步就能完成的事
      解法:先问「这真的需要 Agent 吗?」
    
    错误 2: 糟糕的 Prompt (Bad Prompting)
      症状:复杂架构但 prompt 写得很随意
      解法:先投入时间优化 prompt,再考虑架构
    
    错误 3: 糟糕的系统设计 (Poor System Design)
      症状:没有架构图、数据流不清晰、难以调试
      解法:选好架构模式 → 画架构图 → 定义数据流 → 设置错误处理
    
    
    19.10 系统设计题的答题框架
    ━━━━━━━━━━━━━━━━━━━━━━━━━━
    
    面试官:「设计一个智能客服系统」
    
    标准回答结构:
      1. 场景分析(任务特征分类)
      2. 模式选择(主模式 + 辅助模式)
      3. 架构设计(画图!)
      4. 关键决策说明(为什么选这个模式)
      5. 风险与权衡
    
    示例回答:
      「智能客服有3类请求:FAQ(70%)、工单操作(20%)、投诉(10%)。
       用 Routing 模式分流:FAQ 走 RAG + 小模型;工单走 Tool Use;
       投诉需要升级(Human-in-the-Loop)。
       在工单处理中用 Reflection 确保回复质量。
       敏感操作(退款)需要双重确认。」
    """
    
    
    def demo_all_patterns():
        """演示所有设计模式。"""
        print("=" * 60)
        print("  Agentic Workflow 设计模式综合演示")
        print("=" * 60)
    
        # Reflection
        print("\n  ── Reflection 模式 ──")
        agent = ReflectionAgent(quality_threshold=8, max_rounds=3)
        result = agent.run("解释 AI Agent 的核心组成")
        print(f"  任务: {result['task']}")
        print(f"  轮数: {result['rounds']}")
        for h in result["history"]:
            icon = "✅" if h["score"] >= 8 else "🔄"
            print(f"    {icon} 第{h['round']}轮: {h['score']}/10 | {h['issues']}")
    
        # Routing
        print("\n  ── Routing 模式 ──")
        test_tasks = [
            "帮我写一个 Python 快速排序函数",
            "分析最近一个月的销售数据趋势",
            "什么是机器学习?",
            "删除用户 admin 的所有数据",
        ]
        for task in test_tasks:
            decision = RoutingAgent.route(task)
            print(f"  「{task[:30]}...」→ {decision['category']} "
                  f"| 模型: {decision.get('model','')} "
                  f"| 成本: ${decision.get('estimated_cost', 0):.3f}")
    
        # Planning
        print("\n  ── Planning 模式 ──")
        plan = PlanningAgent.decompose("分析AI Agent市场并写一份报告")
        print(f"  分解为 {len(plan)} 个步骤:")
        for step in plan:
            deps = f" (依赖步骤 {step['depends_on']})" if step.get("depends_on") else ""
            print(f"    Step {step['id']}: {step['desc']}{deps}")
    
        # Orchestrator-Worker
        print("\n  ── Orchestrator-Worker 模式 ──")
        ow = OrchestratorWorker()
        ow.register_worker("coder", ["read", "write", "execute"])
        ow.register_worker("writer", ["read", "write"])
        ow.register_worker("tester", ["execute"])
        result = ow.orchestrate("开发一个功能并写文档,确保代码和文档都完整")
        print(f"  子任务: {result['subtasks']} | 使用 Worker: {result['workers_used']}")
        for r in result["results"]:
            print(f"    [{r.get('worker', '?')}] {r['desc']} → {r['status']}")
    
    
    """
    19.11 本章总结
    ━━━━━━━━━━━━━━
    
    核心要点回顾:
    
    1. Workflow ≠ Agent
       - Workflow: 代码控制流程
       - Agent: LLM 控制流程
       - 能不用 Agent 就不用(Anthropic 核心原则)
    
    2. 7 种核心模式
       - ReAct: 最通用,默认选择
       - Reflection: 质量优先场景
       - Routing: 多种任务类型
       - Planning: 复杂多步骤
       - Orchestrator-Worker: 可并行子任务
       - Evaluator-Optimizer: 量化优化
       - Human-in-the-Loop: 安全关键操作
    
    3. 系统设计答题框架
       场景分析 → 模式选择 → 架构设计 → 关键决策 → 风险权衡
    
    面试速记:
      "你用过哪些 Agent 设计模式?"
      → 说出 4+ 种 + 每种的使用场景 + 对比
      → 重点说 Reflection(双角色分离)和 Routing(成本优化)
      → 结尾:Anthropic 原则「简单优先,够用就好」
    """
    
    
    if __name__ == "__main__":
        print("╔══════════════════════════════════════════════════════╗")
        print("║  第19章:Agentic Workflow 设计模式                     ║")
        print("║  Reflection · Routing · Planning · Orchestrator      ║")
        print("╚══════════════════════════════════════════════════════╝")
    
        demo_all_patterns()
    
        print("\n▶ 模式选择速查表")
        print("-" * 50)
        choices = [
            ("输出质量 > 速度", "Reflection"),
            ("多种可分类任务", "Routing"),
            ("复杂多步骤任务", "Planning + ReAct"),
            ("可并行子任务", "Orchestrator-Worker"),
            ("量化优化", "Evaluator-Optimizer"),
            ("安全关键操作", "Human-in-the-Loop"),
            ("简单固定步骤", "直接 LLM(不用 Agent)"),
        ]
        for scene, pattern in choices:
            print(f"  {scene:20s} → {pattern}")
    
        print("\n✅ 第19章完成!")