AI Agent 工作流实战:从线性脚本到可维护的自动化系统
你是不是也经历过这种场景:写了个 Python 脚本跑自动化,第一周很爽,第二周开始出 bug,第三周平台一改版脚本直接报废。然后你花了两天修它,修完发现它又变成了「一次性脚本」。
这不是你的问题,是架构的问题。今天这篇用真实代码拆解:为什么线性脚本跑不久,以及怎么用 AI Agent 工作流把它升级成可维护的系统。
先说我的背景。过去半年,我给自己搭了十几套自动化:内容分发、数据汇总、定时报表、热点监控。踩过的坑足够写一本书。最痛的一次是某个平台改了接口,我花了两个周末才把发布器修回来------那次之后我意识到,自动化真正的成本不在开发,而在维护。而维护成本的高低,完全取决于你一开始选的架构。
一、线性脚本为什么「跑不久」
先看一段典型的线性自动化脚本:
python
# 线性脚本:每天抓取数据 → 处理 → 发邮件
import requests
def run():
# 1. 抓取
data = requests.get("https://api.example.com/data").json()
# 2. 处理
result = [item for item in data if item["status"] == "ok"]
# 3. 发送
send_email(result)
print("done")
run()
这段代码的问题不是「简单」,而是没有容错、没有反馈、没有演进能力:
- 一个环节挂了,整个流程停:API 超时、字段变更、格式错误,任何一步异常都会让脚本中断,而且你不知道它停在哪一步
- 失败不能自愈:遇到错误只能人工介入,跑得越多维护越累
- 写死逻辑:业务规则一变化,就要改代码重新部署
这不是夸大。我统计过自己过去半年的自动化故障记录:60% 的故障发生在外部依赖变化(接口改版、字段调整、认证过期),30% 是数据格式异常,只有 10% 是逻辑本身写错。也就是说,线性脚本的大部分时间都花在跟「变化」搏斗。而 AI Agent 工作流解决的核心问题,恰恰是应对变化。
二、线性 vs Agent:核心差异
| 维度 | 线性脚本 | AI Agent 工作流 |
|---|---|---|
| 执行方式 | 写死顺序 | 目标驱动,动态规划 |
| 错误处理 | 中断等待人工 | 反思→重试→修复 |
| 状态管理 | 无 | 显式状态机/图 |
| 演进能力 | 改代码 | 调整 prompt 和工具 |
| 适用场景 | 确定性流程 | 半结构化任务 |
关键认知:不是所有任务都要上 Agent。确定性流程(固定 API 调用、固定格式转换)用线性脚本更稳更省。Agent 的价值在「半结构化任务」------需要判断、需要绕路、需要处理意外。
!\[\](img_agent
.jpg)
用一句话概括差异:线性脚本是「你告诉它每一步怎么做」,Agent 工作流是「你告诉它目标,它自己想办法」。前者适合流程确定的场景,后者适合流程中充满「如果......就......」分支的场景。
三、核心概念:任务、工具、记忆、反思
一个可维护的 Agent 工作流有四个核心组件:
python
from dataclasses import dataclass
from typing import List, Dict, Any, Callable
import json
@dataclass
class Task:
id: str
description: str
status: str # pending / running / completed / failed
result: Any = None
class AIAgent:
def __init__(self, llm_client, tools: Dict[str, Callable]):
self.llm = llm_client
self.tools = tools
self.memory = [] # 长期记忆
self.task_queue = [] # 任务队列
def plan(self, goal: str) -> List[Task]:
"""将目标分解为可执行的任务列表"""
prompt = f"""
目标: {goal}
可用工具: {list(self.tools.keys())}
请返回任务列表 JSON: [{{"description": "..."}}]
"""
return [Task(id=str(i), description=t["description"], status="pending")
for i, t in enumerate(json.loads(self.llm(prompt)))]
def execute(self, task: Task) -> Any:
"""执行单个任务,支持工具调用"""
for name, fn in self.tools.items():
if name in task.description:
return fn(task.description)
return self.llm(task.description)
def run(self, goal: str) -> str:
"""完整工作流:规划 → 执行 → 反思"""
self.task_queue = self.plan(goal)
results = []
for task in self.task_queue:
task.status = "running"
try:
task.result = self.execute(task)
task.status = "completed"
except Exception as e:
task.status = "failed"
task.result = str(e) # 错误记录进 memory,供下次反思
results.append(task)
return self.synthesize(results)
def synthesize(self, results: List[Task]) -> str:
"""整合所有结果生成最终输出"""
prompt = f"基于以下执行结果,生成一份专业报告:\n{json.dumps([r.__dict__ for r in results], ensure_ascii=False)}"
return self.llm(prompt)
!\[\](img_pipeline
.jpg)
这段代码的工程要点:
- Task 状态机:pending→running→completed/failed,让整个流程可观测、可恢复。出问题时你能精确知道卡在哪个任务,而不是面对一坨堆栈
- 工具即函数:每个工具都是普通 Python 函数,Agent 通过描述匹配调用。这意味着你可以用任何现成库做工具------requests、pandas、selenium 都行
- 错误进 memory:失败原因记录后,下次遇到类似问题可以检索历史修复方案(自愈的雏形)。这一步是「从脚本到系统」的分水岭
- 多 Agent 协作:可以拆成 researcher / analyst / writer 三个独立 Agent 编排(见注释部分)
四、多 Agent 协作实战
真实场景里,单 Agent 不够用。以「自动化写周报」为例:
python
class MultiAgentSystem:
def __init__(self, llm):
self.agents = {
"researcher": AIAgent(llm, {"search": search_web}), # 负责信息收集
"analyst": AIAgent(llm, {"calc": calculate_metrics}), # 负责数据分析
"writer": AIAgent(llm, {"md": format_markdown}), # 负责报告撰写
}
def orchestrate(self, goal: str) -> str:
raw_data = self.agents["researcher"].run(goal)
analysis = self.agents["analyst"].run(f"分析: {raw_data}")
report = self.agents["writer"].run(f"撰写: {analysis}")
return report
分工逻辑:研究员收集 → 分析师处理 → 写手产出。每个 Agent 只做一件事,单点出错不影响其他部分,这就是模块化的价值------平台改版只影响 researcher,analyst 和 writer 不用动。
我在真实项目里验证过这套分工的实际收益:同样一个「自动整理周报」需求,单 Agent 方案在数据源格式变化时会全流程重跑(每次重跑多花 3-5 分钟和额外 token),而三 Agent 方案只需要重新跑 researcher 一段。模块化带来的不只是代码清晰,更是故障隔离和成本控制。
五、选型决策树:什么时候用 Agent
用一套可复现的判断逻辑:
markdown
任务出现频率 < 3次/周? ──是──→ 手动做
│否
↓
规则是否稳定(3个月不变)? ──否──→ 先别自动化
│是
↓
出错代价是否极高? ──是──→ 加校验+人工审批
│否
↓
需要判断/绕路/处理意外? ──是──→ 用 AI Agent 工作流
│否
↓
用确定性脚本/工作流工具
补充两个工程判断:
- 模块化优先:无论用不用 Agent,把流程拆成「采集/处理/输出」三段,每段独立测试。这样平台改版时只修一段。这是我在一次接口改版事故后总结出的铁律------那次事故里,因为流程是单体脚本,接口一改整个链路全崩,我花了两个周末
- 成本核算:Agent 的 token 消耗比线性脚本高 3-10 倍(每次反思都是额外调用)。自愈流程尤其烧钱------建议「小模型质检、大模型修复」,校验逻辑用便宜模型,重构逻辑用强模型。我实测过:同一套流程,用便宜模型做质检能省 40% 的 token 成本,而且质检质量几乎不受影响,因为「判断对不对」比「怎么改对」简单得多
!\[\](img_dev
.jpg)
六、避坑清单
- 防止死循环:自愈循环必须设「最大重试次数」,比如 5 次修不好就强制人工告警,否则 token 会烧光。我见过一个朋友的 Agent 因为没设上限,一个错误重试了 30 多次,一晚上烧掉了几十块
- 记忆别无限膨胀:向量库要定期清理过期失败案例,否则检索噪音越来越大。我的经验是每月清理一次,只保留最近 90 天的失败案例
- 不要过度 Agent 化:能写 20 行确定性脚本解决的,别上 Agent。我见过把「读文件→发邮件」这种固定流程也 Agent 化的,成本和延迟都翻倍,收益为零
- 日志必须结构化:Task 状态、工具调用参数、token 消耗都要落库,这是排查问题的基础。没有结构化日志的 Agent 系统,出问题就是灾难现场
- Prompt 版本管理:Agent 的行为完全由 prompt 决定,prompt 改了行为就变。一定要给 prompt 做版本号,出了问题能回滚。这条是我踩过最深的一个坑------有一次调了个 prompt 细节,结果整个周报的格式全变了,还没法追溯
七、总结
把自动化从「脚本」升级成「系统」,核心不是代码量,而是架构思维:
- 线性执行 → 状态机(可观测、可恢复)
- 写死逻辑 → 目标驱动(Agent 动态规划)
- 错误中断 → 反思重试(自愈)
- 单点脆弱 → 多 Agent 模块化(隔离故障)
最后提醒一句:Agent 工作流是「让机器帮你干活」的工程化方案,不是魔法。它解决的是结构化程度中等、规则相对稳定、值得长期维护的任务。选型之前,先问自己三个问题:这件事值得自动化吗?规则稳定吗?出错我能接受吗?
如果这三个问题都是肯定的,那今天这套代码就是你起步的地基。建议先跑通单 Agent 的最小示例,再逐步加工具、加记忆、加多 Agent 协作。每一步都做小验证,别一口气堆复杂度。
如果你也正在搭 AI Agent 工作流,评论区聊聊你的架构:用的是 LangGraph 还是自研状态机?踩过什么坑?我会持续更新自动化系统的工程实践系列。
觉得有用的话点赞收藏,遇到再查。关注我,下一篇讲「如何给 Agent 加记忆:向量库选型与成本控制」。