做 AI Agent 这行两年多,我最大的感受就一个字:虚。虚在哪?虚在“能跑”和“好用”之间的距离,可能比从零到一还远。2025年立项时说“我们要做一个 Agent”,大家眼睛发光;2026年开会问“你的 Agent 到底行不行?有没有标准答案?”,气氛瞬间安静。今天我不聊那些天花乱坠的概念,就讲怎么判断、怎么搭、怎么压测、怎么修,把这套标准答案掰开揉碎,也是给我自己这两年踩过的坑做个阶段复盘。
这篇文章是我基于实际项目经验的完整总结,适合三类人看:一是刚接触 AI Agent 的开发者,想搞明白这东西从哪下手;二是团队里要负责 Agent 落地的工程负责人,正愁怎么定验收标准;三是已经在做 Agent、但老觉得效果不稳定的朋友,你可以在里面的问题排查章节对号入座。文章会覆盖主流架构的选型逻辑、一个能扛并发的完整项目骨架、五类可量化的评测指标体系,以及十个实战高频问题的排查方法。先给你说结论:2026年了,Agent 好不好用,不是靠感觉,是有一整套可以量化的标准的。
1. 先搞清楚:你手里的东西到底算不算 Agent
很多团队吵了一个月到底要不要上 Agent,最后发现连定义都没对齐。这真不夸张。产品经理说 Agent 就是能自动干活的机器人,后端说 Agent 是有记忆和执行力的 LLM 应用,测试说 Agent 是那种会自己调用一堆工具的东西。说的都对,但都不全。我建议直接按三档分类法对齐认知,大家一开口就知道在说哪层东西。
1.1 LLM 应用三段论:Chatbot、Workflow、Agent
第一档是纯 Chatbot。就是一个大模型接口加一个聊天界面,有对话、有流式输出,本质上就是 OpenAI 兼容接口的壳。它没有工具调用、没有外部状态、没有自主决策。这种项目做起来最快,但也最容易让老板产生幻觉,以为这就是 Agent。
第二档是 Workflow。固定流程的大模型应用,比如“先做意图识别,再走摘要,再走情感分析”,流程写死在代码里。这类应用的好处是稳定、可预期、好测试。很多号称 Agent 的线上项目,拆开看其实是精致的 Workflow。这里没有任何贬义,实际上我认为 80% 的业务场景用 Workflow 就够了,后面我会专门讲为什么。
第三档才是真正的 Agent。关键区别在于闭环:模型根据用户任务自主决定调用哪些工具、按什么顺序调用、如何根据工具返回结果调整下一步。它具有一定的目标导向性、规划能力和反应能力。判断标准不是“有没有工具调用”,而是“控制流是谁决定的”。控制流写死在代码里叫 Workflow,控制流由模型在运行时决策的叫 Agent。
1.2 Agent 的“五要素”判断法
我总结了五要素,缺一个都别叫 Agent,否则评审会上会被问住。这五要素是:目标感知、工具使用、自主规划、记忆管理、迭代修正。
目标感知指系统能理解用户的最终目标,而不只是理解当前这句话。工具使用指能通过函数调用或 MCP 协议操作外部系统。自主规划指能在运行时拆解步骤、决定顺序。记忆管理指能在多轮对话或长任务中维持短期上下文和长期知识。迭代修正是最关键的一条,当工具返回报错时,Agent 能不能看懂错误、调整参数、再试一次。很多人做的所谓 Agent 一次失败就“复读机”式报错,那连智能的门槛都没碰到。
拿这三档分类和五要素去套你手里的项目,很快就能看清它的真实水位。我见过太多“伪 Agent”,名字叫 AI Agent,实际是个套着 ReAct Prompt 的聊天机器人,工具只有两个还经常调错。
1.3 为什么满大街都是 Agent,真正能打的没几个
这个现象很值得思考。2025 年到 2026 年,Agent 概念泛滥,但落地效果参差不齐,本质原因有三条。
第一,模型能力被高估。很多人默认 GPT-4o 级别或国产旗舰模型已经具备了“推理大师”的能力,实际测下来,模型在复杂多步任务上的稳定率远没有想象中高。给模型一个模糊目标,它能跑出一条漂亮的逻辑链,但跑到第三步就会跑偏。不是模型笨,是 Agent 这类任务的难点本来就不在单次推理,而在长时间的稳定性。
第二,评测体系缺位。传统软件有单元测试、集成测试、回归测试,Agent 呢?很多人上线前手工试了 20 个 prompt,觉得“好像还行”就直接发布。结果线上用户一用,千奇百怪的输入全来了,各种炸。没有量化基准,就没有迭代依据,这是行业最大的坑。
第三,架构设计偷懒。直接把 LLM API 包的调用堆在一起,没有状态管理、没有重试机制、没有超时熔断、没有可观测性,这不是 Agent,是定时炸弹。后面我会展示一个相对标准的架构长什么样。
2. 2026 年主流 Agent 架构长什么样
架构选型是第一个硬骨头。我在几个项目里试过不同流派,也看过业界一些开源方案的演进,2026 年的主流架构其实已经收敛出比较清晰的范式:调度层、执行层、记忆层三层分离。加上 LangGraph、字节扣子这类框架的快速成熟,自研 Agent 的门槛已经大幅下降,但理解架构原理仍然至关重要。
2.1 三层基础:调度层、执行层、记忆层
调度层承担大脑功能:理解用户意图、拆解任务、决定调用哪个工具、判断是否要继续迭代。它的核心可以是 ReAct 循环、Plan-and-Execute 流程,也可以是多 Agent 协作的 Router。这一层对模型的推理能力要求最高,也是 Prompt 工程的重灾区。
执行层是手脚:工具函数、API 集成、RAG 检索、外部系统操作。每个工具必须有清晰的输入输出描述,最好用 JSON Schema 定义,让模型知道参数怎么填。我踩过一个大坑:工具描述写得模糊,模型经常把日期格式传错、把 ID 字段传成名称字段。后来规规矩矩写清楚每一个参数的格式、取值范围、示例,工具调用准确率直接翻倍。
记忆层负责状态存储:短期记忆存对话上下文,长期记忆存用户偏好、领域知识、历史决策。工程上,短期记忆用 Redis 或内存缓存,长期记忆用向量库加 PostgreSQL。没有记忆层的 Agent 是老年痴呆,每轮对话都像第一次见面,产品价值大打折扣。
2.2 ReAct 循环:最简单也最容易翻车
ReAct 是 Reasoning + Acting 的组合,思路很朴素:让模型在思考、行动、观察之间循环,直到得出最终答案。伪代码如下:
while not done: thought = llm.think(task, memory, tool_descriptions) if thought.final_answer: return thought.answer result = call_tool(thought.action, thought.action_input) memory.append(result)优点是好实现、灵活、适合单 Agent 场景。缺点是太自由,特别容易陷入死循环。模型可能会反复调用同一个失败的接口,或者在一个分支里绕不出去。我见过一个文档问答 Agent 在某轮评测中连续循环了 12 次才终止,Token 烧掉一大截,答案还是错的。
解决死循环最土但最有效的三个手段:最大迭代次数、工具调用超时、相似重复动作检测。迭代次数我一般设置在 5 到 8 次,超过就自动终止并返回当前结论。工具调用超时按工具类型区分,数据库查询给 10 秒,外部 HTTP 给 5 秒。重复动作检测是记录最近三步的 action 和 action_input,如果完全一样,说明模型在打转,直接掐断。
2.3 Plan-and-Execute 与 Multi-Agent:场景驱动选型
比 ReAct 更稳的是 Plan-and-Execute 模式,先规划再执行。第一步让模型生成完整计划,例如“1. 查询订单表 → 2. 计算退款金额 → 3. 调用退款接口 → 4. 发送通知”,然后按计划逐步执行,每步执行完把结果反馈给模型,模型可以微调后续步骤。
这种模式的优点是可控性好、Token 消耗更可预测、中途出错的定位也更方便。缺点是灵活性受限,遇到需要临场应变的复杂任务容易卡住。所以我的选型标准是:任务路径相对固定的用 Plan-and-Execute,任务开放性强、需要动态决策的用 ReAct。
Multi-Agent 是 2026 年的大热门,但我对它的态度是谨慎。多个 Agent 各司其职,比如一个负责规划、一个负责写代码、一个负责测试,理论上很美好,实操中要解决通信成本、责任边界、上下文一致性三大问题。我的建议是:能用单 Agent 解决的问题绝不上多 Agent。多 Agent 适合场景足够复杂的团队,比如自动化软件研发、跨系统复杂流程编排,否则只是徒增维护成本。
2.4 主流框架怎么选:LangGraph、扣子、Spring AI、自研
框架选型直接影响开发效率。我聊几个主流的,把适合场景说清楚。
LangGraph 是我目前主力,它的核心价值是把 Agent 定义成一张状态图,节点是处理逻辑,边是状态转移,底层用 LangChain 的组件生态。相比 LangChain 的 Chain 模式,LangGraph 对分支、循环、并发的表达能力强得多。它唯一的毛病是概念有点多,学习曲线略陡,但一旦上手,复杂 Agent 的表达会非常自然。
字节的扣子(Coze)是低代码平台,适合业务人员和轻量场景,我接了不少企业项目,发现很多运营团队用扣子搭客服 Agent,不需要写代码,拖拽节点就能完成。实际上它是 Workflow 驱动的,背后也用到了 Agent 能力,缺点是深度定制、私有化部署以及扛高并发仍有限制。你要是做内部工具、MVP 验证、小红书自动发消息这类轻自动化场景,扣子很合适;要做严肃的线上生产系统,还是得上代码。
Java 技术栈团队会考虑 Spring AI Agent,它跟 Spring Boot 生态融合得很好,适合已有 Java 微服务架构的企业。但它的 Agent 编排能力比起 LangGraph 还是有差距,工具生态也偏薄。
自研是终极方案,适合已经踩透了框架、对性能和可控性有极端要求的团队。我去年帮一个量化交易团队做过一版 Rust 核心 + Python 业务的混合架构,Rust 负责调度和并发,Python 负责模型调用和工具生态调用,效果出奇地稳,压测扛到了单机 1000 并发不垮。这就是热词里说的“基于 Rust 语言 AI Agent”路子,适合高端玩家。
3. 手把手搭一个能扛并发的 Agent 项目
光说不练假把式。这一节我按自己实际搭过的项目,给你一个可以照着改的完整骨架。技术栈选 FastAPI + LangGraph + Redis + PostgreSQL,这套组合是目前我认为性价比最高的:FastAPI 的异步性能自不必说,LangGraph 负责 Agent 编排,Redis 扛状态缓存和限流,PostgreSQL 存长期数据和评测记录。
3.1 项目结构与技术选型逻辑
先看目录结构,按我之前项目的精简版:
agent-server/ ├── app/ │ ├── main.py # FastAPI 入口 │ ├── api/ │ │ └── routes.py # HTTP 接口 │ ├── agent/ │ │ ├── graph.py # LangGraph 状态图定义 │ │ ├── nodes.py # 各节点处理函数 │ │ ├── tools.py # 工具注册与实现 │ │ └── prompts.py # Prompt 模板管理 │ ├── core/ │ │ ├── config.py # 环境配置 │ │ ├── redis_client.py # Redis 封装 │ │ └── security.py # API Key 校验与限流 │ ├── memory/ │ │ ├── short_term.py # 短期内存 │ │ └── long_term.py # 长期向量记忆 │ └── eval/ │ ├── dataset.py # 评测集 │ └── runner.py # 评测执行 ├── tests/ ├── docker-compose.yml ├── Dockerfile └── pyproject.toml为什么这么分?核心思想是 Agent 逻辑、基础能力、接口暴露、离线评测彼此解耦。很多项目把 Agent 代码和 Flask/FastAPI 路由写在一起,刚开始爽,后面加评测、加多租户、加并发控制时就痛苦到想重构。我的习惯是:能提前分离的都分离,不要懒。
3.2 用 LangGraph 定义核心 Agent 状态图
先装依赖:
pip install fastapi uvicorn langgraph langchain-openai redis psycopg[binary] pydantic-settings核心的图定义我直接给代码,这段是能跑的:
# app/agent/graph.py from typing import TypedDict from langgraph.graph import StateGraph, END from app.agent.nodes import think_node, tool_node MAX_ITERATIONS = 6 class AgentState(TypedDict): task: str # 用户原始任务 messages: list # 对话历史 next_tool: str tool_args: dict observation: str iterations: int final_answer: str def should_continue(state: AgentState) -> str: if state["final_answer"]: return "end" if state["iterations"] >= MAX_ITERATIONS: return "end" if state["observation"]: return "think" # 有观察结果,继续思考 if state["next_tool"]: return "tool" # 决策出工具,执行 return "end" graph = StateGraph(AgentState) graph.add_node("think", think_node) graph.add_node("tool", tool_node) graph.set_entry_point("think") graph.add_conditional_edges( "think", should_continue, { "tool": "tool", "end": END, }, ) graph.add_edge("tool", "think") agent_app = graph.compile()这段代码的核心是 conditional_edges,它让控制流由模型输出动态决定。think_node 负责调用大模型,根据系统 Prompt 里给出的工具列表,决定是输出最终答案还是输出工具调用。tool_node 负责解析模型输出的工具名和参数,真正去执行,并把结果写回 observation。
3.3 节点实现:思考节点与工具执行节点
think_node 的伪代码实现要点:
# app/agent/nodes.py import json from langchain_openai import ChatOpenAI from app.agent.tools import TOOL_REGISTRY from app.agent.prompts import AGENT_SYSTEM_PROMPT llm = ChatOpenAI(model="gpt-4o", temperature=0) llm_with_tools = llm.bind_tools([t.openai_schema for t in TOOL_REGISTRY.values()]) def think_node(state: AgentState) -> AgentState: messages = [{"role": "system", "content": AGENT_SYSTEM_PROMPT}] + state["messages"] if state["observation"]: messages.append({"role": "user", "content": f"工具返回结果:{state['observation']}"}) response = llm_with_tools.invoke(messages) state["iterations"] += 1 if response.tool_calls: state["next_tool"] = response.tool_calls[0]["name"] state["tool_args"] = response.tool_calls[0]["args"] state["final_answer"] = "" else: state["next_tool"] = "" state["final_answer"] = response.content state["observation"] = "" return state联网调工具是 Agent 的灵魂,执行节点这样写:
def tool_node(state: AgentState) -> AgentState: tool_name = state["next_tool"] tool = TOOL_REGISTRY.get(tool_name) if not tool or tool is None: state["observation"] = f"错误:未知工具 {tool_name}" return state try: result = tool.execute(**state["tool_args"]) state["observation"] = json.dumps(result, ensure_ascii=False, default=str) except Exception as e: state["observation"] = f"工具执行异常:{str(e)}" state["next_tool"] = "" return state从上面代码可以看到,我把所有工具放进 TOOL_REGISTRY,这样加新工具只需要新写一个类或函数,不用改动图结构,这是 LangGraph 生态里很自然的扩展方式。
3.4 并发三板斧:异步、水平扩展、限流降级
Agent 服务和普通 API 最大的区别在于:每一个请求都是长耗时的、多步推理的、状态可变的。如果按传统同步方式处理,并发一上来立刻被打垮。我在这块试了几种方案,沉淀下三板斧。
第一板斧:接口全异步,非阻塞 IO。FastAPI 天生支持 async,但要注意别在 async 函数里塞同步阻塞的数据库查询或大模型 SDK 调用。ChatOpenAI 的 invoke 是同步的,要包成 async:
import asyncio from fastapi.concurrency import run_in_threadpool @app.post("/v1/agent/run") async def run_agent(req: AgentRequest): # 用 run_in_threadpool 把同步 LLM 调用扔到线程池 result = await run_in_threadpool(agent_app.invoke, req.dict()) return result第二板斧:多副本无状态化,用 Redis 做状态中心。Agent 实例可以水平扩展的关键是实例之间不共享本地内存。LangGraph 的 State 默认在内存里,跨实例就出问题。我这里做了一个简单可靠的方案:启动时把 Agent 初始状态存入 Redis,每步迭代后更新 Redis 中的状态字段,实例故障时可以通过 Redis 恢复。核心代码:
# app/memory/short_term.py import redis r = redis.from_url("redis://localhost:6379/0") def save_agent_run(run_id: str, state: dict, ttl: int = 600): key = f"agent:{run_id}" r.hset(key, mapping=state) r.expire(key, ttl) def get_agent_run(run_id: str) -> dict: return r.hgetall(f"agent:{run_id}")第三板斧:入口限流与超时熔断。我用 Redis + Token Bucket 实现简单的用户级限流,每秒每用户最多 5 个请求,超出直接返回 429。另外每个 Agent 请求设置总体超时,比如 30 秒,超时就把执行中的任务标记为失败并回收资源。这个思路就是热词里“ai agent 怎么扛并发”的答案:不是黑魔法,而是异步化 + 状态外置 + 限流降级这套经典组合拳。
3.5 用 Docker Compose 一键起服务
最后给一个可直接用的编排文件:
version: "3.9" services: redis: image: redis:7-alpine ports: - "6379:6379" postgres: image: postgres:15-alpine environment: POSTGRES_USER: agent POSTGRES_PASSWORD: agent_pass POSTGRES_DB: agent_platform ports: - "5432:5432" agent-server: build: . environment: OPENAI_API_KEY: ${OPENAI_API_KEY} REDIS_URL: redis://redis:6379/0 DATABASE_URL: postgresql://agent:agent_pass@postgres:5432/agent_platform depends_on: - redis - postgres ports: - "8000:8000" command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 4注意 --workers 4 这个参数,代表启动 4 个进程,每个进程有自己的事件循环,进一步吃满多核 CPU。配合上 No.2 的 Redis 状态外置,多进程之间才能无障碍协作。
4. 判断 Agent 好不好用的五类量化指标
聊完架构和实现,回到最开始的问题:你的 Agent 到底好不好用?我的答案是:别凭感觉,用数据打分。我搭建这套评测体系,踩过不少坑,现在整理成五类指标,每类里挑最关键的几个讲,附带计算方法和我的建议阈值。
4.1 功能指标:任务完成率与工具调用准确率
任务完成率是最核心的指标,定义是:在测试集上,Agent 成功完成用户目标的比率。难点在于判定“什么算成功”。我采用两段式判定:先让 Agent 生成结果,再由另一个评测模型 + 规则校验共同判定。例如用户问“查一下订单 A10086 的物流状态并总结”,判定条件包含:正确调用了查物流工具、参数传了正确订单号、最终答案包含物流状态关键信息。
工具调用准确率是另一个硬指标,统计模型在测试中首次调用某个工具时,工具名和参数是否完全合法。注意我这里说的是“首次调用”,不是为了评测模型,而是为了反映模型的真实决策能力。如果首次调用准确率低于 80%,基本可以断定提示词里的工具描述写得不及格。
4.2 性能指标:端到端延迟与步数
端到端延迟就是用户从发出请求到收到完整回复经过的时间,我习惯看 P95 和 P99。一个 5 步以内的 Agent 任务,P95 建议控制在 15 秒以内。超过 25 秒用户基本就流失了。
步数指 Agent 完成一次任务实际执行的工具调用次数加 LLM 推理次数。用户问一句“明天的天气”,如果 Agent 跑了 6 步,那大概率是做了很多无用推理,虽然答案对了,但效率差。步数也直接关联 Token 消耗,所以是同时影响性能和成本的关键变量。我用一个统计口径:平均步数 = 总迭代次数 / 总任务数。行业里健康范围是 2 到 5 步,高于 6 要警惕死循环。
4.3 成本指标:单次调用成本与 Token 效率
成本是老板最关心的,也是团队最容易忽略的。我建议直接算“每完成 1000 个有效任务需要花多少钱”,这比看 Token 总数更直观。拆成两块:LLM 推理成本 + 工具执行成本。
以 GPT-4o 价格为例,一个 5 步 Agent 任务的输入输出 Token 总量大约在 4000 到 8000,折合人民币大概 0.2 到 0.5 元。如果业务客单价高,这成本可以接受;如果做的是免费 C 端工具,那必须用更便宜的模型做执行层,比如用国产旗舰模型承担简单推理,用强模型做最终整合。这个混合路由策略能省 60% 以上成本,我会在第五章评测实例里展示实现。
4.4 可维护性指标:可观测性与回归率
可观测性决定了你半夜两点接到告警后能不能在半小时内定位问题。我认为生产级 Agent 必须记录三类 Trace 日志:完整的思考轨迹(thought)、工具调用参数与返回值、运行时的每一步耗时。我在项目里用 JSON Lines 格式写入 Loki,查询界面长这样:
{"time": "2026-03-12T10:15:22Z", "run_id": "run_1024", "step": 1, "type": "think", "content": "需要查订单A10086物流状态"} {"time": "2026-03-12T10:15:24Z", "run_id": "run_1024", "step": 2, "type": "tool", "name": "query_logistics", "args": {"order_id": "A10086"}, "result": "已签收,签收人:张三"}回归率是评测里容易被忽视的指标。就是每次改完 Prompt 或工具描述后,老测试集上的任务完成率有没有下降。下降就是回归了。没有回归测试的 Agent 项目,就是每次改代码都在赌,上次能跑的任务这次大概率会破。
4.5 用户体验指标:拒绝率与人工修正率
拒绝率指 Agent 遇到不懂的问题时,如何应对。好的 Agent 应该是“我不确定,但我告诉你获取正确答案的路径”,而不是强行编一个。我允许 10% 以内的合理拒绝率,即明确告知无法回答并给出降级方案,这样反而提高信任度。
人工修正率指在人工介入的客服场景中,坐席需要修正 Agent 答案的比例。健康的数字是低于 20%。如果超过 30%,说明 Agent 的质量不足以支撑业务,硬推给用户是在砸口碑。这个指标在自动化运维、交易辅助等严肃场景尤其重要——宁可不答,不可错答,错了比不做更危险。
5. 评测落地:从搭评测集到定位问题的完整闭环
指标定了,怎么落地?我结合一个真实项目给你完整走一遍流程。这个项目是一个电商客服 Agent,用户问订单、退款、物流、发票相关问题,测试集我做了 80 条典型任务。
5.1 搭一个 20 条的迷你评测集
新手建议先从 20 条开始,别贪多。20 条能覆盖主要场景,手工标注也快,一天搞定。我当时的做法是,先列出业务已知的 8 大场景,例如“查物流”、“申请退款”、“修改地址”、“查发票”、“问优惠券”,每个场景写 2 到 3 条不同难度的问法。难度分三档:简单(直接问)、中等(带时间或条件)、困难(上下文复杂或隐含条件)。
评测集的文件格式我用 JSON 数组,每条包含 id、category、prompt、expected_tool、expected_params 和 note。expected_tool 和 expected_params 是人工标注的“标准答案”,用来做工具调用准确率的自动判定。例如:
[ { "id": "logistics_001", "category": "物流", "prompt": "帮我查一下订单号10086的物流情况", "expected_tool": "query_logistics", "expected_params": {"order_id": "10086"}, "note": "单参数,最容易,验证基础调度" }, { "id": "refund_003", "category": "退款", "prompt": "我上周买的那双鞋尺码不合适,能退吗?退款到哪?", "expected_tool": "check_refund_policy", "expected_params": {}, "note": "隐含商品信息,需要先查订单再查退款政策,两步任务" } ]5.2 用评测 runner 批量跑分
评测 runner 就是逐个把 prompt 塞给 Agent,然后计算各项指标。我自己写过一个简约版 runner,核心思路很直白:执行 20 条任务,逐步收集统计信息,最终输出 JSON 报告。这里把统计代码的关键部分贴出来:
# app/eval/runner.py import json from collections import Counter def evaluate_dataset(agent, dataset): stats = Counter() task_results = [] for case in dataset: state = {"task": case["prompt"], "messages": [], "iterations": 0} result = agent.invoke(state) success = result.get("final_answer") and len(result["final_answer"]) > 0 # 工具调用准确率判定:检查是否调用了期望工具,参数是否合法 tool_ok = result.get("last_tool_name") == case["expected_tool"] if tool_ok: # 参数级联校验,简化版只校验必须字段 args = result.get("last_tool_args", {}) for k, v in case["expected_params"].items(): if args.get(k) != v: tool_ok = False break stats["total"] += 1 stats["success"] += 1 if success else 0 stats["tool_ok"] += 1 if tool_ok else 0 stats["steps"] += result.get("iterations", 0) task_results.append({ "id": case["id"], "success": success, "tool_ok": tool_ok, "steps": result.get("iterations", 0), "final_answer": result.get("final_answer", ""), "trace": result.get("trace", []) }) report = { "task_completion_rate": stats["success"] / stats["total"], "tool_call_accuracy": stats["tool_ok"] / stats["total"], "avg_steps": stats["steps"] / stats["total"], "results": task_results } return report跑完 20 条任务后,你会拿到一个初始报告。假设我当时的场景第一轮结果:任务完成率 65%,工具调用准确率 70%,平均步数 7.5。这个成绩单放到哪个团队都不合格,但它给了一个基线,指引你去 Debug。
5.3 用 Trace 定位修复的闭环
拿到报告后,逐条看失败案例的 Trace,找出共性。我那次发现了三个高频问题:
第一类是物流查询,订单号传错。Trace 里显示模型把“10086”识别成数字 10086,工具期望字符串“10086”,传输时格式美化变成了“10086”。修复方式:工具参数 Schema 里给 order_id 加 pattern 和 description,写明“订单号是字符串,不要转成数字”。
第二类是退款类任务,Agent 没有先查订单就直接回答政策问题。它把“我上周买的那双鞋”理解成了泛泛的购物咨询。修复方式:在系统 Prompt 里增加业务规则——“当用户询问退款或售后时,必须先调用 query_recent_orders 获取 30 天内订单,再匹配退款政策”。
第三类是发票问题,Agent 经常绕路查了不必要的工具,导致平均步数 7.5 的罪魁祸首。修复方式:精简工具描述,把与发票不相关的工具描述从主 Prompt 里移到更深的层级,减少模型误判。这一招效果显著,平均步数一下子降到 3.8。
修复后重新跑同一份评测集,任务完成率提升到 90%,工具调用准确率 92%,平均步数 4.1。这就是“评测 → 定位 → 修复 → 回归”的闭环。没有评测集,你根本说不出“哪里不好”,更别说修。
6. 高频问题排查实录与避坑技巧
再好的架构也会遇到问题。我把这两年遇到的高频问题整理成了一份速查表,每一个都是花钱买来的教训。你按图索骥,能省下至少一周的抓瞎时间。
6.1 ReAct 死循环与重复动作
症状:日志里同一个工具被反复调用,或者 think 节点反复输出相似的 thinking 但没有实质进展。原因很复杂:模型陷入局部探索、Prompt 引导不足、工具返回信息导致模型重复尝试。
排查顺序:第一步看 Trace 里最近 5 步的动作,如果完全相同,直接判定为重复。第二步看工具返回的报错信息是否被正确喂给模型。第三步看 Prompt 里是否有限制“不要重复调用已经失败的工具”的指令。
我的修复组合拳是:设置最大迭代次数 6;对相同 tool_name + tool_args 连续出现 2 次则强制终止;在 Prompt 中增加“如果你已经尝试过某个工具且失败,请更换策略”这句话。别小看这一句,实测能将死循环率从 12% 降到 1% 以下。
6.2 工具调用参数格式混乱
症状:模型传参经常把时间写成“2026年3月12日”,工具却要 ISO 格式;订单号带着汉字后缀;金额单位忽大忽小。病根不是模型蠢,是工具描述不清晰。
正确做法是在工具函数的 docstring 和参数 Schema 里写得极其具体。我常用的模板:
# app/agent/tools.py from pydantic import BaseModel, Field class QueryLogisticsSchema(BaseModel): order_id: str = Field( ..., description="订单号,纯数字字符串,例如 '10086',不要转数字,不带 '订单' 等前缀", pattern=r"^\\d+$" ) class QueryLogisticsTool: name = "query_logistics" openai_schema = { "type": "function", "function": { "name": name, "description": "查询指定订单的物流状态。用户问物流、快递、送达时间时使用。", "parameters": QueryLogisticsSchema.model_json_schema() } } def execute(self, order_id: str): # 真正执行查询 return {"status": "delivered", "carrier": "顺丰"}事实就是,把 description 写详细,比你在 Prompt 里反复强调“注意参数格式”有效得多。模型是看工具说明来生成调用的,说明越清楚,出错越少。
6.3 RAG 检索效果差,Agent 越答越偏
很多 Agent 项目加载了 RAG,想让模型基于企业知识库回答。但经常遇到:检索回来的片段不相关、模型不引用检索结果、回答越来越胡扯。
排查方法:先单独测 RAG 检索质量。把用户 query 丢进向量检索,人工检查 Top5 结果的相关性。如果检索本身不准,Agent 再怎么调 Prompt 都没用。我在这类问题上的三招:切换更好的 Embedding 模型、给向量库加 metadata 过滤、在 Prompt 里增加指令——“只允许基于知识库内容回答,如果知识库没有相关信息,明确说明并拒绝回答”。
6.4 并发一涨就超时
症状:上线第一天 20 个用户并发,Agent 就开始报错,P95 延迟飙升。原因十有八九是同步执行、实例无状态化失败、或者 LLM API 的限流被打满。
排查顺序先看日志:有没有大量“OpenAI rate limit exceeded”报错?如果有,前排限流策略没做,或者单账号 QPS 超限。这时可以在代码里给 LLM 调用加滑动窗口限速,或者切换多 Key 轮询。再看 CPU 和内存:如果 CPU 打满,说明有阻塞调用,比如在 async 函数里用了 sync 的 SQLAlchemy。最后看 Redis 连接池:有没有报连接数耗尽。调大 Max Connections 或使用连接池复用。
6.5 上下文塞爆导致效果退化
症状:Agent 对话超过 10 轮后,回答开始答非所问,或者上下文超出窗口长度报错。原因是 messages 列表一直膨胀。
解决方案是三段式记忆管理:把最近 6 轮对话完整保留,把中间部分做摘要压缩,把长期事实细节存入外部向量库。压缩摘要可以用一次额外的 LLM 调用,每次对话轮数达到阈值时触发。这个策略我实测下来,能把上下文占用减少 70%,且端到端质量下降不超过 5%。
6.6 幻觉问题能不能“根治”
说起幻觉,直接给结论:不能完全根治,只能缓解。缓解手段分三层:第一层,检索增强,强制要求模型基于检索内容回答;第二层,输出校验,对关键断言用规则或工具验证,比如金额、日期、订单状态;第三层,置信度降级,模型自信度低时直接转人工或拒绝回答。
在客服 Agent 里,我设置了硬性规则:凡涉及退款金额、赔付金额,金额必须来自查询工具返回值,模型不得自行计算;模型生成的答案里有数字时,强制调用一个校验工具核对。这套机制上线后,金额类严重幻觉为零。
7. 谈谈这两年的实操感悟
写了这么多架构和代码,最后想聊点形而下的东西。这两年做 Agent 项目最大的体会是,这个领域没有灵丹妙药,也没有银弹。2026 年了,业界对 Agent 的“标准答案”正在收敛,收敛到几件朴素的事情上。
第一,能 Workflow 解决的事别硬上 Agent。Agent 的灵活是优势也是风险。用户需求稳定、路径固定时,写死流程性能更好、成本更低、还不会胡来。我接过的项目里,至少一半号称要上 Agent 的场景最终改成了 Workflow + 少量 LLM,效果反而更好。
第二,给 Agent 穿“紧身衣”。这里的紧身衣指约束:约束任务范围、约束工具数量、约束输出格式、约束动作空间。在一次上线前,我把 Agent 可用的工具从 12 个砍到 6 个,任务完成率从 82% 升到 93%。工具少而精,模型决策的负担小,出错率自然下降。
第三,部署不是终点,可观测性才是。我见过好几个团队 Agent 上线当天特别开心,第二天就被老板拉进会议室:“这个东西昨天出错了你们知道吗?”如果日志只记录最终答案,不记录思考轨迹和工具调用,你根本没法复盘。好的 Agent 系统,可用性是从日志的完整度开始的。
第四,架构选型上,Rust 核心 + Python 业务确实是 2026 年高端场景的一个值得尝试的方向。Rust 的并发模型和资源占用非常适合做高并发的调度层,Python 的生态用来接模型和工具。但我不建议小团队一上来就这么搞,它需要同时具备 Rust 和 Python 两边的人才。先从 FastAPI 单服务跑通,再按需演进,是最稳妥的路径。
最后分享一个长期主义的看法:AI Agent 的本质是在“模型能力”和“工程约束”之间找平衡。模型还不完美的阶段,工程约束是决定成败的最大变量。谁能把工具描述写得准确、把评测闭环建得扎实、把可观测性做得完备,谁就能在这个浮躁的赛道里真正把 Agent 做成一个“好用”的产品。希望这篇长文能帮你少走几步弯路,把自己的 Agent 从“能跑”推进到“好用”。