Agentic工作流设计模式:四大范式与工程选型完全指南

1 阅读1分钟

从"问答机器"到"自主工作者"

2023年以前,大多数AI应用的形态是:用户输入 → 模型生成 → 用户看结果。这是一种被动的、单轮的交互模式,模型的角色更像是一个会打字的搜索引擎。

但今天,越来越多的AI系统开始承担"工作"而非"回答"。它们会自主规划步骤、调用工具、处理异常、评估结果、修正策略——这正是Agentic AI的本质。

然而,"Agentic"这个词在业界被极度滥用。任何接了个function call的聊天机器人都自称"AI Agent"。本文试图厘清概念,梳理Agentic工作流的四大核心设计范式,以及它们各自适用的工程场景和实现要点。

什么构成了一个真正的Agentic系统?

Anthropic的研究给出了一个简洁的判断标准:一个系统是否是Agentic,取决于LLM的输出在多大程度上直接影响真实世界,以及模型是否在无人监督的情况下做出了连续的自主决策。

具体来说,Agentic系统通常具备以下特征:

  • 多步骤执行:完成一个任务需要多轮LLM调用和工具执行
  • 工具使用:能够调用代码执行、搜索、文件操作、API等外部能力
  • 状态管理:跨步骤维护上下文和中间结果
  • 自主判断:不需要每步都等待人类确认
  • 错误恢复:能够处理失败并调整策略

四大核心设计范式

范式一:提示链(Prompt Chaining)

这是最简单的Agentic范式,将复杂任务分解为一系列顺序的LLM调用,每一步的输出是下一步的输入。

核心特点

  • 流程固定,顺序执行
  • 每步专注于单一子任务
  • 可以插入验证节点(Gate),中止不符合条件的执行
from typing import Optional
import openai

class PromptChain:
    def __init__(self, model: str = "gpt-4o"):
        self.client = openai.OpenAI()
        self.model = model
        self.history = []  # 记录每步输出
    
    def step(self, prompt_template: str, gate_fn=None, **kwargs) -> Optional[str]:
        """
        执行一个步骤
        gate_fn: 可选的验证函数,返回False时中止链
        """
        # 用上一步输出填充模板
        previous = self.history[-1] if self.history else ""
        prompt = prompt_template.format(previous=previous, **kwargs)
        
        response = self.client.chat.completions.create(
            model=self.model,
            messages=[{"role": "user", "content": prompt}]
        )
        output = response.choices[0].message.content
        
        # 门控检查
        if gate_fn and not gate_fn(output):
            raise ValueError(f"步骤验证失败,中止链执行。输出:{output[:200]}")
        
        self.history.append(output)
        return output
    
    def get_final(self) -> str:
        return self.history[-1] if self.history else ""


# 实际使用示例:代码生成→测试→Review三步链
def code_generation_chain(requirement: str) -> dict:
    chain = PromptChain()
    
    # 步骤1:生成代码
    code = chain.step(
        "根据需求生成Python代码(只输出代码,不要解释):\n{requirement}",
        requirement=requirement
    )
    
    # 步骤2:生成测试(带门控:确保代码非空)
    tests = chain.step(
        "为以下代码生成pytest单元测试:\n{previous}",
        gate_fn=lambda output: len(output) > 100
    )
    
    # 步骤3:Code Review
    review = chain.step(
        "对以下代码和测试进行安全性和可维护性review,指出潜在问题:\n代码:{code}\n测试:{tests}",
        code=code,
        tests=tests
    )
    
    return {"code": code, "tests": tests, "review": review}

适用场景

  • 文档处理流水线(提取→摘要→翻译→格式化)
  • 代码生成流水线(需求→代码→测试→review)
  • 内容创作流水线(主题→大纲→正文→润色)

不适用:需要根据中间结果动态调整流程的任务。


范式二:路由(Routing)

路由范式的核心是:先由LLM判断输入属于哪种类型,再将其分发到对应的专门处理流程。这种模式实现了"专才专用"。

from enum import Enum
from dataclasses import dataclass

class QueryType(Enum):
    TECHNICAL = "technical"
    BILLING = "billing"
    COMPLAINT = "complaint"
    GENERAL = "general"

@dataclass
class RoutedQuery:
    query: str
    query_type: QueryType
    confidence: float
    metadata: dict

class IntelligentRouter:
    def __init__(self):
        self.client = openai.OpenAI()
        # 各类型对应的专门处理器
        self.handlers = {
            QueryType.TECHNICAL: self.handle_technical,
            QueryType.BILLING: self.handle_billing,
            QueryType.COMPLAINT: self.handle_complaint,
            QueryType.GENERAL: self.handle_general,
        }
    
    def classify(self, query: str) -> RoutedQuery:
        """使用LLM分类,要求结构化输出"""
        import json
        
        response = self.client.chat.completions.create(
            model="gpt-4o-mini",  # 路由用小模型,节省成本
            response_format={"type": "json_object"},
            messages=[{
                "role": "user",
                "content": f"""
将以下用户查询分类为:technical/billing/complaint/general
输出JSON格式:{{"type": "...", "confidence": 0.0-1.0, "reason": "..."}}

查询:{query}
"""
            }]
        )
        
        result = json.loads(response.choices[0].message.content)
        return RoutedQuery(
            query=query,
            query_type=QueryType(result["type"]),
            confidence=result["confidence"],
            metadata={"reason": result.get("reason", "")}
        )
    
    async def handle_technical(self, routed: RoutedQuery) -> str:
        """技术问题:使用更强的模型+工具调用"""
        # 调用代码执行工具、文档搜索等
        return f"[技术支持] 处理:{routed.query}"
    
    async def handle_billing(self, routed: RoutedQuery) -> str:
        """账单问题:查询财务系统"""
        return f"[账单查询] 处理:{routed.query}"
    
    async def handle_complaint(self, routed: RoutedQuery) -> str:
        """投诉:优先级最高,转人工"""
        return f"[投诉处理] 已转接人工客服:{routed.query}"
    
    async def handle_general(self, routed: RoutedQuery) -> str:
        """一般问题:标准模型处理"""
        return f"[通用回答] 处理:{routed.query}"
    
    async def route_and_handle(self, query: str) -> dict:
        routed = self.classify(query)
        handler = self.handlers[routed.query_type]
        result = await handler(routed)
        
        return {
            "query": query,
            "classified_as": routed.query_type.value,
            "confidence": routed.confidence,
            "response": result
        }

多模型路由策略(按成本和能力分级):

class ModelRouter:
    """根据任务复杂度路由到不同的模型"""
    
    MODELS = {
        "simple": "gpt-4o-mini",    # 简单任务:低延迟低成本
        "medium": "gpt-4o",          # 中等任务:平衡
        "complex": "o1",             # 复杂推理:高准确率
        "creative": "claude-opus-4-5", # 创意生成:最佳输出质量
    }
    
    def select_model(self, task_description: str) -> str:
        complexity = self._estimate_complexity(task_description)
        task_type = self._classify_task_type(task_description)
        
        if task_type == "creative":
            return self.MODELS["creative"]
        return self.MODELS.get(complexity, self.MODELS["medium"])

范式三:并行化(Parallelization)

对于可以分解为独立子任务的工作,并行执行能显著降低总延迟,同时通过多路验证提升结果质量。

子范式A:分段并行

import asyncio
from typing import List

async def parallel_document_analysis(document: str) -> dict:
    """
    对同一文档并行执行多项分析
    原本串行需要 4×T,并行只需 1×T
    """
    async def analyze_key_points(doc: str) -> str:
        # 提取核心论点
        pass
    
    async def assess_risks(doc: str) -> str:
        # 风险评估
        pass
    
    async def check_compliance(doc: str) -> str:
        # 合规检查
        pass
    
    async def generate_summary(doc: str) -> str:
        # 生成摘要
        pass
    
    # 并行执行所有分析
    results = await asyncio.gather(
        analyze_key_points(document),
        assess_risks(document),
        check_compliance(document),
        generate_summary(document),
        return_exceptions=True
    )
    
    key_points, risks, compliance, summary = results
    
    return {
        "key_points": key_points,
        "risks": risks if not isinstance(risks, Exception) else "分析失败",
        "compliance": compliance,
        "summary": summary
    }

子范式B:投票验证(多数表决)

async def validated_extraction(text: str, schema: dict) -> dict:
    """
    使用多个并行调用做投票验证,提高结构化提取的准确性
    适合高精度要求的信息提取场景
    """
    import json
    
    async def single_extraction(attempt_id: int) -> dict:
        response = await client.chat.completions.create(
            model="gpt-4o",
            response_format={"type": "json_object"},
            messages=[{
                "role": "user",
                "content": f"从以下文本提取信息,输出JSON:\n{text}\n目标schema:{json.dumps(schema)}"
            }],
            temperature=0.1  # 低温度,但多次采样增加稳定性
        )
        return json.loads(response.choices[0].message.content)
    
    # 并行执行3次提取
    extractions = await asyncio.gather(*[single_extraction(i) for i in range(3)])
    
    # 字段级投票:对每个字段取出现最多的值
    merged = {}
    for key in schema.keys():
        values = [e.get(key) for e in extractions if e.get(key) is not None]
        if values:
            # 取众数
            from collections import Counter
            merged[key] = Counter(values).most_common(1)[0][0]
    
    return merged

范式四:Orchestrator-Subagent(编排者-子智能体)

这是最复杂也是最强大的范式。一个中央编排者LLM负责任务拆解和协调,多个专门的子智能体负责具体执行。

from typing import Dict, Any, Callable
import json

class AgentOrchestrator:
    """
    编排者:负责任务拆解、子智能体调度、结果整合
    """
    
    def __init__(self):
        self.client = openai.OpenAI()
        self.subagents: Dict[str, Callable] = {}
        self.execution_log = []
    
    def register_subagent(self, name: str, agent_fn: Callable, description: str):
        """注册子智能体"""
        self.subagents[name] = {
            "fn": agent_fn,
            "description": description
        }
    
    def get_tools_schema(self) -> list:
        """将子智能体转为tools schema"""
        return [
            {
                "type": "function",
                "function": {
                    "name": name,
                    "description": info["description"],
                    "parameters": {
                        "type": "object",
                        "properties": {
                            "task": {"type": "string", "description": "要执行的具体任务描述"},
                            "context": {"type": "string", "description": "相关上下文信息"}
                        },
                        "required": ["task"]
                    }
                }
            }
            for name, info in self.subagents.items()
        ]
    
    async def orchestrate(self, objective: str, max_iterations: int = 10) -> str:
        """
        主编排循环
        1. 编排者分析目标,决定调用哪个子智能体
        2. 执行子智能体,获取结果
        3. 编排者根据结果决定下一步
        4. 重复直到任务完成
        """
        messages = [
            {"role": "system", "content": "你是一个任务编排助手,通过调用专门的子智能体来完成复杂任务。分析目标,按序调度合适的子智能体。"},
            {"role": "user", "content": f"目标:{objective}"}
        ]
        
        for iteration in range(max_iterations):
            response = self.client.chat.completions.create(
                model="gpt-4o",
                messages=messages,
                tools=self.get_tools_schema(),
                tool_choice="auto"
            )
            
            msg = response.choices[0].message
            
            # 如果不需要工具调用,说明任务完成
            if not msg.tool_calls:
                return msg.content
            
            messages.append(msg)
            
            # 执行所有工具调用(可能并行)
            tool_results = []
            for tool_call in msg.tool_calls:
                agent_name = tool_call.function.name
                args = json.loads(tool_call.function.arguments)
                
                print(f"  [编排] 调用子智能体: {agent_name}")
                print(f"  [任务] {args.get('task', '')[:100]}")
                
                try:
                    agent_fn = self.subagents[agent_name]["fn"]
                    result = await agent_fn(args.get("task", ""), args.get("context", ""))
                    self.execution_log.append({
                        "agent": agent_name,
                        "task": args.get("task"),
                        "result_preview": str(result)[:200]
                    })
                except Exception as e:
                    result = f"错误:{str(e)}"
                
                tool_results.append({
                    "tool_call_id": tool_call.id,
                    "role": "tool",
                    "name": agent_name,
                    "content": str(result)
                })
            
            messages.extend(tool_results)
        
        return "达到最大迭代次数,任务未完全完成"


# 实际使用:搭建一个软件开发Agent系统
async def build_software_agent():
    orchestrator = AgentOrchestrator()
    
    # 注册专门的子智能体
    orchestrator.register_subagent(
        "code_writer",
        lambda task, ctx: write_code(task, ctx),
        "编写代码的智能体,擅长Python、JavaScript等"
    )
    orchestrator.register_subagent(
        "test_writer",
        lambda task, ctx: write_tests(task, ctx),
        "编写单元测试的智能体"
    )
    orchestrator.register_subagent(
        "code_reviewer",
        lambda task, ctx: review_code(task, ctx),
        "代码审查智能体,检查安全性、性能和可维护性"
    )
    orchestrator.register_subagent(
        "documentation_writer",
        lambda task, ctx: write_docs(task, ctx),
        "编写技术文档和注释的智能体"
    )
    
    result = await orchestrator.orchestrate(
        "实现一个用户认证模块,包括注册、登录、JWT token管理,带完整测试和文档"
    )
    return result

范式选型决策树

任务是否可以分解为固定的顺序步骤?
├── 是 → 提示链(Prompt Chaining)
│         适合:文档处理、内容生成流水线
│
任务输入是否属于明确的几类之一?
├── 是 → 路由(Routing)
│         适合:客服系统、多专业域问答
│
任务的子任务之间是否相互独立?
├── 是 → 并行化(Parallelization)
│         适合:多角度分析、批量处理、验证
│
任务是否需要动态判断执行步骤?
└── 是 → 编排者-子智能体
          适合:复杂软件开发、研究任务、多步骤规划

Human-in-the-Loop的工程集成

对于高风险的Agentic操作,合理的人工介入点设计至关重要:

class CheckpointedAgent:
    """
    在关键节点暂停等待人工确认的Agent
    """
    RISK_LEVELS = {
        "read_file": "low",
        "write_file": "medium",
        "delete_file": "high",
        "send_email": "high",
        "execute_sql": "medium",
        "api_call_external": "medium"
    }
    
    async def execute_with_checkpoint(self, action: str, args: dict, risk_threshold: str = "high") -> dict:
        risk = self.RISK_LEVELS.get(action, "medium")
        
        risk_order = {"low": 0, "medium": 1, "high": 2}
        
        if risk_order[risk] >= risk_order[risk_threshold]:
            # 需要人工确认
            confirmed = await self.request_human_approval(action, args, risk)
            if not confirmed:
                return {"status": "rejected", "reason": "用户拒绝执行"}
        
        # 执行实际操作
        return await self.execute_action(action, args)
    
    async def request_human_approval(self, action: str, args: dict, risk: str) -> bool:
        print(f"\n⚠️  [需要确认] 风险等级: {risk.upper()}")
        print(f"   操作: {action}")
        print(f"   参数: {args}")
        response = input("   确认执行? (y/n): ")
        return response.lower() == 'y'

总结

四大Agentic工作流范式并非互斥,实际系统往往是它们的组合:

范式最适场景关键优势主要限制
提示链固定流水线简单、可预测不灵活
路由多类型输入专才专用分类边界模糊时失效
并行化独立子任务低延迟、多验证需要汇总逻辑
编排者复杂动态任务最灵活成本高、难调试

选择范式的核心原则:从最简单的开始。提示链能解决的问题,不要上编排者;路由能处理的,不要写复杂的动态规划。复杂性是工程债务,只在真正需要的时候才引入。

2026年,Agentic系统的可靠性、可观测性和成本控制是工程落地的三大挑战。掌握这四种范式,是构建可维护AI系统的基础。