
聊《Agent怎么学先做一个会暴露问题的真实项目》之前先说一句实在的别急着背概念先看它在真实项目里到底解决什么问题。摘要去年帮一个电商团队做Agent项目Demo阶段跑得很顺。模型能查库存、能改价格、能推订单业务方拍板说就这么上。结果上线第一周权限问题炸了三次。第一次是Agent擅自调了退款接口客服群里收到三条不合规的退款记录第二次是模型幻觉出的接口参数把订单状态改成了乱码第三次最离谱Agent在日志里留了用户的手机号明文被安全团队直接封了。事后复盘团队里懂Agent原理的人不多。工具调用谁都会调个OpenAPI的事。但权限边界在哪、日志怎么留、失败怎么恢复这些才是生产环境的硬门槛。这篇文章不想讲理论想从那次联调失败里把Agent的底层机制拆清楚顺便说说怎么避坑。---目录Agent的本质不是聊天机器人是执行系统规划能力模型会想但不一定想对工具调用调API谁都会关键是权限边界记忆系统上下文不是无限的也不是免费的失败恢复Demo能跑不代表能兜底权限和日志上线后的真正硬仗总结Agent不是模型调得好就行Agent的本质不是聊天机器人是执行系统很多人对Agent的理解还停留在能对话的机器人。这没错但不完整。Agent的核心是自主执行。它能感知环境、做出决策、调用工具、拿到结果、继续决策。这是一个闭环不是单次问答。我见过的最直观的区分方式聊天机器人用户问 → 模型答 → 结束 Agent用户问 → 模型分析 → 调用工具 → 拿到结果 → 再次分析 → 再次调用 → 输出最终答案这个区别看起来简单但直接影响架构设计。聊天机器人只需要一个模型接口Agent需要规划器 工具集 记忆系统 执行引擎四个模块协同工作。我们当时的项目规划器用的是ReAct模式工具集接了库存、订单、客服三个系统的API记忆系统用了简单的Redis缓存执行引擎是LangGraph写的状态机。Demo阶段这四个模块配合得还不错。但一上生产问题就出来了。---规划能力模型会想但不一定想对规划是Agent最容易被高估的能力。很多人以为把任务丢给大模型模型就会自动拆解、执行、验证。实际上模型只是在做概率预测它没有真正的推理能力。ReAct模式Reasoning Acting是目前最常用的规划框架思路很简单让模型在每次调用工具前先输出自己的思考过程。# ReAct模式的典型循环 while not finished: # 1. 模型根据当前状态生成思考 thought llm.generate(state, memory) # 2. 解析思考判断是否需要调用工具 if 工具调用 in thought: tool_name, params parse_tool_call(thought) result call_tool(tool_name, params) state.append(f工具{tool_name}返回: {result}) else: # 3. 模型直接输出最终答案 answer llm.generate_final(thought) finished True这个循环看起来简单但有几个坑第一个坑是工具参数校验。 模型生成的参数经常不符合接口要求。我们当时有一个订单查询接口要求order_id是16位数字模型经常生成类似订单12345这种带前缀的字符串。结果就是接口报错Agent卡在循环里出不来。解决办法很简单在调用工具前加一层参数校验。def validate_order_params(params): if not params.get(order_id, ).isdigit() or len(params[order_id]) ! 16: raise ValueError(f订单ID格式错误: {params.get(order_id)}) return True # 调用前校验 if tool_name query_order: validate_order_params(params) result call_tool(tool_name, params)第二个坑是规划深度。 模型不是无限推理的它有自己的思考预算。任务越复杂模型越容易在中间步骤迷路输出无意义的循环。我们的解决方案是限制最大步骤数超时直接返回错误。MAX_STEPS 10 step_count 0 while step_count MAX_STEPS: step_count 1 # ... 执行逻辑 ... else: return 任务执行步骤过多可能陷入循环第三个坑是规划不可观测。 这是最致命的。模型在思考什么调用什么工具为什么调用这些在Demo阶段没人关心。但生产环境出了问题你连排查路径都没有。我们后来给规划器加了一套日志import logging logger logging.getLogger(agent_planner) def log_planning_step(step, thought, tool_callNone, tool_resultNone): logger.info({ step: step, thought: thought, tool_call: tool_call, tool_result: tool_result, timestamp: datetime.now().isoformat() })这套日志后来成了排查问题的救命稻草。---工具调用调API谁都会关键是权限边界工具调用是Agent最显性的能力也是问题最多的地方。我们的Agent接了三个系统库存系统、订单系统、客服系统。每个系统有不同的权限级别。库存查询是只读订单修改需要审批客服系统有敏感数据。Demo阶段我们用同一个Token调用所有接口没区分权限。上线后安全团队要求按角色分配Token。这时候问题来了Agent不知道该用什么Token。模型没有权限意识它只知道我要调用这个工具。但工具调用背后是真实的业务权限不同操作需要不同级别的授权。我们当时的解决方案是在工具层做权限拦截而不是让模型自己判断。class ToolWithPermission: def __init__(self, tool, required_permission): self.tool tool self.required_permission required_permission def call(self, user_id, params): # 检查用户是否有该权限 if not check_permission(user_id, self.required_permission): raise PermissionError(f用户{user_id}无权限执行{self.required_permission}) # 记录操作日志 log_operation(user_id, self.tool.name, params) # 调用实际工具 return self.tool.call(params) # 注册工具时指定权限 tools { query_inventory: ToolWithPermission(inventory_api, READ), update_order: ToolWithPermission(order_api, WRITE), refund_order: ToolWithPermission(refund_api, ADMIN), }这样即使模型想调用退款接口没有ADMIN权限的用户也调不了。另一个问题是工具调用的结果处理。 模型生成的参数可能有问题接口可能返回错误网络可能超时。这些情况Agent怎么应对我们当时没有做失败处理结果Agent在遇到接口错误时直接卡死反复调用同一个失败的接口。后来加了重试和错误处理def call_tool_with_retry(tool_name, params, max_retries3): for attempt in range(max_retries): try: result call_tool(tool_name, params) return {success: True, result: result} except Exception as e: if attempt max_retries - 1: return {success: False, error: str(e)} time.sleep(2 ** attempt) # 指数退避---记忆系统上下文不是无限的也不是免费的记忆是Agent区别于普通聊天机器人的关键能力。没有记忆的Agent每次对话都是全新的。它不知道之前说过什么做过什么。这对于单次问答没问题但对于需要多步协作的任务记忆是必须的。我们当时的记忆系统很简单用Redis存一个列表记录最近的对话历史。class SimpleMemory: def __init__(self, max_length20): self.max_length max_length self.history [] def add(self, message): self.history.append(message) if len(self.history) self.max_length: self.history.pop(0) def get_context(self): return \n.join(self.history)这个方案在Demo阶段够用但有几个问题第一个问题是敏感信息泄露。 我们的对话历史里经常包含用户手机号、订单号等敏感信息。Redis里的数据没有加密一旦被攻击者获取后果严重。第二个问题是记忆丢失。 Redis是内存存储重启就没了。如果Agent在执行过程中服务重启所有记忆都丢失任务必须从头开始。第三个问题是记忆成本。 对话历史越长Token消耗越大调用成本越高。而且模型对长上下文的注意力会下降输出质量会变差。后来我们做了三个改进1. 敏感信息脱敏在存入记忆前用正则替换手机号、身份证等敏感信息。2. 持久化存储把记忆存到数据库重启不丢失。3. 记忆压缩定期用模型对长历史做摘要压缩成简短的记忆点。def compress_memory(self, history): 用模型压缩历史保留关键信息 prompt f 请将以下对话历史压缩成关键记忆点保留重要信息和决策依据 {history} 输出格式 1. 关键事实 2. 已做出的决策 3. 待处理的任务 compressed llm.generate(prompt) return compressed---失败恢复Demo能跑不代表能兜底这是这次联调失败后我印象最深刻的部分。Demo阶段所有场景都是精心设计的成功路径。模型回答正确工具调用成功结果符合预期。没有人会测试失败场景。但生产环境里失败是常态。我们的Agent遇到过这些失败模型输出格式错误解析失败工具调用超时结果拿不到工具返回错误Agent不知道怎么办用户中途改变需求Agent还在按原计划执行每一种失败Agent都需要有应对策略。我们当时没有做失败恢复结果每次出错Agent就卡死或者乱跑。后来我们设计了三种失败恢复策略策略一重试。 对于网络超时、接口临时错误直接重试。def retry_on_transient_error(func, max_retries3): for attempt in range(max_retries): try: return func() except TransientError as e: if attempt max_retries - 1: raise time.sleep(2 ** attempt)策略二降级。 对于工具调用失败提供备选方案。比如库存查询失败可以降级为提示用户稍后重试。策略三人工介入。 对于无法自动恢复的失败记录日志通知人工处理。def handle_unrecoverable_error(error, context): logger.error(fAgent执行失败需要人工介入: {error}) logger.error(f失败上下文: {context}) # 发送告警 send_alert(fAgent执行失败: {error}) # 返回友好提示 return 任务执行遇到问题已通知人工处理请稍后再试---权限和日志上线后的真正硬仗回到开头说的那个项目。联调失败三次原因各不相同但追根溯源都是权限和日志的问题。权限问题模型不知道哪些操作需要审批哪些操作可以直接执行。我们后来在工具层加了权限拦截才解决了这个问题。日志问题模型思考的过程没有记录出了问题只能看结果不知道中间发生了什么。我们后来给规划器加了详细日志排查效率提升了一个数量级。可观测性问题Agent的执行过程是一个黑盒不知道当前状态、不知道下一步要做什么。我们后来加了执行状态追踪每个步骤都有明确的标记。class ExecutionTracer: def __init__(self): self.steps [] def start_step(self, step_name, paramsNone): self.steps.append({ name: step_name, params: params, status: running, start_time: datetime.now() }) def end_step(self, successTrue, resultNone): if self.steps: last_step self.steps[-1] last_step[status] success if success else failed last_step[result] result last_step[end_time] datetime.now() last_step[duration] ( last_step[end_time] - last_step[start_time] ).total_seconds() def get_trace(self): return self.steps有了这套追踪我们可以清楚地看到Agent每一步在做什么、花了多长时间、结果是什么。出了问题直接看日志不用猜。---总结Agent不是模型调得好就行这篇复盘想说的就一句话Agent的难点不在模型在工程。工具调用、记忆系统、任务规划这些是Agent的三大核心能力。但Demo能跑不代表生产能用。权限边界、日志追踪、失败恢复这些才是上线后的真正硬仗。如果你正在做Agent项目我有几个建议1. 权限控制要在工具层做不要依赖模型。 模型没有权限意识你需要在调用工具前做权限校验。2. 日志要记录模型的思考过程不只是结果。 出了问题你需要知道模型为什么这么做。3. 失败恢复要有预案不要指望模型自己处理。 模型会犯错你要为常见错误准备好应对策略。4. 可观测性要从一开始就设计不要上线后补。 Agent的执行过程是黑盒你需要让它变成透明。Demo能跑只是第一步。能让Agent在生产环境稳定运行才是真本事。资料展示下面是我整理的AI大模型学习资料和工具包预览适合收藏后按主题逐步学习。如果你想看完整资料目录可以在评论区留言「资料」也欢迎告诉我你更关注AI大模型里的哪类内容。