尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Agent自动化工作流设计:从固定脚本到智能动态执行的技术实践

Agent自动化工作流设计:从固定脚本到智能动态执行的技术实践 这一章聊的案例三是我自动化工作流系列里最“像人”的一题自动化工作流 Agent。前两题还在教怎么把固定任务用脚本编排到这一题任务的输入会变、规则会变、甚至目标都可能中途调整固定脚本完全扛不住。Agent 的意义就在这里它让机器不再按照你写死的步骤执行而是由大模型根据目标、上下文、可用工具动态规划行动自己拆任务、自己调接口、自己在出错后重试。对正在做 Agent 开发或者想把日常工作流从“定期执行脚本”升级成“智能助理”的人来说这个案例能提供一个非常具体的落地样板。1. 案例三背后的设计思路为什么固定流程撑不住了1.1 固定流程自动化的天花板先说一个我自己的例子。早几年做竞品信息采集我用定时脚本爬固定网站每天把结果写进数据库。刚开始一切正常后来目标站点一个改版页面结构全变我下班回家看到一条告警第二天早上来修。这种工作重复多了之后你会意识到一个问题稳定运行的脚本才是少数真正稳定的是需求变化本身。你花大量时间维护选择器和异常分支其实是在不断补丁一个跟随外部世界变化的固定路径。Agent 的思路完全不同。它不维护“抓取 A 网站的第几行”而是维护“找最近一周内有价值的竞品动态”这样一个目标再基于当前网络内容、搜索结果、正文质量自己选择路径。模型看到的上下文变了行为也跟着变所以抗变化能力强很多。当然这不是说传统脚本完全无用。如果流程完全固定、量巨大且成本敏感脚本依然是最优解。Agent 适合的是“半固定半变化”的场景既有规则约束又需要临场判断的输出。这正好是自动化工作流 Agent 的典型适用区间。1.2 案例三的目标与最小闭环案例三我定的目标是输入一个业务关键词和输出格式Agent 自动完成信息搜集、筛选、结构化、生成 Markdown 报告并推送至指定通道。这句话看起来简单背后其实说明了案例的验收标准结果必须是可阅读的 Markdown 文件必须包含来源链接关键数据必须有时间戳。这些硬性约束能防止 Agent 把任务做得“看起来很对”。最小闭环我控制在五个动作搜索、读取、提取、生成、通知。前三个是基础信息能力第四个是组织能力第五个是对外动作。为什么选择这五个因为任何一个知识型工作流都能拆成这五类熟练之后再抽象成通用模板后面接新案例只需要改提示词和工具清单不用重新设计整套流程。1.3 明确边界自动与人工的界线很多项目第一版就想让 Agent 全自动完成所有步骤我建议别这么干。案例里我把“通知”设成可审批动作Agent 生成的内容先进草稿箱再由事件触发决定是否发送。表面上牺牲了一点自动化程度实际上换回了操作信心。你可以在一条规则里放开达到某个置信度阈值就自动发送否则等人工。这种分级授权比一刀切安全得多。这里顺便回答热词里的“agent scope”。我理解的 Agent 作用域不是越大越好而是越清晰越好。给 Agent 限定工具清单、网络范围、数据源范围它才能把有限上下文用在正确的判断上。案例三的 Agent 只允许访问指定的搜索 API 和网站列表不开放数据库删除权限这既是安全要求也是质量要求。2. 工具选型与 Agent 架构拆解2.1 Agent 框架、编排层和 Agent 外壳Agent 本体是循环决策算法。模型每次读入当前状态决定下一步动作执行后把结果写回状态再进入下一轮。算法本身不长难的是外界环境怎么接入。热词里常见的问题“harness 和 agent 区别”就是在问这件事。Harness 指的是 Agent 运行时要依赖的外壳环境变量、沙箱、文件系统、工具装载、权限策略、日志收集。它不是一个算法而是一个执行平台。框架则更靠近业务编排负责状态转移、断点续跑、人工审批、并行分支。打个比方Agent 是驾驶员决策框架是导航系统Harness 是车子本身。三者容易混但选型时逻辑完全不同。我在案例里选了 LangGraph 作为编排层不是因为它花哨而是因为它的 checkpointer 和状态持久化很成熟中途挂了能恢复现场。团队如果用 JavaSpring AI 的 Agent 支持也在变好用 Rust 走 Tokio 并发写核心运行器是一个越高吞吐越有价值的方向。社区里讨论的 Hermes Agent 这类第三方工作台本质上也是把 Agent、Harness、记忆管理打包成一个独立服务方便接进不同工作流。2.2 选型思考语言栈、持久化、审批没有万能框架我是按团队技术栈和管控需求来筛的。场景推荐理由Python 生态要快速出效果LangGraph / Dify / CozeAgent 工具生态和 Function Calling 支持最全开发快文档多Java/Kotlin 团队要贴近现网基础设施Spring AI / ADK能复用公司已有的 JVM 中间件适合企业级集成高并发/低资源占用Rust Tokio 自研 Runner异步开销小内存占用低适合高频 Agent低代码/产品验证扣子 Coze / Dify先搭原型验证效果减少无意义代码成本注意选型不要被框架绑架。LangGraph 再方便如果你的需求只是写一个顺序固定的脚本那直接上普通任务队列就够了把动态决策交给模型也不需要完整图引擎。先确认“动态”的部分到底在哪再决定编排层要不要上重武器。2.3 案例中的整体架构前面说过架构这里展开每个模块的职责。FastAPI 入口只做鉴权和任务入队Redis 队列是任务缓冲Worker 是 Agent 的运行单位。模型层统一抽象成 LLM 接口这样更换模型供应商时不需要动业务代码。工具注册表里每个工具的名字、描述、参数 Schema 都靠 JSON Schema 描述模型通过 Function Calling 选择调用。存储层拆两块状态数据库存任务状态和轨迹向量库存长期记忆。日志系统单独走结构化日志任何一次工具调用的出入参都要记录。有了这个架构后续加权限、加评测、加监控都很顺手。这里有个实操经验不要把 Agent 运行循环和 Web 服务放在同一个进程里同步执行。否则一个 Agent 卡在模型 API 慢请求上整个 API 进程都会被占住别的请求全部排长队。先入队再执行的话用户体验好很多也方便水平扩容。3. 实操要点让 Agent 真的干起活来3.1 封装 Skill工具即技能给模型调用的工具不能只写在代码里要让模型“看得懂”。我会把每个能力包装成带 JSON Schema 的函数例如def fetch_page(url: str) - dict: 抓取网页正文返回结构化内容 ...但真正给模型看的不是这个函数本身而是它的描述。我会额外写一段描述当目标页面被屏蔽时改用缓存副本或搜索标题。模型根据描述判断什么时候合适调用以及失败后怎么换路。热词里的“agent skill”“claude agent skills”都在讲同一件事把知识、步骤甚至示例打包成可复用的技能单元。我建议每个 Skill 至少包含四部分功能说明、参数示例、边界条件和失败处理建议。比如网页抓取技能要告诉模型如果抓取超时返回错误码 HTTP_TIMEOUT不要尝试轮询三次以上。再强调一点封装接口时返回值的结构化程度决定 Agent 后续能不能用好。宁可多返回几个冗余字段也不要让模型从一大段 HTML 里自行抽取。想象一下你让一个实习生去找资料他带回整页源码你很难直接用但他按统一格式整理成标题、时间、摘要你就能快速做下一步。3.2 编排状态机别让 Agent 自由到失控如果不上重型框架自研状态机也够用。状态五态就够状态含义触发动作Idle等待新任务消费队列中的任务Running正在模型推理/执行工具更新进度记录轨迹WaitingApproval等待人工确认暂停 Agent发送确认通知Done任务完成保存结果清理上下文Failed多次重试失败标记错误触发补偿代码层面每个循环开始前我都做一轮健康检查state { status: Idle, step: 0, max_steps: 15, context: [], pending_approval: None, }如果 step 超过 max_steps或者存在 pending_approval就不能再让模型做规划。状态机不是给模型用的是给运维兜底的。这个案例里有一次调度系统升级Worker 全部重启由于有 checkpointerAgent 恢复到上次工具调用结束的位置继续跑没有丢数据。多花一小时做持久化绝对值得。3.3 防止死循环与重试爆炸模型不是每次都能推理正确。一个常见情况是Agent 把解析失败的网页持续提交给抽取工具连续几次相同的工具参数组合这就是典型的死循环。我直接写死规则连续 3 次工具名加参数完全相同就判断为循环强制停止。另一种循环是模型反复调用某工具但修改了无关参数实际上还在原地踏步。处理方式是把步骤之间的工具结果做哈希对比连续多轮结果集合一致就中断。重试策略也要分情况。网络抖动可以重试业务错误不要重试。比如 API 返回 401重试一百次也改变不了结果直接把错误原因交给模型去调整思路。热词里提到的“agent execution terminated due to error.”不一定都是环境问题很多时候是重试策略写歪了。3.4 并发模型Agent 到底怎么扛并发并发问题先说结论Agent 的瓶颈几乎都在模型 API 调用和外部 IO 上Processor 本身很轻。所以扛并发的手段是异步队列加水平扩展 Worker。具体算一下。假设一个 Agent 任务平均要做 20 次模型调用单次调用耗时 3 秒那么串行需要 60 秒。如果模型 API 的限流是每秒 2 次调用那么单 Worker 用满也就每秒最多 2 次模型调用换算成任务吞吐是 2/200.1 任务每秒也就是一分钟最多 6 个任务。要支撑同时进行 60 个任务至少需要 10 个 Worker。这个数字和上游 API 限流强相关所以配置 Worker 池之前必须知道模型网关的配额。我建议缓存工具结果尤其网页抓取。同一个 URL 在多个任务里出现概率很高缓存 1 小时能省大量外部请求和解析时间。Redis 里的 TTL 设置短一点控制信息过期风险。还有一点模型 API 调用要加连接池和超时控制不然并发一上来连接数先爆。4. 工作流 Agent 的记忆与上下文管理4.1 短期上下文控制 Token 窗口一个流程内模型看到的上下文会随步骤增长但不能把所有历史都丢给模型。我采用三种方式配合使用。滑动窗口只保留最近 N 轮对话和工具结果更早的直接丢弃。摘要压缩每完成一个子任务把前面的长对话压成 300 字以内的要点。向量检索当需要“之前看过类似页面”时按语义检索旧结果再放回上下文。实现上我会写一个简单的上下文对象context { recent_messages: [], summary: , token_estimate: 0, }超过阈值就触发一次 summarize()。摘要压缩会损失细节所以我会在摘要提示词里加一条规则如果当前任务依赖某个具体数字摘要必须保留原始数字。这个约束写进提示词里比事后补救好用。4.2 长期记忆把经验落库长期记忆不是把所有历史都塞给模型而是按需检索。案例里Agent 每完成一个任务会把结论向量化存到本地向量库用户下次提到同一个关键词时先用 Embedding 检索相似度最高的最近几条结论再决定要不要重复劳动。记住时间戳、来源、置信度旧数据默认低置信。这里有个细节长期记忆要有遗忘机制。比如用户三个月前偏好 A 风格报告最近十次都是 B 风格那模型应该自动以 B 为准。实现方式很简单检索结果排序按时间做衰减权重时间越近优先级越高。否则你会发现 Agent 记忆越多反而不如新模型“干净”。4.3 多 Agent 与记忆边界有热词在问“多 agent”这里说一句。案例三我用单 Agent因为是闭环任务一个 Agent 完全能覆盖。多 Agent 更适合任务内部需要专业化分工的场景比如一个负责搜索、一个负责分析、一个负责写稿这时候它们之间要共享可验证的消息队列否则协作成本会超过收益。对大多数业务工作流先单 Agent 跑通再考虑多 Agent。记忆安全也要提前评估。如果多个 Agent 共享记忆要有明确的命名空间和权限边界避免 A 任务的记忆污染 B 任务。最简单方案是每条记忆带上 task_type 和 user_id检索时先过滤用户数据最小化合规上也轻松很多。5. 常见问题与排查实录5.1 沙盒更新后 Agent 启动失败先说我碰到的报错某次更新沙盒镜像后Worker 启动日志里出现“error occurred during initialization of vm agent library failed agent_onload”任务执行到一半变成“agent execution terminated due to error.”。这种报错常见于沙盒依赖和运行进程不一致。热词里提到的“codex 无法发送消息显示更新 agent 沙盒”其实是同一个逻辑外部环境升级后本地 Agent 还在用旧上下文消息自然发不出去。排查顺序很简单先看日志是初始化阶段还是运行阶段接着检查沙盒路径、Python 环境、动态链接库然后确认依赖缓存是否过期。如果代码没改却突然挂优先考虑回滚镜像而不是改代码。我后来把沙盒初始化放进 Worker 健康检查里每次启动先 init失败就终止并不再消费队列。这个改动看起来简单但能避免大量“僵尸 Worker”持续重试导致队列积压。5.2 模型返回不符合 JSON Schema模型不按 Schema 走是老问题。Function Calling 虽然能用但偶尔嵌套字段会类型错误。我的修复方案是三板斧系统提示里附加一个工具调用示例模型 API 的 JSON Mode 开启解析失败时把异常传回给模型让它自己修复后重试。实际执行下来大部分错误一轮就能修好三轮修复后如果还不行就退回规则解析并标记人工。还有一个隐蔽的坑工具返回结果里如果包含非法字符也会让后续模型调用报错。所以每个工具返回前都要做 UTF-8 清洗去掉控制字符。这类问题排查起来特别费时间但遇过一次之后我就会把清洗逻辑做成公共方法。5.3 外部动作缺少反馈Agent 调用 Webhook 后如果服务端没有明确返回成功Agent 会默认失败然后重试。最坏的情况下会重复下单、重复发消息。我给所有外部连接工具加了三态协议成功、失败、未知。成功就继续失败就改策略未知直接进人工确认队列不做自动重试。这个坑很多团队要踩一遍才会遇到等造成线上事故再补不如一开始约定好。6. 部署、评测与上线后的运营细节6.1 权限最小化和人工审批Agent 安全这块我把工具分成四类只读、局部写入、全局写入、外部副作用。前两类可以自动执行后两类必须人工确认。还要限制网络出口和数据库账号Agent 只能访问业务需要的库不能让它拿着超级账号到处跑。热词里的“agent anywhere”可以理解成把 Agent 运行能力带到不同环境但环境越开放安全边界越要明确。具体到案例里Agent 运行环境与生产环境隔离用沙箱限制网络出口。外部动作进审批队列审批通过才真正执行。这个流程不复杂但能拦住绝大多数误操作。如果你不甘心每件事都审批也可以按置信度阈值放行高风险动作还是走人工。6.2 评测集与可观测性“agent 评测集构建”绝对不能省。我维护了一个小评测集包含典型任务、边缘 case、对抗 case。类型数量用例示例典型任务30收集某关键词的行业新闻并生成日报边缘 case20关键词为空、所有源超时、页面全是广告对抗 case5指令模棱两可、要求执行危险操作每次改模型、改工具定义就全量跑一遍评测集记录通过率、平均步数、平均 token 消耗。通过率下降就说明回归了。不要只凭几个感觉好的例子就上线那样很容易被一次偶然成功骗到。追踪方面每个任务生成 trace_id所有日志带上 trace_id模型调用、工具结果、审批事件串成一条时间线。排查问题时直接 grep trace_id能省很多时间。热词里的“agent 学习路线”“agent 面试题”其实就是把评测集当成练习题去做比看一百篇文章有效。6.3 部署细节与优雅退出Docker 镜像固定依赖版本环境变量管理模型密钥。K8s 部署时 Worker 单独一个 DeploymentHPA 按队列长度扩容。模型 API 限流在网关做Worker 端使用令牌桶避免无限重试打爆上游。另一个重要部署细节是优雅退出。Worker 收到 SIGTERM 后先把当前任务状态保存再停止拉取新任务最后退出。否则任务会丢在队列里但状态错乱。这个点写在团队文档里之后运维同事一致点赞。自动化工作流上线不是写好代码就完事部署和运营细节决定它能不能稳定跑一个月。7. 从案例三延伸的几点个人体会7.1 边界比模型更重要做自动化工作流 Agent 这几章下来我的体会是模型决定能力上限工程决定可靠性下限。多数失败不是模型不够聪明而是没有定义好工具边界、没有设置步数限制、没有把错误反馈做对。所以我会先画一张“允许 Agent 做什么、不允许做什么”的清单再去选型。模型可以换但边界一旦画得乱后面每个环节都要为此买单。7.2 给 Agent 一份危险动作清单最后分享一个延续至今的小技巧在 Harness 的配置里放一份危险动作清单凡是命中清单的动作Agent 必须额外解释一次原因人工确认后才能执行。这个清单不需要很长把“删除、发送、切换环境、改库、消耗资金”列进去就够了。它不能解决所有问题但能拦住最蠢的那批错误。这个案例之后我又把同一个结构复制到好几个业务线入口队列、工具注册表、状态机、记忆存储、审批闸门。换模型、换提示词就能适配新场景。如果你准备做自己的自动化工作流 Agent不必追求一步到位先把这个骨架搭起来后面所有增量都建立在可观测和安全之上。
返回列表