/ AI Agent  工作流  LLM  大模型  智能体  生产实践  Prompt工程  工具调用 

深度解析 AI Agent 工作流:从理论到生产实践的完整指南


封面

一、AI Agent 的本质:不只是"会用工具的 LLM"

近两年,"AI Agent"这个词几乎出现在所有大模型相关的讨论中。但在实际落地时,很多团队发现:Demo 跑起来很酷,一到生产就翻车。原因往往不在模型本身,而在于对 Agent 架构的理解不够深入。

从本质上看,AI Agent 是一个具备自主决策能力的循环系统。它不只是接收一个问题然后返回答案,而是能够:

  • 感知环境:接收用户输入、工具返回、上下文状态

  • 规划行动:根据目标分解任务、选择工具

  • 执行操作:调用外部 API、执行代码、检索信息

  • 反思结果:评估执行结果,决定下一步

  • 记忆管理:维护短期和长期记忆,跨轮次保持上下文

这个循环可以持续运转,直到任务完成或遇到需要人工介入的情况。理解这个本质,是构建可靠 Agent 系统的第一步。

二、ReAct 模式:Agent 工作流的基石

目前最主流的 Agent 推理框架是 ReAct(Reason + Act),由 Yao et al. 在 2022 年提出。其核心思想是让 LLM 交替进行"思考"和"行动",形成 Thought → Action → Observation 的循环。

Thought: 用户想查询北京今天的天气,我需要调用天气 API
Action: call_weather_api(city="北京", date="2026-06-24")
Observation: {"temp": 32, "weather": "晴", "humidity": 45}
Thought: 已获取天气数据,现在可以给用户回复了
Action: final_answer("北京今天天气晴,气温32°C,湿度45%")

这种模式有几个关键优点:

  • 可解释性强:每一步推理都有迹可循,便于调试

  • 错误可恢复:Observation 失败时,模型可以重新规划

  • 工具解耦:工具定义与推理逻辑分离,易于扩展

在实际工程实现中,ReAct 通常通过函数调用(Function Calling)来落地。以 OpenAI 兼容接口为例:

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "获取指定城市的天气信息",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {"type": "string", "description": "城市名称"},
                    "date": {"type": "string", "description": "日期,格式 YYYY-MM-DD"}
                },
                "required": ["city"]
            }
        }
    }
]

response = client.chat.completions.create(
    model="gpt-4o",
    messages=messages,
    tools=tools,
    tool_choice="auto"
)

当模型决定调用工具时,会返回 tool_calls 字段,你的代码负责执行,将结果以 role: "tool" 的消息追加回去,再次请求模型,如此循环。

三、工具设计原则:好工具是 Agent 成功的关键

工具质量直接决定 Agent 的能力上限。很多开发者在工具设计上犯的错误,比模型选择的影响还要大。以下是经过生产验证的工具设计原则:

1. 单一职责

每个工具只做一件事。避免"万能工具"——一个工具参数越多,模型调用出错的概率就越高。

# ❌ 糟糕的设计:一个工具做太多事
def database_operation(action: str, table: str, data: dict = None, query: str = None):
    if action == "read": ...
    elif action == "write": ...
    elif action == "delete": ...

# ✅ 好的设计:分开定义
def query_records(table: str, filters: dict) -> list: ...
def insert_record(table: str, data: dict) -> str: ...
def delete_record(table: str, record_id: str) -> bool: ...

2. 描述要精准

工具的 description 不是写给人看的注释,而是模型的"说明书"。要明确说明:什么情况下用、参数含义、返回值格式、副作用(是否有写操作)。

3. 幂等性设计

网络超时、模型重试都可能导致工具被调用多次。查询类工具天然幂等,写操作需要通过唯一 ID 或条件检查来保证幂等。

4. 结构化返回值

工具返回 JSON 而非自然语言字符串。模型处理结构化数据更准确,也便于后续的错误检测。

四、记忆管理:让 Agent 拥有"真正的记忆"

Agent 的记忆系统通常分为四个层次:

  • 感知缓冲(Context Window):当前对话的完整上下文,受 Token 限制

  • 短期记忆(Working Memory):本次任务的中间状态,如变量值、已完成的子任务

  • 长期记忆(Long-term Memory):跨会话的用户偏好、历史摘要,通常存向量数据库

  • 外部知识(External Knowledge):RAG 检索的文档、实时数据

Context Window 管理是最常见的工程挑战。当对话历史超出限制时,常用策略:

class ContextManager:
    def __init__(self, max_tokens: int = 16000):
        self.max_tokens = max_tokens
        self.messages = []
    
    def add_message(self, role: str, content: str):
        self.messages.append({"role": role, "content": content})
        self._trim_if_needed()
    
    def _trim_if_needed(self):
        """保留系统消息 + 最近 N 轮对话"""
        total = self._estimate_tokens()
        while total > self.max_tokens and len(self.messages) > 2:
            # 保留第一条 system 消息,删除最旧的 user/assistant 对
            if self.messages[1]["role"] != "system":
                removed = self.messages.pop(1)
                total -= self._count_tokens(removed["content"])
    
    def _estimate_tokens(self) -> int:
        return sum(len(m["content"]) // 3 for m in self.messages)

对于需要长期记忆的 Agent,推荐使用 Mem0 或自建向量存储(如 Qdrant + text-embedding)来持久化重要信息。

五、错误恢复与容错设计:从 Demo 到生产的关键跨越

生产环境的 Agent 面临各种故障:网络超时、工具返回错误、模型幻觉、无限循环……不做好容错,Agent 要么卡死,要么产生错误结果。

1. 设置最大步骤数

class AgentRunner:
    def __init__(self, max_steps: int = 20):
        self.max_steps = max_steps
    
    async def run(self, task: str) -> str:
        steps = 0
        messages = [{"role": "user", "content": task}]
        
        while steps < self.max_steps:
            response = await self.llm.call(messages)
            
            if response.finish_reason == "stop":
                return response.content  # 任务完成
            
            if response.finish_reason == "tool_calls":
                tool_results = await self.execute_tools(response.tool_calls)
                messages.extend(tool_results)
                steps += 1
            else:
                break
        
        return "任务超出最大步骤数,已终止"  # 防止无限循环

2. 工具调用重试

import asyncio
from tenacity import retry, stop_after_attempt, wait_exponential

@retry(stop=stop_after_attempt(3), wait=wait_exponential(min=1, max=10))
async def call_tool_with_retry(tool_name: str, params: dict):
    try:
        result = await tools[tool_name](**params)
        return {"success": True, "data": result}
    except Exception as e:
        # 将错误信息返回给模型,让它重新规划
        return {"success": False, "error": str(e), "hint": "请检查参数后重试"}

3. 人工介入点(Human-in-the-Loop)

对于高风险操作(删除数据、发送邮件、支付),在执行前暂停并请求人工确认:

HIGH_RISK_TOOLS = {"delete_user", "send_email", "process_payment"}

async def execute_tool(tool_name: str, params: dict):
    if tool_name in HIGH_RISK_TOOLS:
        confirmed = await request_human_approval(tool_name, params)
        if not confirmed:
            return {"status": "cancelled", "reason": "用户拒绝授权"}
    return await tools[tool_name](**params)

六、可观测性:让 Agent 的"思考"不再是黑盒

生产 Agent 必须是可观测的。没有追踪,出了问题你甚至不知道 Agent 到底做了什么。

推荐使用 LangSmith(LangChain 生态)或 Langfuse(开源,自托管友好)进行追踪。核心追踪维度:

  • Trace:完整的 Agent 执行链路,包含所有 LLM 调用和工具调用

  • Span:单次操作的耗时、输入输出

  • Token 用量:每次 LLM 调用的 prompt/completion tokens,用于成本控制

  • 错误率:工具调用失败率、模型返回异常率

from langfuse import Langfuse
from langfuse.decorators import observe

langfuse = Langfuse()

@observe(name="agent_run")
async def run_agent(task: str, user_id: str):
    trace = langfuse.trace(name="agent_task", user_id=user_id, input=task)
    
    with trace.span(name="planning") as span:
        plan = await llm.plan(task)
        span.end(output=plan)
    
    for step in plan.steps:
        with trace.span(name=f"tool_{step.tool}") as span:
            result = await execute_tool(step.tool, step.params)
            span.end(output=result, metadata={"tokens": result.get("tokens")})
    
    return final_result

除了追踪,还要建立 评估体系(Evaluation)。定期用标准测试集跑 Agent,追踪任务完成率、平均步骤数、成本等指标的变化趋势,这样才能知道模型升级或 Prompt 调整是否真的带来了提升。

七、生产部署的工程实践总结

把所有经验凝练成几条可直接落地的建议:

  • 从简单架构开始:不要一上来就用多 Agent,单 Agent + 好工具能解决 80% 的问题

  • 投资工具质量:花在工具描述和错误处理上的时间,比调 Prompt 更值

  • 先跑通,再优化:先用 GPT-4o 跑通业务逻辑,再考虑换小模型降成本

  • 一切都要可追踪:没有观测性的 Agent 不要上生产

  • 为失败设计:工具失败是常态,每个工具都要有明确的错误返回格式

  • 控制上下文长度:Token 成本会随任务复杂度指数上涨,要主动管理

  • 灰度发布:先给 5% 用户,观察错误率和完成率,再逐步放量

AI Agent 正在经历从"技术演示"到"生产系统"的关键转型期。掌握这些工程实践,才能在这波浪潮中真正建立竞争优势,而不是停留在 Demo 阶段。

发布评论

热门评论区: