首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Demo 跑通那一下是假象:两年 Agent 开发攒下的五个真问题

Demo 跑通那一下是假象:两年 Agent 开发攒下的五个真问题

原创
作者头像
用户12770437
发布于 2026-09-25 10:03:22
发布于 2026-09-25 10:03:22
1430
举报

掘金作者"云边有个技术书屋"最近发了一篇复盘,标题很朴素:《做了近两年的 Agent 开发,其实真正要学的就是这五件事》。 他说的第一句话,我觉得做过的都懂:做 Agent 最有意思的时刻,通常是 Demo 刚跑通的那一下——模型理解了需求,自己选了工具,还给出了看起来不错的结果。 真正让人头疼的是第二个阶段。用户换一种问法,状态就丢了;工具返回一个含糊的错误,Agent 开始乱试;你改了提示词,一个场景好了,另一个场景坏了;上线第二天,账单和延迟一起超预期。 他把 Demo 和 Agent 系统之间的那层东西叫"工程化解决方案",并把真正难的部分归成五件事。这五件事,比任何框架都活得久。 一、上下文:难在状态会丢 他举的例子很典型。假设做一个"汽车门店销量助手",用户先问"帮我看看上海上周的销量",下一句又问"那杭州呢?" 人一听就懂:查询的还是销量,时间还是上周,只把城市换成杭州。但如果系统只把最后一句传给模型,模型不知道该查什么、更不知道时间范围。 大多数人的第一反应是往上下文里塞更多资料。短期有效,长期会引入三个问题:状态丢失(关键信息在历史里不在当前输入里)、状态冲突(系统限制查最近 30 天,历史里却躺着去年的数据)、重点稀释(工具返回、检索片段、执行日志全塞进去,模型反而找不到那条关键约束)。 他的结论是:Agent 的上下文不是聊天记录列表,而是一个随任务推进变化的运行时状态。正确做法类似 Java 里的领域对象——维护一个明确的查询状态,用户说"那杭州呢"只更新城市这一个字段,不要重建整个对象,也不要让模型随意覆盖所有字段。 一句话总结这节:程序维护状态,模型解析意图。 二、工具:难在把概率系统接到确定性接口上 工具调用看起来只是让模型调函数,麻烦全在失败场景里。比如模型调用 `querySales("魔都", lastWeek)`,系统可能遇到五种结果:城市名不标准、日期算错、结果为空、接口超时、用户没权限。 如果工具只返回一个字符串,模型分不清这五种情况,只能靠猜。 他的解法是按 Java 接口那样设计工具契约:返回一个带 `Status`(成功/空/参数错/无权限/超时)、`data`、`message`、`retryable`、`nextAction` 五个字段的结构体。城市名错的时候,返回值要写清楚"city 不是标准城市名、可重试、下一步请调用 resolveCity 把魔都解析成上海"。这样程序知道能不能重试,模型知道下一步干什么。 工具层还必须做三件事:参数在工具层强制校验;下单、发消息、删除这类操作带幂等键;只读、可逆写、不可逆写三类权限分级处理。 他把执行顺序也钉死了:先权限,再参数,再查询,最后处理空结果和异常。原话是那句糙理:"不要指望 Prompt 保证安全,接口必须能挡住错误。" 三、执行:难在 Agent 越跑越偏 没有边界的 Agent 会长这样:查上海销量 → 查杭州销量 → 发现杭州数据异常 → 跑去查库存 → 又查了一遍上海 → 宣布任务完成。用户只想比两个数,它顺手发散到库存还重复劳动。 解法不是让模型"更认真",而是给它一张有限任务图:明确意图、解析城市别名、查销量、对比、生成、验收六个节点,用状态机推进。再叠加预算:最多几次工具调用、最多几次解析、最多几次重试、总耗时上限。 最后由程序验收:结果里有没有上海和杭州、时间范围是不是上周、所有数字能不能对上工具返回的数据。"不要相信模型说完成"——第一次验收失败把原因交给模型修复,第二次降低任务范围,第三次转人工或直接返回失败原因。 四、评估:难在不知道错在哪一步 Agent 最后回答"杭州销量比上海高 18%",这个结论可能错在四个层:意图层(用户问门店销量,它查了城市总量)、工具层(只查了杭州)、数据层(上周日期算错)、生成层(数据是 8%,写成了 18%)。只看最终答案,你根本不知道哪一层坏了。 所以要分层评估,准备三类用例:意图用例(输入"那杭州呢?",期望动作是查销量、城市是杭州、周期是上周)、工具用例(模拟杭州接口超时,期望重试一次后返回部分结果,禁止编造销量)、结果用例(必须包含上海杭州上周销量,所有数字必须来自工具返回,空数据必须明说)。 同时把执行轨迹记下来:意图解析结果、调了哪个工具、参数是什么、工具返回什么状态、耗时多少、最终答案引用了哪些数据。他形容这是 Java 服务的调用链日志——没有 Trace,线上问题只能靠猜。 五、成本和延迟:难在路径会放大 用户只问一句"上海和杭州上周销量哪个更好",系统实际可能做了八件事:解析意图、解析城市别名、查上海、查杭州、杭州超时重试、组装上下文、生成总结、验收结果。全串行的话,等待时间就是所有步骤相加。 上海和杭州两个查询互不依赖,应该并行。再配四个手段:模型分级(分类用轻量模型,总结用强模型)、Prompt 缓存(稳定前缀放前面,变化内容放后面)、结果缓存(昨日销量不要每次重算)、硬预算。 他给的限额很具体:单任务最多 5 次工具调用、最多 2 次重试、最多 8 次模型调用、最长 15 秒,超预算就返回部分结果。 六、另一篇给出的两个抓手:Hooks 和 Checkpointer 如果我们把这五件事再往下落到实处,掘金作者"Setsuna_F_Seiei"在《前端转型 Agent 开发 05》里讲的两个机制,恰好是工程落地最实用的两只手。 Hooks 是实时介入的检查站。 在 LangGraph 里用 `createAgent` 配置 `preModelHook`(推理前)和 `postModelHook`(推理后)。它能干四件事:看 token 用量,超预算就停;对着那些不该自动执行的工具(删文件、执行命令、发邮件)在 `postModelHook` 里拦下来,用 `interrupt` 抛一个审批请求等用户批准;发现上下文快撑爆时触发摘要压缩;把每一步都记进日志。他特意叮嘱,用户点"拒绝"不等于中止 Agent,而是拦截这一次工具调用、注入一条拒绝消息,让 Agent 自己调整后面的行为。 Checkpointer 是存档点。 开发用内存版 `MemorySaver`,生产用 `SqliteSaver`,配上 `thread_id` 就能做到:进程崩了从最近的存档恢复;长任务可以断点续跑;不知道哪一步出错就回退重放;想试不同方案就从某个存档 fork 新分支。他提醒了一个很容易漏的点——Checkpoint 只存内部状态,不含外部改变,所以重放可能重复发邮件、重复扣款。生产上必须用 `toolCallId` 给所有有副作用的工具做幂等去重。 七、框架会变,这五个问题不会 把两篇放在一起,其实指向同一件事:Agent 的难点从来不在"能不能调用模型",而在"出问题之后你能不能知道它坏在哪、拦得住、回得去、兜得起底"。 LangChain、LangGraph、Spring AI、AgentScope 还是自研循环,解决的是调用模型、注册工具、组织消息的胶水层。而那些真正让 Demo 在生产环境里翻车的东西——参数校验、异常处理、幂等、事务、日志、测试、容量控制——跟写后端服务是一模一样的。 区别只有一个:Agent 的输入是自然语言,输出是概率。所以中间这层确定性设施,比过去任何一个时代都更值钱。 参考 · 掘金《做了近两年的Agent开发,其实真正要学的就是这五件事》https://juejin.cn/post/7688159506154209321 · 掘金《前端转型 Agent 开发 05 之 Agent Hooks 与 Checkpointer》https://juejin.cn/post/7687876412298805248

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档