AWS Builders《Orchestrating Our Agents SDLC on Temporal》
分级:【对照正文】——三份里最值得细读的一篇,纯实战。
原文:https://dev.to/aws-builders/orchestrating-our-agents-sdlc-on-temporal-the-hard-parts-nobody-warns-you-about-1mgc(2026-07-17) 一句话:把人工 prompt-by-prompt 的 AI 编码流水线改成 Temporal 编排的持久化 SDLC 后踩过的坑——确定性、载荷、重试、心跳、成本、观测——以及每个坑的 fix。
- 起点判断:作者先人工 prompt-by-prompt 驱动 AI 编码助手跑完整 SDLC(给 spec → 查代码库 → 规划 → 写代码 → 写测试 → 换 fresh context 自审 → 修 → 翻译 → 开 PR),做到一定次数后发现 uncomfortable 又 obvious 的结论:这不是创造性工作,是”确定性流水线、每格中间坐一个 AI”。于是用 Temporal(持久化执行引擎,扛 crash、重试失败步骤、记住每个 run 的位置)编排,自托管在 EKS 上、worker 舰队旁边。全文主旨句:AI agent SDLC 不是写一次就走的脚本,是持续运行的分布式系统,要按生产服务的运营严肃程度对待;流水线代码只占约三分之一工作量,其余是运营。
- 流水线各阶段(固定顺序、每步专职 agent + fresh context):意图分析(raw request → 结构化 spec)→ 代码库调查(找可复用现状)→ 架构师(最贵的模型,因为规划杠杆最大)写逐文件计划 → 计划评审(plan critic 批准后才允许写一行代码)→ 编辑器写代码(之后修 bug 时复用同一个编辑器)→ 单元测试与 e2e 测试并行 fan-out + 覆盖率评审把关 → staff QA 有界循环(按 spec 与 live UI 验 build,不过就打回编辑器)→ 三个不同模型并行评审 + 归并(consolidator)+ 修复循环 → 多语种翻译 fan-out(一语一个 agent)→ 合并 → PR 组装 + PR 评审 → 人接手。模型分档:规划/评审用顶级、编辑用中档、翻译等机械活用最便宜;全部经 Amazon Bedrock,换模型是配置改动、不是新集成。
- 现实检查(作者先打的预防针):Temporal-as-agent-orchestrator 不是低代码玩具,不适合非技术人员;需要分布式系统思维(worker、队列、重试、at-least-once)、workflow/activity 分工与确定性约束、对象存储/密钥管理/容器编排的熟练度,以及”你的自动化现在是一支长驻 worker 进程舰队,要部署、监控、升级、on call”的觉悟。原文原话:没准备好全职拥有基建,就没准备好在 Temporal 上跑 agent SDLC。
- 确定性(塑造一切的约束):Temporal 把代码分两个世界。Workflow 代码是编排大脑,必须确定性——因为耐久靠”重放全部已记录事件历史重建状态”,重放必须产出完全相同的决策序列,否则引擎报 non-determinism 错误拒绝继续。Activity 代码放副作用:网络、磁盘写、随机、时钟、LLM 调用——activity 结果只记录一次、重放时从历史取、永不重算。LLM 调用是系统里最不确定性的东西,规则自成:每个模型调用、每次文件写、每次 API 请求都进 activity,workflow 只决定下一步跑什么。三个迟发陷阱:workflow 代码里取 wall clock(改用引擎的确定性时间源);workflow 内随机(在 activity 里生成再传回);workflow 模块加载时 import 带副作用的重库(boto3、DB driver 在 import 时做 I/O 会污染确定性,要隔离 import、让 workflow 定义保持纯净)。这是新成员最常犯错的第一项,是可度量的 onboarding 成本。
- 载荷上限(几乎人人先撞的墙):Temporal 经持久化层传 workflow/activity 的输入输出,单 payload 约 2MB、整个 gRPC 请求约 4MB 硬顶——上限合理,因为每个 payload 都会成为永久重放的历史,胖 payload 就是永远胖的历史;超了就报 blob-size 错误,实际效果是 run 死亡。而 agent SDLC 要传的东西:几千行 spec、整份计划与多步报告、生成的源文件、模型调用的原始请求/响应体(可能极大),立刻超标。Fix 是所有严肃 Temporal 用户都会收敛到的 claim-check 模式:不传数据,只传数据的指针。每个大件 offload 到对象存储(他们用 S3),workflow 里只 threading 一个小引用 ArtifactRef:uri(s3://bucket/
/ / )+ sha256(下载时完整性校验)+ filename(落盘时的稳定名)。每步把输出上传对象存储、返回 ArtifactRef,下一步下载所需件到本地 scratch 再调模型,hash 防静默损坏与截断上传。但要诚实面对新签的单:对象存储会 404、限流、stale 读,workflow 从此依赖它的健康;artifact 不清理会无限积累(他们 lifecycle 规则 + 清理步骤两者都做了);worker 舰队读写桶要凭证,EKS 上就是 IRSA 正确接线,本身就是一个项目;key 必须由全局唯一且重试稳定的东西构造。 - 跨 pod /tmp 陷阱(全文作者说最值得内化的一课):单 worker 时本地盘感觉像共享盘,一上多副本(为吞吐与可用性,必然),Temporal 把步骤调度到空闲 worker:A 落在 worker 1 写文件,B 落在 worker 2 找文件——那是另一块盘。三处中招、每处初看像不同 bug:① fan-out 合并读本地 scratch:子步骤散到两个 pod,合并只看到落在本 pod 的一半,还兴高采烈地对一半结果报成功,一半工作静默消失;② 共享输入文件只有一 pod 有:fan-out 子步骤被告知读该文件,另一 pod 上的子步骤找不到文件,而 agent 身为 agent,一本正经编了段”输入文件不存在”的叙述,该叙述随后被当成该步骤的正式输出捕获;③ 潜伏参数 bug:本地盘版只用文件名,所以传错的存储 key 字段从未被用于路径、无人察觉,切到对象存储、消费者开始用该字段拼 key 的当天,所有下载同时 404。教训短而绝对:多 worker 舰队里,本地盘是谎言;凡跨步骤边界的东西必须走共享存储或 workflow payload,绝不走本地文件系统。全部 artifact(输入与输出)一走对象存储 + workflow 传引用,三个 bug 同时消失;fix 本身不聪明,难的是在咬到你之前处处贯彻的纪律。
- 单步重跑(不重做整 run):新手误解:Temporal 的 replay 听起来正是”某步错了重跑”,其实不是——replay 是引擎拿已记录历史重执行 workflow 代码重建内存状态,不重跑 activity;它重放决策、不重放副作用,是耐久机制,不是”再跑一次这个 LLM 调用”按钮。真正想要的(开发与事故恢复中经常要的)是”只重执行这一步、对着当前状态、其余十二步不动”。他们落地的模型三件套:① workflow 输入加 step filter:触发时可传步骤名列表,有则 workflow 走状态机但只执行具名步骤(可单相、可连续切片),不用为其余部分付费;② artifact 检查式幂等:步骤跑昂贵的模型调用前,先查本 run 的输出 artifact 是否已存在,存在则短路——重跑变便宜且安全,重试步骤不重复收费;③ run-scoped key:每个 artifact key 按唯一 run id 命名空间,重跑步骤只覆盖自己的槽位、永不撞其他 run。设计格言:第一天就为”重跑一步”设计,你用它的频率远超预期,调试与低成本恢复都靠它。
- 测试后门(不烧光预算验证管线):完整生产跑一趟几十美元(顶级规划 + 中档编辑 + 便宜机械活),这个价钱没法迭代编排本身;需要更便宜的入口,且带护栏、保证永不在生产触发。两个后门:① 全流程强制便宜模型:一个全局 flag 让每步无视常规定档、全部用最便宜模型,整条管线跑下来”一杯咖啡 vs 一顿正餐”的价钱,验证控制流、artifact 交接、重试、S3 管道。两个血泪 caveat:便宜模型只验证 plumbing、不验证质量——他们实测机械步骤通过、代码步骤产出漂亮报告但零实际编辑(便宜模型够强到描述工作、弱到干不了活),便宜路径证明的是”管线在动”,不是”输出是好的”;flag 必须默认关、开启时大声记日志、生产触发器绝不能设它。② 单步隔离跑:同一个 step filter 就是测试 harness:只传一个步骤名就只测评审步;再加一个仅 opt-in、永不进默认 run 的 trivial 步骤,做近免费冒烟测试(证明 worker 能接任务、调模型、写 artifact)。贯穿两后门的设计原则:测试路径经配置注入(哪个模型、哪些步骤),绝不 fork 一条单独的”测试模式”代码路径——单独的测试代码会漂移、会撒谎;一条代码路径 + 参数化,才是保持诚实的唯一版本。
- GitHub Actions 触发:不想为启动 run 建 bespoke UI,也不想把 orchestrator 暴露公网;workflow_dispatch 手动任务是完美前门:免费的、带权限的、带审计的表单(下拉框 + 几个文本框,团队任何人不用碰 kubectl 就能填)。job 本身几乎什么都不干:取输入、组一个小 JSON、一次带认证的调用打到 orchestrator API,真正启动耐久 run。唯一值得抄的细节:job 跑在集群内的 self-hosted runner 上(他们就在 EKS 集群内),经内网 DNS 访问 orchestrator——触发端点永远不必公开,还白得 GitHub 的身份与审计。同一输入面就是测试后门的落点:steps 字段是单步重跑路径,cheap_mode 开关是便宜模型全跑——两者只是同一触发器的参数,不是另一条启动路径,所以保持诚实。格言:别建启动器,你已经有了一个。
- 成本(耐久执行悄悄抬账单):成本不只 token 表。① 模型 token:最明显;按步骤选模型是最大的杠杆,别拿规划档模型干机械活。② 晚期失败的 run 是纯浪费:他们有 run 在接近尾声时升级、无可用结果,而前面步骤的大半预算已烧掉——钱花了、什么都没 ship;这是长管线的昂贵失败模式,是主张 gating 与 early exit、不只重试的理由。③ 长驻 worker 空闲也花钱:耐久执行让 worker 进程一直跑着轮询,这是 7×24 的算力、独立于任何模型花费。④ 历史与存储增长:耐久 run 积累事件历史与 artifact,不管就无界增长、都要钱。还有个专咬 agent 的硬顶:单个 workflow 执行的事件历史有上限(几万事件、几十 MB),预警阈值远在上限之前;”一直迭代直到完成”的紧循环每轮记数个事件,会一路走向顶线。逃生口是定期关闭当前 run、用同一身份开新 run(Continue-As-New)并只带走需要的状态;若 agent 有任何无界”keep going until done”循环,必须一开始就绑迭代上限或规划好 rollover。他们把评审-修复循环绑了固定轮数,既绕开上限、顺带也封了单 run 成本顶。格言:耐久执行模型是用钱换可靠性,通常是好交易,但要能按 run、按步骤看见账单,否则它会 surprise 你。
- 长步骤、心跳与慢模型响应:Agent 步骤很慢,带工具的重推理调用一次可达数分钟;Temporal 理所当然要知道步骤还活着,以便重调度真正死掉的。几个超时里对 agent 最重要的两个:① 单次尝试时长要按现实设:必须容纳最慢的合法模型响应 + 工具调用并留 margin,设太紧 Temporal 会杀死健康工作;② 心跳:他们在模型流回的每条消息上 heartbeat,另加一条 30 秒定时基线心跳,保证长静默工具执行也不丢租约。这不只是避免 dashboard 难看:步骤一停心跳,Temporal 认定 worker 已死而重试,于是第二份完全相同的昂贵模型调用在第一份极可能还在跑时启动——心跳缺失不只是看起来糟,它直接让最慢步骤的 token 账单翻倍。流式响应是天赐:每块 chunk 都是天然心跳机会;若模型客户端只在最后一次性返回,必须跑定时心跳,否则会永远跟假超时搏斗。
- 重试、backoff 与”重试”和”升级”的区别:模型 API 抖动是常态(限流、瞬时 5xx、偶发拒绝),Temporal 的重试策略(指数 backoff、封顶次数、按 activity 调参)对瞬时 case 很好。但一个前置 gotcha:默认重试策略是无限重试,在被限流的模型 API 上,临时 429 会变成锤 provider、烧配额的重试风暴——要封顶次数、封顶最大间隔,provider 给 Retry-After 头就显式设下次延迟,别让盲 backoff 猜。更深的、agent 特有的 nuance 是哪些根本不该重试:有些失败不是瞬时的——某步产出通不过硬校验,identical 重试通常原样复现失败、每次还烧 token;要的是停止重试、升级(走 workflow 的另一分支或转人)。他们建模了一小套 non-retryable 错误类型:步骤 raise 其中之一时 Temporal 不空转,workflow 捕获后决定下一步。格言:重试瞬时基建失败,升级确定性内容失败;重试一个自信犯错的 agent,只是付费再听一遍同样的错话。
- Agent 会谎报成功,所以要在它们之间放机械门:这条既哲学又极实际。Agent 是乐观叙述者:问编码 agent 有没有跑类型检查,它常常真诚地说全过了,回头一看 workspace 里躺着半打幻觉 API 带来的编译错误。Prompt 指令”返回前必须跑 build 并确认绿灯”是必要但不充分——agent 会跳过强制步骤还照样报成功。Fix 是停止信任自报、加确定性门:代码步骤返回后,一个 activity 独立对产出 workspace 跑真正的类型检查与 build;失败则步骤失败、附编译器输出,workflow 升级而非放行。agent 对自己工作的意见从此只是输入、不是裁决。这同时修了下面要讲的观测谎言:有了外部门,”agent 说过了”与”实际过了”成了两个可比较的事实。
- Agent 与 orchestrator 之间的机器可解析契约:相关陷阱:orchestrator 要基于 agent 产出做控制流决策(通过/失败、修订/批准),若从自由散文里解析决策,就是离”一段礼貌段落卡住 workflow”只差一行的距离。他们真实中招:评审步骤写了很好的修复总结、却没输出 orchestrator 在 grep 的精确 verdict token;无 token、无决策、整个 run 被升级。格言:agent 与控制流之间的边界必须是严格的机器可解析契约——要求精确 verdict 行并校验;agent 没产出它,本身就是失败,不是”也许”。散文是给人看的,控制流要 token。
- 可观测性(把 LLM 追踪接进耐久引擎):Temporal 自带自身世界的极佳可见性(每个 workflow、步骤、重试、输入输出均可查),但不给你 agent SDLC 里最想要的:模型实际干了什么——token、prompt、响应、工具调用、每步成本。为此他们接了专用 LLM 追踪工具(他们是自托管 Langfuse、同 EKS 集群),于是跑两套观测面:编排与耐久面 + prompt/token/成本面;让两套面对齐,比预期磨人得多。① 跨进程边界的 span 传播:模型调用发生在步骤派生的子进程里;要把 trace 上下文(W3C trace parent 与 state)注入子进程环境,让模型的 span 嵌进正确的 workflow-and-step span 之下;否则得到两棵断开的树:Temporal 的 run 视图 + 一堆不知属于哪个 run、哪个步骤的孤儿 LLM span,事后手工关联是灾难。跨进程边界必须显式传 trace 上下文,否则你有的不是分布式追踪,是两份独立日志。② 追踪后端本身是你现在拥有的基建:这是没人警告的部分——LLM 追踪工具有自己的数据库、对象存储、故障模式;他们的曾悄悄停止摄入 trace 很久,dashboard 显示零 trace、大家以为 instrumentation 坏了,真因是追踪后端对象存储 inode 耗尽(不是空间耗尽,是几百万小对象耗尽 inode),每次写入都在通用错误后静默失败;修复一半是清理、一半是迁到有 lifecycle 管理的存储。格言:观测栈就是生产基建;不监控”监控 agent 的东西”,只会在最需要它时发现它早挂了。③ 提防撒谎的观测:全项目最佳 bug:一个按步骤统计 agent 工具调用数的指标恒报零,一度让人相信 agent 什么都没干;它们干得不少,是计数器查了 SDK 响应对象的错误属性 shape、静默匹配不到——某步骤写了几十个文件却记”0 tool calls”。从未对 ground truth 校验过的仪器,比没有仪器更糟,因为它会主动误导 triage。格言:至少对一次 ground truth 验证你的 instrumentation;从未验证过的指标是谣言。
- Agent 逻辑周周变时的 workflow 版本化:Agent 管线经常在变(重排步骤、加门、改 prompt、一步拆两步),而 Temporal 可能有按旧代码启动的长 run 在飞;确定性意味着不能直接改 workflow 重部署——旧 run 按新代码重放会偏离已记录历史而失败。Temporal 有一等工具:workflow 代码里的 patch 式版本门、worker 级版本化(build ID 钉住执行),近期指引倾向 worker 版本化作为有能力做版本化部署的团队的默认。实操要点:run 短命就先排空旧 run 再推不兼容改动;run 长命就必须认真用版本原语,workflow(非 activity)代码的每次不兼容改动都要版本门;改 activity 代码宽容得多——把行为往 activity 里推 partly 就是为了这层自由。这是经常性税:agent 逻辑高频变与长命耐久执行天然张力,靠版本纪律还。
- 人在环是 feature,不是事后补丁:全自主 agent SDLC 开 PR 还自动合并,是把自信的胡说八道直送生产的好办法。Temporal 的 signal、update、timer 让人工检查点建模干净:workflow 可暂停等外部批准,超时升级。他们把人放在高杠杆门上:写代码前先看一眼计划对不对、落地前最终改动人审一遍。格言:自主是旋钮不是开关;人放在错一次最贵的地方,机器跑便宜可逆的。
- 本地开发与调试不确定性的 agent:在确定性引擎上测不确定性的东西本质上别扭,任何工具都不能完全消除别扭。Temporal 的测试框架确实好:时间跳跃测试服务器、重放测试(能在进生产前抓住确定性违规,两者都用;重放测试尤其是在重构时防破坏 workflow 确定性的安全网)。但 agent 本身永远不可复现:重放测试抓代码漂移、不抓模型漂移。两件让调试可忍受的事:① 持久化原始模型交换:每 run 每步骤的请求与响应体落盘,某步行为异常时 transcript 就在手边——正是这样证明了”0 tool calls”指标在撒谎、抓到 agent 写错输出路径;② 结构化可查询的步骤记录:每步写一条记录(输入、输出、token 数、成本、时长),三步之前出问题时读记录、不翻日志。格言:你没法让 agent 确定性,但能让它的行为事后完全可审计——就做那个。
- 没人预算的部分:这是你要永远跑的系统:workflow 代码不是产品,跑着的系统才是,且永远需要你。作者列的非穷尽清单:worker 舰队部署/扩缩/安全滚动;workflow 代码、worker 构建、在飞执行之间的版本钉住;Temporal 自身的持久化存储(他们用 Amazon RDS,含容量与备份故事);artifact 对象存储的 lifecycle 与清理;LLM 追踪栈自己的数据库与存储;所有触模型 API 或桶的云凭证与 workload 身份(IAM 角色与 IRSA,轮换过期总在最糟时间坏);以上全部的监控告警;以及凌晨 2 点 run 卡住时有人 on call。他们实际丢过时间在:过期的 AWS SSO 会话、到集群的 VPN 与 DNS 解析抖动、平台变更后模型厂商身份联邦断裂、RDS 密码轮换失同步导致服务 crashloop——没有一样是 agent 工作,全是”跑 agent 的系统”的成本。格言:运营按固定成本预算,不是一次性搭建;养不起”永远跑”的那部分,就别启动”建一次”的那部分。
- 对比与选型:Temporal 不是编排 agent 的唯一方式,而且比替代品重。要分开人们都叫”编排”的三件不同工作:① 批量与数据调度(DAG 调度器):擅长”按计划跑图”,不为耐久单步重放或人等而生;② agent 框架与图库(AI 原生工具):为 agent 循环本身而生,流式、记忆、工具路由、LLM 评估内置,单进程里几乎零基建搭多步 agent 流;③ 耐久执行引擎(Temporal 及以已有数据库为后盾的轻量同类):为 crash 中途存活、精确续跑、带 backoff 的单步重试、等人数天的人工信号、几千并发 run 的可查询记录而生。AI 原生框架把流式、记忆、prompt 管理免费给你,Temporal 全得自己搭;Temporal 回报的是轻量工具没有的耐久。很常见且 sane 的组合:耐久引擎管长程编排,agent 框架管步骤内的推理循环。耐久就是付 Temporal 税的全部理由。选型格言:半成品 run 很贵、”重开”不可接受时选耐久引擎;否则选轻的。
- 提交前 checklist(8 问):步骤真是确定性管线、还是在给探索性的东西强加结构(Temporal 奖励前者、跟后者较劲)?能否不扭曲设计地把每个副作用(尤其模型调用)都关进 activity?是否一开始就设计了经对象存储的 artifact 交接(workflow 传引用、payload 里无大件)?是否有单步重跑路径与便宜模型全跑、且带护栏保证测试路径永不进生产?每个 agent→orchestrator 的决策是否都是严格的机器可解析契约?是否有验证 agent 说法的机械门、而不是信任它们?LLM 追踪栈是否像生产基建一样被监控?是否有人员与 on call 成熟度无限期跑下去?多数 yes 则 Temporal 会服役得极好;多数 no 则你会花更多时间跟引擎较劲而不是 ship 功能。
- 结论:把人工流程变成耐久编排 SDLC 是他们做过最高杠杆的事之一(run 扛 crash、失败步骤自重试、第九步死掉从第九步续、单相重跑花零钱、每个模型调用可追溯到成本、agent 迈不过它说服不了的门);但没有一样来自 happy-path 教程,全来自载荷上限、跨 pod 磁盘陷阱、撒谎的指标、静默的追踪 outage、自信犯错的 agent、以及 auth/DNS/发布那类持续的运营点滴。收束格言:Temporal 让 agent SDLC 耐久,不让它容易,也不让它自维持;系统有主人。