Agentic AI 跑通 Demo 容易,上线翻车才痛苦
聊《Agentic AI到底能不能干活?别只看 Demo 和跑分》之前,先说一句实在的:别急着背概念,先看它在真实项目里到底解决什么问题。
摘要
上周我带团队上线了一个内部 Agent 系统,负责自动处理工单分类和初步回复。Demo 阶段跑得很顺,模型生成准确率看着也不错。结果上线第三天,一个边界 case 触发了连锁调用——Agent 把"重置密码"和"账号申诉"当成了同一个任务,连续调了四个工具,还往不该发的邮箱发了不该发的内容。
事后复盘,问题不在模型能力,而在我们忽略了权限隔离、日志追踪和异常兜底。这也是为什么最近圈子里讨论的焦点从"Agent 有多聪明"转向了"Agent 怎么可靠地干活"。
目录
- Agentic 到底是什么
- 自主性的边界比想象中小
- 任务拆解比 Prompt 更难
- 可观测性:上线前的最后一道门槛
- 安全约束不是可选项
- 总结
Agentic 到底是什么
很多人一听到 Agentic AI 就联想到自主决策、自动执行。但真正区分"聊天机器人"和"Agent"的,不是能不能聊天,而是能不能在约束下持续做动作。
我的判断标准很朴素:一个系统能不能叫 Agent,看三个问题。
第一,它有没有工具调用能力。不是简单的 function calling,而是能根据上下文选择工具、组合工具、甚至动态生成新的工具调用序列。
第二,它有没有状态记忆。不是指把对话历史塞进 prompt,而是能在任务执行过程中维护一个可查询的状态,比如"用户已经完成了身份验证"或"当前工单处于等待审批阶段"。
第三,它有没有目标驱动的循环。聊天机器人是问答模式,一问一答。Agent 是循环模式:感知→规划→执行→观察→再规划。这个循环可以终止于目标达成,也可以终止于失败或超时。
# 一个最简单的 Agent 循环伪代码 while not goal_reached and not failed: observation = agent.perceive(state) plan = agent.plan(observation, memory) action = agent.execute(plan) result = agent.observe(action) memory.update(result) if is_safety_violation(action): escalate_to_human(action) break代码很简单,但生产环境里每一行都藏着坑。比如is_safety_violation怎么定义?escalate_to_human的接口谁来维护?memory的边界在哪?这些才是决定 Agent 能不能上线的关键。
自主性的边界比想象中小
我见过太多团队把 Agent 当成"全自动"来设计,结果上线就被现实打脸。
自主性不是越自由越好。真正的问题不是"Agent 能做什么",而是"Agent 不能做什么"。
我们的工单 Agent 最初被设计成可以自主决定工单优先级、分配处理人、甚至直接回复用户。结果上线第一天就出了事故:模型把"咨询类"工单当成了"投诉类",直接升级了优先级,还调用了"投诉处理"工具,触发了一连串不该发生的流程。
教训是:自主性必须分层。
我把 Agent 的自主性分为三个层级:
- L1 执行层:Agent 只能在预定义的参数范围内执行工具,不能修改工具的调用逻辑。比如查询订单状态可以自主决定,但修改订单信息必须人工确认。
- L2 规划层:Agent 可以自主规划工具调用序列,但关键节点需要人工审批。比如处理一个复杂工单,Agent 可以先规划三步操作,但在第二步执行前等待确认。
- L3 决策层:Agent 可以自主决策,但所有决策必须有可追溯的日志,并且可以事后审计。
我们最终把工单 Agent 定在 L1 层级,关键操作全部走人工审批。这不是模型能力不够,而是业务风险不允许。
任务拆解比 Prompt 更难
很多人以为 Agent 的核心是 Prompt 工程。实际上,任务拆解才是工程化的深水区。
一个复杂的任务,比如"处理用户投诉",拆解成 Agent 能理解的子任务并不简单。我见过两种失败的拆解方式:
第一种是拆得太细。把"处理投诉"拆成二十个子步骤,结果 Agent 在第二步就卡住了,因为某个子步骤需要的信息在第一步没有获取到。
第二种是拆得太粗。把"处理投诉"拆成"查询"、"判断"、"回复"三个步骤,结果 Agent 在"判断"这一步完全靠模型自由发挥,出现了各种不一致的判断逻辑。
正确的拆解应该满足三个条件:
- 可执行:每个子任务都有明确的工具或 API 可以完成
- 可组合:子任务之间有清晰的依赖关系,不会因为顺序错误导致状态混乱
- 可回滚:如果某个子任务失败,可以回退到上一个安全状态
# 任务拆解的依赖图示例 tasks = { "verify_identity": { "depends_on": [], "tools": ["auth_service.query_user", "sms_service.send_code"], "timeout": 30 }, "query_complaint": { "depends_on": ["verify_identity"], "tools": ["crm_service.get_complaints"], "timeout": 15 }, "classify_complaint": { "depends_on": ["query_complaint"], "tools": ["model_service.classify"], "timeout": 10 } }这个依赖图看起来简单,但在生产环境里,你需要考虑每个工具的超时、重试、降级策略,以及任务之间的状态一致性。这些才是任务拆解的真正难点。
可观测性:上线前的最后一道门槛
这是我踩坑最深的一个环节。
我们的 Agent 系统上线后,问题排查花了整整两天。原因很简单:日志不够细。
我们只记录了 Agent 的最终输出,没有记录中间的工具调用、状态变化和决策依据。当出现错误时,我们只能看到"Agent 输出了错误内容",却不知道是哪个环节出了问题。
可观测性不是加几个日志就完事的。我总结了一个最小可观测性清单:
- 工具调用日志:每次工具调用的输入、输出、耗时、错误信息
- 状态变化日志:Agent 内部状态的每一次变更,包括变更原因和触发条件
- 决策依据日志:Agent 做出某个决策时,依据了哪些上下文信息
- 异常链路日志:从异常发生到最终处理的全链路记录
# 工具调用日志示例 import logging logger = logging.getLogger("agent.tool_call") async def call_tool(tool_name: str, params: dict) -> dict: start_time = time.time() logger.info(f"Calling tool: {tool_name}, params: {params}") try: result = await execute_tool(tool_name, params) elapsed = time.time() - start_time logger.info(f"Tool {tool_name} succeeded in {elapsed:.2f}s, result: {result}") return result except Exception as e: elapsed = time.time() - start_time logger.error(f"Tool {tool_name} failed after {elapsed:.2f}s: {e}") raise这个日志看起来简单,但真正生产环境里,你需要考虑日志的采样率、存储成本、查询性能,以及敏感信息的脱敏处理。
安全约束不是可选项
最后说一个容易被忽视的问题:安全约束。
很多人把安全约束理解为"不让 Agent 做坏事"。但实际上,安全约束是 Agent 系统的基础设施,不是事后补的补丁。
我们的工单 Agent 上线后,安全团队提出了三个问题:
第一,Agent 有没有权限访问用户敏感数据?我们最初的方案是让 Agent 直接查询数据库,结果被安全团队叫停。后来改成通过 API 网关访问,所有查询都经过权限校验。
第二,Agent 的输出有没有经过审核?我们最初的方案是 Agent 直接回复用户,结果发现模型会生成一些不准确的建议。后来改成 Agent 生成草稿,人工审核后发送。
第三,Agent 的异常行为有没有兜底?我们最初的方案是设置超时和重试,结果发现模型会陷入死循环。后来加了一个最大步骤限制和异常检测机制。
安全约束的核心原则是:默认拒绝,最小权限,全程可审计。
# 安全约束示例 class AgentSecurityGuard: def __init__(self): self.max_steps = 10 self.sensitive_tools = {"modify_user_data", "send_email"} self.audit_logger = AuditLogger() async def before_tool_call(self, tool_name: str, params: dict): if tool_name in self.sensitive_tools: if not await self.check_permission(user_id, tool_name): raise PermissionError(f"Unauthorized tool: {tool_name}") self.audit_logger.log("before", tool_name, params) async def after_tool_call(self, tool_name: str, result: dict): self.audit_logger.log("after", tool_name, result) if self.is_abnormal(result): await self.escalate(tool_name, result)这个安全网关看起来增加了复杂度,但它是 Agent 系统上线的必要条件。没有安全约束的 Agent,就像没有刹车的车,跑得越快越危险。
总结
Agentic AI 从 Demo 到生产,最大的差距不在模型能力,而在工程化能力。
我见过太多团队把 Agent 当成"智能聊天机器人"来设计,结果上线就被权限、日志、异常处理等问题打回原形。真正能上线的 Agent 系统,需要满足三个条件:
- 有边界的自主性:明确知道 Agent 能做什么、不能做什么
- 可拆解的任务:把复杂任务拆成 Agent 能可靠执行的子任务
- 可观测的安全:全程记录、可追溯、有兜底
Demo 只是热身,权限、日志和可观测才是真正考验工程能力的地方。这也是为什么最近圈子里的讨论从"Agent 有多聪明"转向了"Agent 怎么可靠地干活"。
如果你正在做 Agent 项目,建议在上线前问自己三个问题:你的 Agent 出了错能不能快速定位?你的 Agent 越权了能不能及时拦截?你的 Agent 异常了能不能安全回滚?
这三个问题答不上来,就别急着上线。
资料展示
下面是我整理的AI大模型学习资料和工具包预览,适合收藏后按主题逐步学习。
如果你想看完整资料目录,可以在评论区留言「资料」;也欢迎告诉我你更关注AI大模型里的哪类内容。
