最近在国内外技术社区里,总能看到一个争议很大的问题:Agentic Programming 到底是不是一个“Flop(失败/泡沫)”?
有人觉得 Agentic AI 是下一代开发范式,是打破传统“输入—处理—输出”固化逻辑的新方向;也有人觉得它不过是“调大模型 API + 写了一堆 if-else”,Demo 看着热闹,真正上生产就崩,甚至不如普通 RAG 稳定。
本文不打算站队,而是从工程角度把这个问题拆开:先厘清 Agentic Programming 到底是什么,再看看当前被吐槽“Flop”的核心原因,然后结合一个 Agentic RAG 的落地案例,聊聊如何用工程手段把“不稳定”控制在可接受范围内,最后给出一套适合新手入门的路线和场景决策表。
目录:
1. 背景与核心概念
1.1 Agentic Programming 到底是什么
Agentic Programming 不是一门新语言,也不是一个新的开发框架,而是一种编程范式的转变。
传统编程中,开发者会把一个任务拆成明确的函数调用链:A() -> B() -> C(),每一步做什么、参数是什么、返回什么都是确定的。这种范式在业务逻辑清晰、输入输出可控的场景下非常高效。
但到了大模型时代,很多任务的输入是“模糊的自然语言”,输出没有固定结构,甚至“目标”本身都需要模型来理解。这时候,传统编程就不好使了。Agentic Programming 的核心思路是:你不再直接写死每一步怎么做,而是定义好目标、工具、约束和边界,让模型在运行过程中动态规划下一步做什么。
一个典型的 Agentic 系统通常包含:
- 一个 LLM 作为“大脑”,负责理解和规划。
- 一组工具(Tool),比如搜索、数据库查询、代码执行、HTTP 请求。
- 一个执行循环,模型根据当前状态决定调用哪个工具,然后观察结果,再决定下一步。
- 可选的内存模块,用于记录对话历史或任务状态。
所以 Agentic Programming 不是“凭空自动写代码”,而是“把决策权交给模型,开发者负责搭建可控的执行环境”。
1.2 为什么会有人问“Is Agentic a Flop”
先说结论:Agentic Programming 并没有真正失败,但当前确实处于“期望膨胀期到落地阵痛期”的过渡阶段。
之所以大家质疑它,主要有几个很现实的原因:
- 大多数 Agent 项目停留在 Demo 阶段,跑通一个完整业务并长期稳定运行的项目非常少。
- Agent 的行为具有不确定性,同样的输入,可能前一次成功、后一次失败,这在传统工程里是灾难级的缺陷。
- 成本不可控,多轮规划、多次工具调用,每一轮都是 Token 消耗,线上账单容易失控。
- 可观测性差,传统代码一行日志就能定位问题,而 Agent 的问题经常发生在多轮推理中,排查难度成倍增加。
说白了,大家反感的不是“Agentic 这个方向”,而是“只展示能力、不解决工程问题的玩法”。
1.3 Agentic 编程与传统编程的核心区别
| 维度 | 传统编程 | Agentic 编程 |
|---|---|---|
| 控制方式 | 开发者写死控制流 | 模型动态规划控制流 |
| 容错能力 | 异常可以精确捕获处理 | 需要设计恢复机制,错误比较隐蔽 |
| 可测试性 | 单测、集成测试成熟 | 需要额外的评估集和轨迹评测 |
| 成本 | 计算资源相对固定 | 与 Token 消耗、工具调用次数强相关 |
| 适用场景 | 逻辑明确、输入结构化 | 任务开放、需要跨工具协调 |
需要强调的是,两者不是替代关系,而是互补关系。一个成熟系统往往是用传统代码搭建骨架,在需要灵活决策的地方引入 Agentic 能力。
2. 为什么当前 Agentic 项目容易“翻车”
2.1 不可重复性与“幻觉”被放大
传统程序是确定性的,同一个输入必然得到同一个输出。Agent 则不同,模型每次生成的概率不同,加上多轮规划,失败会被逐步放大。
比如一个 Agent 任务:查询用户订单状态,如果异常则发邮件通知。它可能在第一轮正确调用了订单查询工具,但在第二轮解读结果时出现“幻觉”,错误地判断为“订单不存在”,然后走完了后续流程。这种错误在传统代码里是不会出现的。
应对思路是把“关键判断点”抽出来,做显式校验。比如模型判断“订单不存在”时,如果原始工具返回的是“网络超时”,就不应该直接接受模型的结论,而应该让 Agent 进入重试分支。
2.2 评估缺失
很多人觉得 Agent 写好了就是好的,但“跑通了”和“跑得好”是两个概念。传统代码可以用单元测试覆盖,Agent 则需要一个评测集,里面包含不同难度的任务、预期路径、期望结果。
如果没有评测集,你根本无法回答“我的 Agent 这次改动是变好了还是变坏了”。这也是 Agentic 项目早期最容易踩的坑。
2.3 成本与延迟失控
一个复杂任务可能要调用 5~10 次 LLM,每次几千 Token,算下来一次请求的成本是传统 API 调用的几十倍。如果 Agent 还在错误路径上循环,成本就更高。
延迟也一样,多轮串行调用会让用户感觉“卡了很久”。实践中需要限制最大步数、配置超时,以及把简单的流程直接做成固定代码,而不是交给 Agent 去“思考”。
2.4 工具层不稳定
Agent 能力再强,也要依赖底层工具。工具本身的返回值格式变化、接口超时、权限不足,都会让 Agent 走入“死胡同”。
比如你给 Agent 接了一个数据库查询工具,结果这个工具有时候返回[{"id":1}],有时候直接抛异常,Agent 很难从这种不一致中恢复。所以工具层的规范同样重要,需要有一个稳定的“工具封装层”,对上游返回做归一化。
3. 从“能跑”到“可控”:一个 Agentic RAG 的工程化实战
下面我们用一个 Agentic RAG 作为案例,看看怎么在工程上让 Agentic 系统更可控。
3.1 先理解 Agentic RAG 和传统 RAG 的区别
传统 RAG 是“检索—生成”的固定两步走:
- 用户提问
- 向量检索 TopK 文档
- 将文档拼进 Prompt,让 LLM 生成回答
这种方式实现简单,但问题也明显:它不会判断“当前问题是否需要检索”,也不会自动处理多跳问题。比如用户问“去年 A 项目负责人现在负责什么项目”,需要先查 A 项目的负责人,再查该负责人的当前项目,传统 RAG 做不了这种多步推理。
Agentic RAG 则在传统 RAG 外面套了一个“规划层”:
- 模型先判断问题是否需要检索,还是直接回答。
- 如果需要检索,再决定是查向量库、查结构化数据库,还是先执行一次工具调用。
- 每一步的结果都会被观察,然后决定继续还是终止。
这样就可以根据问题动态切换检索策略,甚至把多个工具串联起来。
3.2 场景设计
我们设计一个最小可用的 Agentic RAG 场景:
- 用户输入一个问题。
- Agent 判断问题是否需要检索。
- 如果需要,Agent 调用“文档检索工具”。
- 如果文档检索结果不足,Agent 还可以调用“网络搜索工具”(这里用 mock 数据代替)。
- 最终根据所有证据生成回答。
为了不让示例过于复杂,我们用 Python 实现一个简化版 Agent 循环。
3.3 代码:一个极简 Agent 执行循环
下面的代码演示 Agent 的核心循环,不依赖任何特定 Agent 框架,只使用大模型的chat/completions接口(这里用 OpenAI 风格的接口示意,实际需要按你的模型服务调整)。
# agent_loop.py # 一个极简 Agent 执行循环,思路演示 import json from openai import OpenAI client = OpenAI() # 按你的环境设置 base_url 和 api_key TOOLS = [ { "type": "function", "function": { "name": "retrieve_docs", "description": "从内部文档库检索与问题相关的资料", "parameters": { "type": "object", "properties": { "query": {"type": "string", "description": "检索关键词"} }, "required": ["query"] } } }, { "type": "function", "function": { "name": "web_search", "description": "搜索公开网络信息,作为补充证据", "parameters": { "type": "object", "properties": { "query": {"type": "string", "description": "搜索关键词"} }, "required": ["query"] } } } ] def retrieve_docs(query: str) -> str: # 实际项目中这里会调用向量数据库 mock_docs = { "项目": "Agentic RAG 项目于 2025 年启动,目标是实现动态检索。", "负责人": "当前负责人是张三。", } result = [v for k, v in mock_docs.items() if k in query] return "\n".join(result) if result else "未找到内部文档。" def web_search(query: str) -> str: # 实际项目中这里会调用搜索 API,此处用 mock 数据 return "公开信息:Agentic RAG 是检索增强生成与 Agent 决策能力的结合。" def run_tool(tool_name: str, args: dict) -> str: if tool_name == "retrieve_docs": return retrieve_docs(args["query"]) if tool_name == "web_search": return web_search(args["query"]) return "未知工具" def agent_run(user_input: str, max_steps: int = 5) -> str: messages = [{"role": "user", "content": user_input}] step_count = 0 while step_count < max_steps: response = client.chat.completions.create( model="gpt-4o-mini", # 按实际模型调整 messages=messages, tools=TOOLS, tool_choice="auto", ) message = response.choices[0].message messages.append(message) # 如果模型没有要求调用工具,说明可以输出最终结果 if not message.tool_calls: return message.content # 执行工具调用 for tool_call in message.tool_calls: tool_name = tool_call.function.name args = json.loads(tool_call.function.arguments) print(f"[Step {step_count}] 调用工具: {tool_name}, 参数: {args}") observation = run_tool(tool_name, args) print(f"[Step {step_count}] 工具返回: {observation[:100]}") messages.append({ "role": "tool", "tool_call_id": tool_call.id, "content": observation, }) step_count += 1 return "已达到最大步数,停止执行。" if __name__ == "__main__": result = agent_run("请帮我查一下 Agentic RAG 项目的负责人是谁?") print("最终回答:", result)这段代码里最关键的是while循环:
- 将用户输入和工具返回结果都追加到
messages。 - 每次让模型判断是调用工具还是直接结束。
- 如果调用工具,就执行
run_tool并把结果返回给模型。 - 设置
max_steps,防止模型无限循环。
在真实项目中,通常不建议自己手写循环,而是使用 LangChain、LangGraph、Dify 等项目,它们的核心价值是已经帮你处理了状态管理、工具调用和错误处理,但上面的思路是通用的。
3.4 代码:工具层的返回值归一化
工具返回不统一,是 Agent 踩坑的高频原因。下面这个示例展示如何用标准结构包装工具输出:
# tool_wrapper.py from dataclasses import dataclass from typing import Any @dataclass class ToolResult: success: bool data: Any error: str = "" def wrapped_retrieve_docs(query: str) -> ToolResult: try: docs = retrieve_docs(query) if not docs: return ToolResult(success=False, data=None, error="检索结果为空") return ToolResult(success=True, data=docs) except Exception as e: return ToolResult(success=False, data=None, error=str(e)) def run_tool_with_unified_result(tool_name: str, args: dict) -> ToolResult: if tool_name == "retrieve_docs": return wrapped_retrieve_docs(args["query"]) # 其他工具类似 return ToolResult(success=False, data=None, error="未知工具")为什么这很重要?因为当工具返回结构统一之后,你可以把success、error拼进 Prompt,让模型知道“这次调用失败了,要不要换一个方式”,而不是让模型对着一段莫名其妙的报错信息瞎猜。
归一化之后,Agent 的系统提示词中可以增加一条约束:
如果工具调用失败,请阅读 error 字段,并尝试换一个关键词重试,最多重试一次;若仍然失败,则明确告知用户无法完成该请求。3.5 代码:记录执行轨迹和基础评估
可观测性,是 Agentic 系统落地的基本功。下面用一个极简例子,记录每一步的输入输出:
# trace_and_eval.py import json import uuid import time from collections import defaultdict class AgentTracer: def __init__(self): self.records = [] def record_step(self, step_type: str, content: dict): self.records.append({ "time": time.time(), "step_type": step_type, "content": content, }) def save(self, path: str = "agent_trace.json"): with open(path, "w", encoding="utf-8") as f: json.dump(self.records, f, ensure_ascii=False, indent=2) # 使用示例 tracer = AgentTracer() tracer.record_step("llm", {"role": "assistant", "content": "需要检索"}) tracer.record_step("tool", {"tool": "retrieve_docs", "args": {"query": "项目"}}) tracer.record_step("result", {"content": "Agentic RAG 项目于 2025 年启动"}) tracer.save()评估层面的核心思路是:准备 20~50 条典型问题,每条标注“期望的关键步骤”和“期望答案”,然后运行 Agent,检查关键步骤是否被覆盖。
下面是一个简化评估函数:
# simple_eval.py def evaluate_agent(agent_fn, test_cases: list[dict]) -> dict: correct = 0 for case in test_cases: result = agent_fn(case["input"]) # 这里用最朴素的判断:期望关键词是否出现在结果中 if all(keyword in result for keyword in case["expected_keywords"]): correct += 1 total = len(test_cases) return { "accuracy": correct / total if total else 0, "correct": correct, "total": total, } test_cases = [ {"input": "Agentic RAG 项目的负责人是谁?", "expected_keywords": ["张三"]}, {"input": "什么是 Agentic RAG?", "expected_keywords": ["检索增强生成"]}, ] print(evaluate_agent(agent_run, test_cases))当然,真实项目里的评估会更复杂,需要评估工具调用是否合理、步骤是否冗余、最终结果是否忠实于证据。但核心思想是不变的:先定指标,再跑回归,再迭代。
4. Agentic 编程落地时的高频问题与排查思路
以下问题来自真实项目里常见的“Flop”现场。
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| Agent 陷入无限循环,反复调用同一个工具 | 没有设置最大步数或超时 | 在循环中增加max_steps,并配置请求超时 |
| 工具调用参数格式错误 | 模型生成的 JSON 参数不规范 | 在工具 API 侧做 JSON 解析保护,失败时返回结构化错误 |
| 回答结果出现事实性错误 | 模型过度依赖自身记忆,忽略检索结果 | 在 Prompt 中强调“只能基于工具返回内容回答” |
| 多个 Agent 任务间互相干扰 | 全局共享上下文 | 每个任务使用独立状态和消息列表 |
| Token 成本飞涨 | 多轮调用、每次注入大量历史消息 | 设置上下文裁剪策略,只保留最近 N 轮和关键结果 |
| 线上行为与本地不一致 | 随机采样参数设置不一致 | 固定temperature、seed,并记录实际调用参数 |
排查建议按以下顺序:
- 先看 Trace,确认 Agent 每一步到底调了什么工具、模型输出了什么。
- 再复现 Prompt,用相同消息历史直接调 LLM,判断是模型决策问题还是工具问题。
- 如果是决策问题,修改 Prompt 或增加结构化约束。
- 如果是工具问题,先在工具层修复,而不是让 Agent 去“适应”错误。
- 最后跑一遍评测集,确认改动没有让其他场景退化。
5. 最佳实践:如何避免 Agentic 项目变成“Flop”
5.1 能确定的部分,不要交给 Agent
这是最重要的一条。
Agent 适合处理“步骤不固定、需要动态判断”的部分。如果是固定流程,比如“收到订单 -> 校验金额 -> 扣库存 -> 发通知”,直接用传统代码写死就好。Agent 的灵活性在这里反而是负担。
一个合理的系统设计是:
- 传统代码负责稳定流程。
- Agent 只负责“判断下一步走哪个分支”。
- 分支内部仍然是确定性的函数调用。
5.2 让 Agent 学会说“做不到”
很多 Agent 项目失败,是因为模型在工具返回不充分时,仍然硬着头皮编答案。
在系统提示词中加入约束:
如果你没有找到足够的信息来回答用户,请直接回复“根据当前可用的信息,我无法回答该问题”,不要猜测或编造。这句话看起来简单,但实际上能大幅减少幻觉。因为模型知道“承认不知道”是合法的输出,就不会为了完成任务而去虚构信息。
5.3 控制上下文长度和成本
每次工具调用后,把完整历史都塞给模型,很快就把 Token 打爆。建议在每轮调用前做上下文裁剪:
- 移除已经过时的中间推理。
- 只保留“用户问题、最新工具结果、最终结论”。
- 长文档使用摘要或检索片段,而非原文传输。
5.4 安全与权限边界不能省
Agent 可能根据模型决策去调用危险工具。比如一个具备数据库写入能力的 Agent,一旦被提示词注入攻击,可能导致数据被修改。
安全建议:
- Agent 执行敏感操作前,必须经过人工确认。
- 工具层做好白名单,Agent 只能调用预先定义好的函数。
- 所有权限遵循最小权限原则,不要给 Agent 一个“万能数据库管理账号”。
- 对 Agent 的输入输出做敏感信息过滤。
5.5 建立评测集并持续回归
没有评测集的 Agent 项目,就像没有测试用例的 Web 项目,上线全靠感觉。
评测集至少包含:
- 正常问题。
- 需要多步工具调用的问题。
- 工具返回空结果的问题。
- 含有误导信息的问题。
- 模型应该“拒答”的问题。
修改一次 Prompt 后,跑一遍评测集,效果不下降再发布。
6. 哪些场景适合 Agentic,哪些场景不适合
| 场景类型 | 适合 Agentic? | 原因 |
|---|---|---|
| 文档问答(单跳) | 传统 RAG 就够了 | 不需要动态规划,固定流程稳定性更高 |
| 多跳问答、跨系统任务 | 适合 | 需要动态判断下一步查什么数据 |
| 客户工单自动分类和初步回复 | 适合 | 类型多变,需要模型灵活决策 |
| 固定报表生成 | 不适合 | 流程固定,传统代码更可控 |
| 数据库智能运维 | 高风险,需谨慎 | Agent 决策可能触发危险操作,必须有防护 |
| 代码自动修复 | 适合辅助场景 | 可以自动定位问题,但合入代码需人工审核 |
| 实时低延迟接口 | 不适合 | 多轮推理延迟不可控 |
这个表可以作为选型参考:如果任务包含多个工具、多个步骤,且步骤顺序不固定,Agent 才有价值;如果任务是一条直线走到底,别硬上 Agentic。
7. 下一步怎么学
如果你刚接触 Agentic 方向,建议按下面的顺序推进:
- 先理解大模型函数调用(Function Calling)的原理,这是 Agent 的基础能力。
- 手写一个最小 Agent 循环,跑通“模型选工具 -> 执行工具 -> 模型总结”的流程。
- 学习一个成熟编排框架,比如 LangGraph,理解状态图、节点、边、条件分支的概念。
- 做一个 Agentic RAG 项目,把检索、路由、多跳对话串起来。
- 加上 Trace 和 Eval,建立评测集,迭代两轮 Prompt。
- 再考虑生产化:超时、限流、缓存、权限、日志、监控。
Agentic Programming 不是一个马上能交付所有业务需求的技术,但它确实为“开放任务自动化”打开了一个新方向。与其争论它是不是 Flop,不如实际跑一个场景,用工程手段把不确定性控制住。真正被淘汰的,永远是只会写 Demo、不考虑稳定性、安全性和成本的人,而不是“Agent”这个方向本身。
如果这篇文章对你有帮助,建议先收藏,等你自己动手做 Agent 项目时,再回来对照排查表和实践建议。你目前在学 Agentic 的哪个阶段?遇到过什么翻车现场?欢迎在评论区交流。