不再手写 Prompt 链:用工作流编译器构建可验证的多模型 Agent 运行时

不再手写 Prompt 链:用工作流编译器构建可验证的多模型 Agent 运行时 许多 Agent 项目从一段看似清晰的业务代码开始先让大模型拆解任务再根据返回文本调用搜索、图片或视频接口最后把所有结果交给另一个模型汇总。原型阶段只有三五个节点这种写法足够直接进入生产环境后节点数量、模型版本、租户策略和失败分支同时增长代码很快变成一张由 Prompt、条件语句和供应商 SDK 拼成的隐形流程图。开发者无法在执行前回答三个基本问题这次任务最多会花费多少 Token会产生哪些外部副作用任一节点失败后系统将从哪里恢复。解决这些问题不能继续堆叠 Prompt Engineering。更合适的抽象是把 Agentic Workflow 看成一门领域语言把用户目标编译成带类型、预算、依赖和验收条件的中间表示再交给多模型运行时执行。模型只是编译后端之一检索器、数据库、图像引擎和视频队列也是后端。API Gateway 则类似驱动层它屏蔽协议差异却不负责决定业务语义。本文以“工作流编译器”为主线构建一套从 Agent IR、静态检查、Token 成本规划、异步运行时、统一协议驱动到差分回放的完整方法。它与常见的“调用哪个模型”教程不同重点不是某个模型的单次回答而是如何让一条包含 DeepSeek、Claude、GPT、Flux、Midjourney、Kling 等异构能力的执行计划可验证、可预算、可中止并且可重放。一、为什么 Prompt Chain 会失控Agent 需要编译阶段1. 解释执行的三个盲区传统 Chain 本质上是解释执行上一步生成一段自然语言宿主程序读取这段文字再决定下一步。问题在于自然语言同时承担了数据、指令和控制流三种职责。模型写出“继续搜索”究竟是一个普通句子还是一次工具调用返回“已完成”是否意味着结果通过了验收只依赖字符串约定系统无法在运行前做静态分析。第二个盲区是成本不可闭合。规划器可以动态追加步骤一个看似简单的任务可能在反思循环中调用十几次模型。每次请求都没有错但总成本已经超过业务价值。第三个盲区是副作用不可追踪。发送通知、修改数据库、提交视频任务都可能在超时后实际成功如果执行器把超时等同于失败并直接重试就会制造重复操作。编译式 Agent 将“决定做什么”和“真正执行”分开。前端解析用户目标编译器输出结构化任务图静态检查器拒绝不完整或越界的计划优化器进行路由和缓存改写运行时只执行已经签名的图。模型仍可参与规划但其输出先被当作候选程序而不是可以立即执行的命令。LangChain、LlamaIndex、AutoGPT 等框架可以继续存在于这套体系中但它们更适合作为前端 DSL、工具封装或检索组件而不是整个生产运行时。框架生成的链路先转换为统一 IR再接入组织自己的权限、预算和审计策略。这样既保留框架的开发效率也避免业务流程被某个框架的消息对象、回调方式或版本升级锁定。2. 编译器与运行时的职责边界一条完整链路可以表达为自然语言目标 | v Intent Parser - Agent IR - Static Analyzer - Plan Optimizer | v Signed Execution Plan | v Event Runtime - Model/Tool Drivers - Validators | | | ---------- Result Ledger -------编译器负责确定节点类型、输入来源、依赖关系、预算上限、截止时间、可重试性和验收器运行时负责排队、并发、取消、租约、状态持久化与事件投递驱动层负责把统一调用转换为 OpenAI Compatible Protocol 或供应商原生协议验证器则判断结果能否进入后继节点。这种分工带来一个重要变化业务评审可以发生在调用模型之前。安全团队能够检查计划中是否包含高风险工具FinOps 能够检查成本上界平台团队能够确认候选能力是否存在。计划未通过时系统不会产生任何上游费用或外部副作用。编译结果还可以缓存但缓存对象不是最终答案而是经过检查的计划模板。只要用户约束、策略版本、工具版本和能力目录未变化同类目标可以复用拓扑结构只重新绑定输入资产与截止时间。策略或工具 Schema 更新后相关计划模板立即失效。这种“计划缓存”减少规划 Token同时不会把旧答案误当成当前事实。3. 确定性外壳与概率性内核LLM 输出具有概率性但包围它的系统不必同样随机。节点输入、Schema、超时、重试次数、预算和状态转换都可以确定只有“模型生成内容”这一小段保持概率性。工程目标不是消除概率而是把它限制在可测量的边界内。例如脚本节点允许多种措辞但必须返回三段式结构、目标受众和镜头数量图片节点允许画面差异但必须满足宽高比、资产格式和安全策略。确定性外壳使自动化测试不必比较整段文本是否相同只需验证不变量是否成立。二、设计 Agent IR让任务、资产和副作用拥有类型1. 中间表示不是聊天记录Agent IRIntermediate Representation不是模型消息的简单封装。它描述的是一个可执行节点需要哪些输入资产产生何种输出调用什么能力消耗多少预算失败时能否重试以及完成后由谁验收。聊天记录只是某些文本节点的输入之一不应成为整个系统的状态容器。最小节点可以包含以下字段字段作用静态检查示例node_id图内唯一标识不得重复capability能力别名必须存在于能力目录inputs上游资产引用引用节点必须先完成output_type输出类型必须与后继输入兼容budget成本与 Token 上限所有节点之和不得越界deadline_ms节点截止时间不得超过流程截止时间effect副作用等级高风险操作要求审批validator验收规则发布前节点不得为空2. 使用 Pydantic 固化契约下面的类型只表达编译期信息不包含任何供应商 SDK 对象。Capability是稳定别名真实模型 ID 在部署期解析。fromenumimportEnumfromtypingimportAny,LiteralfrompydanticimportBaseModel,Field,model_validatorclassEffect(str,Enum):PUREpureREVERSIBLEreversibleIRREVERSIBLEirreversibleclassAssetRef(BaseModel):producer:strname:strmedia_type:strclassNodeIR(BaseModel):node_id:strcapability:strinputs:list[AssetRef]Field(default_factorylist)output_type:strmax_input_tokens:intField(ge0)max_output_tokens:intField(ge0)deadline_ms:intField(ge100)effect:EffectEffect.PURE retry_limit:intField(default1,ge0,le5)validator:dict[str,Any]classWorkflowIR(BaseModel):version:Literal[agent-ir/v1]workflow_id:strnodes:list[NodeIR]total_budget:floatField(gt0)model_validator(modeafter)defvalidate_graph(self)-WorkflowIR:ids[node.node_idfornodeinself.nodes]iflen(ids)!len(set(ids)):raiseValueError(duplicate_node_id)knownset(ids)fornodeinself.nodes:forrefinnode.inputs:ifref.producernotinknown:raiseValueError(funknown_producer:{ref.producer})returnself这段定义没有检查环路、数据类型和拓扑顺序这些工作应由独立静态分析器完成。Pydantic 负责验证数据形状编译器负责验证程序语义两者不能混为一层。否则复杂规则会散落在字段校验回调中既难测试也无法给出清晰的诊断位置。3. 多模态资产必须通过引用传递文本可以短暂内联图像、音频和视频则应进入版本化资产仓库。IR 只传递asset_id、内容哈希、媒体类型、尺寸、创建节点和访问策略。这样既能避免消息体膨胀也能保证重放时拿到同一份输入。资产不可只用文件名寻址。同一分镜重试两次可能产生两个同名文件如果后一次覆盖前一次验证报告就无法与原结果对应。内容寻址可以使用sha256或对象存储版本号派生资产还要记录父资产与转换参数从而形成可追踪的 lineage。4. 把副作用写进类型系统纯节点可以安全重算例如摘要、分类和向量化可逆节点需要补偿动作例如创建临时资源后可以删除不可逆节点则必须在执行前取得显式许可并使用幂等收据。编译器发现一个不可逆节点位于未验证的生成节点之后时可以自动插入审核屏障。这类似数据库事务中的写集合分析。Agent 不再等到线上发生重复发送后才增加补丁而是在计划阶段就知道哪条边跨越了副作用边界。5. 能力符号表传统编译器使用符号表解析变量与函数Agent 编译器也需要一份能力符号表。每个能力条目声明输入类型、输出类型、最大上下文、同步或异步模式、是否支持流式、允许的数据区域、价格版本和质量等级。符号表只描述逻辑能力不暴露真实凭证。同一个reasoning.plan可以关联多个实现但编译器看到的是稳定函数签名。若某个后端停止支持工具调用平台只修改该实现的能力声明静态分析器会自动阻止需要工具调用的计划绑定到它。相比在业务代码里维护模型白名单这种类型化目录更容易测试也能在部署前发现不兼容变更。三、从目标到可执行图工作流编译器的四遍处理1. 第一遍语义解析与约束提取编译器前端先把用户目标拆成事实、偏好、硬约束和待确认项。比如“生成一段 30 秒中文产品视频不能出现价格明天下午前完成”至少包含模态、时长、语言、禁用字段和截止时间。解析器必须用结构化 Schema 返回缺失的关键参数标为unknown不能自行猜测。对高风险工作流解析结果要显示给调用方确认对低风险任务可以根据租户默认策略补全。所有补全都记录来源用户输入、项目配置、组织策略或编译器推导。后续发生冲突时优先级由来源而不是文本出现顺序决定。2. 第二遍类型检查与依赖分析静态分析器构建有向图检查环路、孤立节点、不可达分支、输入输出类型和截止时间传播。若video.compose需要分镜图列表而上游返回普通文本计划应在执行前失败。若两个节点都修改同一外部对象分析器应标记写冲突要求串行或增加版本条件。截止时间采用反向传播最终交付节点的 deadline 向前减去各节点的 P95 运行时间与安全余量。如果某个前置节点得到的可用时间为负说明这张图在当前 SLO 下不可行。系统应该缩减任务、改用低延迟能力或转为异步交付而不是让请求运行到一半才超时。3. 第三遍计划优化工作流优化与传统编译器有相似之处。Semantic Cache 可以被视为公共子表达式消除当两个纯节点拥有相同规范化输入、知识快照、模型策略和输出 Schema 时只需执行一次。Prompt 中不影响语义的空白和字段顺序可在计算缓存键前规范化但时间、租户权限和随机种子必须进入键空间。独立节点可以并行化小型同类节点可以批处理连续的格式转换可以合并永远不会被消费的中间结果可以删除。不过模型调用不是完全透明的函数。只要节点依赖当前时间、外部检索、个性化数据或随机生成优化器就必须保守。每次改写都写入优化日志保留改写前后的 IR便于解释成本为何发生变化。4. 第四遍路由绑定与计划签名编译前端只指定能力例如reasoning.plan、vision.storyboard、video.compose。最后一遍根据区域、租户权限、上下文长度、价格版本和近期质量把能力绑定到候选池而不是单一模型。运行时仍可在候选池内做健康切换但不能越过编译器设定的质量与合规边界。计划完成后计算哈希并签名。运行时收到的每个节点都携带plan_hash任何动态追加节点都必须生成新版本并重新通过检查。这能阻止执行器或模型在未审计的情况下扩大权限。签名不是为了证明模型输出正确而是为了证明实际执行的程序与已审核计划一致。5. 策略即代码的静态分析企业规则不应散落在 Prompt 中例如“客户数据不得离开指定区域”“生产发布必须人工确认”“单次视频任务不得超过预算上限”。这些规则应编写为针对 IR 的可测试策略在编译阶段返回允许、拒绝或要求补充条件。诊断信息必须指向具体节点和字段而不是只返回“策略不通过”。策略之间还可能冲突低延迟策略要求跨区域后端数据策略却禁止出区低成本策略选择轻量模型质量策略又要求高置信度。编译器应按照硬约束优先、软目标优化的方式求解并在无可行解时明确列出冲突集合。沉默地忽略某条规则会让系统表面成功却破坏治理边界。6. 一个简单的拓扑编译器fromcollectionsimportdefaultdict,dequefromdataclassesimportdataclassdataclass(frozenTrue)classStep:name:strdeps:tuple[str,...]p95_ms:intdefcompile_levels(steps:list[Step])-list[list[str]]:by_name{step.name:stepforstepinsteps}indegree{step.name:0forstepinsteps}children:dict[str,list[str]]defaultdict(list)forstepinsteps:fordepinstep.deps:ifdepnotinby_name:raiseValueError(funknown_dependency:{dep})indegree[step.name]1children[dep].append(step.name)readydeque(nameforname,degreeinindegree.items()ifdegree0)levels:list[list[str]][]visited0whileready:currentlist(ready)ready.clear()levels.append(current)fornameincurrent:visited1forchildinchildren[name]:indegree[child]-1ifindegree[child]0:ready.append(child)ifvisited!len(steps):raiseValueError(cycle_detected)returnlevelslevels中同一层的节点具备并行执行条件但运行时还要结合并发额度、内存、租户配额和上游频控做二次调度。编译器证明“可以并行”运行时决定“此刻是否应该并行”。四、把 Token 当作计算资源成本模型、准入控制与路由1. 从请求计费转向计划计费企业通常按单次请求统计模型成本但 Agent 的真实计费单元应是一张执行计划。一次用户请求可能触发规划、检索、脚本生成、图像理解和多轮修复。若只看最终模型最昂贵的循环会隐藏在中间节点。设节点i的输入、输出 Token 上限分别为I_i、O_i对应单价为p_i、q_i重试上限为r_i工具与资产成本为a_i则保守成本上界为[C_{max}\sum_{i1}^{n}(1r_i)(p_i I_iq_i O_ia_i)]这个上界通常高于实际成本但它适合做准入控制。优化器还可以根据历史分布给出 P50、P95 预测区间。业务策略分别限制硬上界和期望值前者防止灾难性循环后者用于日常预算管理。成本账本需要区分预留、实际消耗与释放。任务被接纳时先预留预算节点完成后以真实 usage 结算未使用部分立即归还。异步任务长时间排队时预留额度不能无限占用可设置租约并在过期后重新评估。价格表本身带版本号因为同一计划在不同日期执行可能使用不同单价审计报表必须按当时生效版本复算而不是套用今天的价格。2. 准入控制先于 Load Balancing传统 Load Balancing 关注把流量均匀分给健康实例模型系统则必须先判断任务能否被接受。准入器检查租户余额、并发槽位、截止时间、数据区域、能力可用性和预测成本。任何一项违反硬约束都不能靠换一个后端掩盖。对于长视频等异步任务准入成功只意味着计划进入队列不意味着同步请求会等待完成。系统返回任务句柄和预计阶段客户端通过事件或轮询获取进度。这样可以把 HTTP 生命周期与生成生命周期解耦避免连接超时后任务仍在上游运行。3. Token Dynamic Routing 的多目标决策通过准入后Token Dynamic Routing 才对候选后端排序。评分不仅看价格还要考虑质量预测、排队时间、TTFT、错误率、上下文利用率和切换风险[U(m,t)w_qQ(m,t)-w_cC(m,t)-w_lL(m,t)-w_eE(m,t)-w_dD(m,t)]其中Q是任务条件下的质量概率C是成本L是预计延迟E是错误风险D是相对当前路由的漂移惩罚。先用硬条件过滤再最大化效用函数。权重按任务类型配置代码修复提高质量权重交互式分类提高首字延迟权重批量离线摘要提高成本权重。路由决策还要设置滞回窗口。若两个候选分数接近保持当前路由通常比频繁切换更稳定。只有替代路由连续多个窗口显著领先才逐步增加权重。每次选择都记录候选集合、特征快照和route_reason让成本审计能够回答“为什么这次没有使用更便宜的模型”。实时调度还必须考虑队列公平性。若一个大租户提交大量离线摘要不应挤占小租户的交互请求同一租户内部高优先级任务也不能永久饿死普通任务。可以按租户设置加权公平队列再在租户内部按 deadline 和优先级排序。队列等待时间一旦侵蚀节点预算调度器需要重新绑定低延迟候选或拒绝任务不能沿用入队时已经过期的路由判断。4. 模型名称只应是可变后端DeepSeek-R1、DeepSeek-V3、Claude 3.5 Sonnet、GPT-4o、Qwen2.5-72B、Llama-3.3 可以进入文本能力候选池Flux.1 Dev/Pro、Midjourney V6 API 可以进入图像后端Kling V1.5/V3 API、MiniMax Video-01 和 Sora API 映射可作为视频能力配置。这些名称不应成为代码常量也不应被理解为当前平台必然提供的固定 ID。诸如 GPT-5.6、Qwen 3.7 Max 等字符串若出现在内部配置中应明确标记为路由别名由部署环境映射到当时实际可用的供应商模型。可用性、价格和版本都以运行时配置为准。5. Benchmark 必须服务于路由而非排行榜下面是一张示例评测表用于说明编译器需要哪些输入。数值是合成工作负载的演示值不是供应商性能声明。能力池样本任务TTFT P50总延迟 P95Schema 通过率任务成功率成本指数reasoning.deep多约束计划1.8 s13.2 s97.1%94.8%1.00reasoning.fast分类与改写0.6 s4.4 s93.0%96.1%0.29vision.scene分镜约束抽取1.3 s8.1 s95.2%92.7%0.61image.render统一风格图像2.5 s20.6 s89.4%87.9%0.78video.compose短视频生成4.6 s58.0 s84.3%81.8%2.55测试集必须版本化并按输入长度、语言、工具数量、模态和风险等级分层。报告中位数、P95、置信区间与失败类型而不是只给平均值。供应商更新模型或安全策略后旧分数自动过期新后端先跑影子流量达到质量门槛后才进入生产候选池。五、运行时语义协程、事件账本与补偿事务1. Asyncio 不是运行时的全部Python Asyncio 能高效承载网络 I/O但asyncio.gather并不等于一个可靠的 Agent 调度器。运行时还要处理持久队列、租约、优先级、截止时间、取消传播、分布式限流和进程崩溃恢复。协程只存在于当前进程内一旦 worker 退出内存中的 Future 不具备恢复能力。正确做法是把数据库或事件流作为事实来源。worker 领取节点时写入带过期时间的租约执行期间续约进程失联后其他 worker 只有在租约过期时才能接管。节点状态更新携带版本号通过乐观锁防止回调、超时处理器和恢复线程同时覆盖结果。重试策略必须接受“剩余时间”和“剩余预算”两个输入。固定重试三次看似稳妥却会在上游故障时造成重试放大所有 worker 同时等待、同时醒来、再同时冲击后端。运行时应采用带随机扰动的指数退避尊重上游retry_after并为每个能力设置全局重试额度。当错误率越过断路阈值时新任务停止进入故障驱动少量探针用于判断恢复状态。2. 事件账本而不是最终状态表只保存statusFAILED无法解释失败过程。事件账本按时间追加NODE_ADMITTED、ROUTE_BOUND、REQUEST_SENT、FIRST_TOKEN、ASSET_STORED、VALIDATION_FAILED、RETRY_SCHEDULED和NODE_COMMITTED。当前状态由事件折叠得到原始事件不可修改。这种 Event Sourcing 设计允许重建任意时间点的状态也能计算排队、网络、推理、验证分别花了多少时间。日志中不直接保存敏感 Prompt而是保存脱敏摘要、内容哈希和加密资产引用。观测系统通过trace_id将网关请求、上游 request ID、工具执行和资产写入串成一条链路。3. 用 Saga 管理跨系统副作用Agent 很难使用传统数据库的全局事务模型服务、对象存储、消息系统和视频队列不会参加同一个两阶段提交。更现实的方式是 Saga。每个可逆节点声明补偿动作例如创建临时素材的补偿是删除素材写入草稿的补偿是恢复旧版本。补偿不是简单倒序重试。系统先判断哪些步骤已经提交、哪些补偿仍然合法再根据依赖关系执行。不可逆节点没有真正的补偿只能通过审批屏障、幂等键和执行回执降低风险。若外部调用超时但结果未知节点进入UNCERTAIN先查询回执不能立即重复提交。4. Memory 应成为显式状态输入短期对话、长期知识和工作流中间状态必须分离。长期 Memory 写入前经过来源校验、去重、脱敏、租户隔离和过期设置读取后以带来源的资产进入 IR而不是偷偷拼接到系统提示词。这样编译器可以计算它占用的上下文预算也能在回放时恢复同一版本。上下文压缩同样属于编译优化。系统按照约束优先级、相关度、可信度和时间衰减选择内容压缩后执行“约束存活检查”。若禁止事项、输出 Schema 或用户已确认选择丢失编译器必须重新调整而不是让模型在缺少关键条件的上下文中继续执行。Memory 的写回也要通过验证。模型在一次任务中推断出的临时结论不能自动升级为长期事实只有带可靠来源、通过一致性检查并满足保留策略的信息才能进入长期存储。写回事件保存来源任务、证据资产和置信度后续事实被更正时可以按 lineage 定位并使相关记忆失效。否则错误会随着每次检索不断自我强化。5. 取消必须沿任务图传播用户取消根任务时运行时先阻止新节点入队再取消没有副作用的在途请求最后处理已经提交的外部任务。取消结果分为CANCELLED、TOO_LATE和COMPENSATING不能用一个布尔值覆盖。对于不支持取消的视频后端系统记录孤儿任务完成后按策略归档或删除资产避免资源长期泄漏。六、后端驱动层用统一网关隔离协议碎片1. 网关是驱动层不是业务大脑不同模型接口在消息字段、工具调用、流式事件、错误结构和计费明细上存在差异。文本接口通常同步或 SSE 返回图像接口可能直接返回资产视频接口往往只返回任务句柄。如果编译器理解这些私有格式后端替换就会影响计划语义。统一网关只做五件事校验内部请求、解析租户凭证、把能力别名映射为驱动、转换协议、归一化响应与错误。业务层的预算审批、工作流依赖和内容验收不应放进网关。这样的边界类似操作系统调用与设备驱动上层声明意图驱动处理具体设备差异。在协议联调环境中可以将 OpenAI Compatible Protocol 的统一接口测试上游配置为base_urlhttps://178.nz/bo凭证从密钥服务注入这一地址仅承担请求转换、SSE 解析、错误映射与 Token 计量的沙盒验证不作为代码中的固定生产依赖。2. 统一请求信封请求信封至少包含request_id、tenant_id、plan_hash、node_id、capability、deadline_at、idempotency_key、budget、content和response_schema。网关收到请求后先校验截止时间与幂等键再解析候选驱动。所有上游凭证都由网关持有Agent 运行时只使用短时内部身份。错误被归一为INVALID_REQUEST、AUTH_FAILED、RATE_LIMITED、UPSTREAM_TIMEOUT、SAFETY_REJECTED、CONTEXT_OVERFLOW和UNKNOWN_RESULT。只有RATE_LIMITED与部分超时适合自动重试参数错误、安全拒绝和上下文越界需要回到编译器或业务策略处理。3. FastAPI 驱动入口importasyncioimportosfromdatetimeimportdatetime,timezonefromtypingimportAnyimporthttpxfromfastapiimportFastAPI,Header,HTTPExceptionfrompydanticimportBaseModel,Field appFastAPI()classEnvelope(BaseModel):plan_hash:strnode_id:strcapability:strdeadline_at:datetime idempotency_key:strbudget:floatField(gt0)content:list[dict[str,Any]]DRIVERS{reasoning.plan:os.environ[REASONING_DRIVER_URL],vision.storyboard:os.environ[VISION_DRIVER_URL],video.compose:os.environ[VIDEO_DRIVER_URL],}defremaining_seconds(deadline:datetime)-float:nowdatetime.now(timezone.utc)returnmax((deadline-now).total_seconds(),0.0)asyncdefinvoke_driver(url:str,body:dict[str,Any],timeout:float):limitshttpx.Limits(max_connections200,max_keepalive_connections40)asyncwithhttpx.AsyncClient(limitslimits,http2True)asclient:responseawaitclient.post(url,jsonbody,timeouttimeout)ifresponse.status_code429:raiseRuntimeError(RATE_LIMITED)response.raise_for_status()returnresponse.json()app.post(/internal/v1/invoke)asyncdefinvoke(envelope:Envelope,x_tenant_id:strHeader()):urlDRIVERS.get(envelope.capability)ifurlisNone:raiseHTTPException(400,UNSUPPORTED_CAPABILITY)remainingremaining_seconds(envelope.deadline_at)ifremaining0:raiseHTTPException(408,DEADLINE_EXCEEDED)payload{messages:envelope.content,metadata:{tenant_id:x_tenant_id,plan_hash:envelope.plan_hash,node_id:envelope.node_id,idempotency_key:(envelope.idempotency_key),},}try:resultawaitasyncio.wait_for(invoke_driver(url,payload,remaining),timeoutremaining,)exceptasyncio.TimeoutErrorasexc:raiseHTTPException(504,UPSTREAM_TIMEOUT)fromexcexceptRuntimeErrorasexc:raiseHTTPException(503,str(exc))fromexcreturn{node_id:envelope.node_id,capability:envelope.capability,result:result,}示例中的环境变量由部署平台提供因此源码不包含供应商域名与凭证。生产实现还要加入 Secret Store、持久化幂等表、租户配额、流式转发和审计事件。对于 SSE网关应把私有增量字段转换为统一事件序列并在客户端断开时向上游传播取消信号。流式转发需要独立的背压策略。如果客户端读取速度低于模型输出速度网关不能无限缓存 delta它应限制缓冲区在超限时暂停读取、降采样非关键事件或终止连接。工具调用事件必须完整保留调用 ID 和参数片段不能像普通文本一样丢弃。流结束后网关发送带 usage、完成原因和资产引用的终止事件运行时只有收到终止事件才提交节点。4. 限流必须是多维的单个 RPS 计数器无法描述模型资源。系统需要同时约束请求数、输入 Token、输出 Token、在途连接、异步任务数和资产带宽。限流键至少包含租户与能力必要时再叠加供应商和区域。不同维度使用独立令牌桶任何一个桶耗尽都返回明确的retry_after。网关还要实现背压。当驱动队列持续增长时低优先级任务延迟入队交互请求保留有限槽位批处理任务转移到离线队列。背压的目的不是让所有请求都成功而是让系统在过载时保持可预测的失败边界。七、差分回放与故障注入验证整个系统而不是单次回答1. 评测对象应是执行计划单模型 Benchmark 无法覆盖 Agent 级风险。完整评测需要记录计划是否编译成功、静态检查是否发现非法副作用、实际成本是否落在预测区间、路由是否满足 SLO、失败后是否正确恢复以及最终资产是否通过验收。一个模型分数很高但总是触发格式修复它在工作流层可能更慢、更贵。评测数据分为三层节点层统计质量、Token 和延迟图层统计关键路径、并行收益、重试放大与补偿次数业务层统计最终任务通过率和人工接管率。三层使用同一个run_id关联才能判断问题来自模型、调度还是计划结构。质量指标必须与失败成本对应。对于内部草稿格式错误后自动修复可能可以接受对于对外发布或数据库写入同样的错误率可能完全不可接受。评测报告因此要按副作用等级分桶并额外统计“错误穿透验证器”的比例。一个总分很高但偶尔越过安全边界的版本不能被平均质量掩盖。2. 差分回放隔离变量保存 Agent IR、模板版本、能力目录快照、资产哈希、路由特征和验收结果后可以对历史任务进行差分回放。一次实验只替换一个变量候选模型、缓存策略、剪裁算法或路由权重。新旧结果由同一验证器评分高风险样本再进行盲审。回放不能无条件复用外部副作用。纯节点在隔离环境中重算可逆节点使用测试资源不可逆节点由模拟驱动代替。涉及个人数据的样本先脱敏并限制保留时间与访问范围。评测集本身也要防止被 Prompt 调优污染保留从未公开的隔离集。差分结果不仅比较最终文本还比较计划形状。新编译器是否增加了节点、扩大了权限、改变了关键路径或引入更多不可逆操作都应单独展示。即使最终结果相似计划成本和风险也可能已经发生结构性变化。对存在随机性的生成节点可以比较约束满足率、资产属性和人工盲审分布而不是要求像素或句子完全一致。3. 必做的故障注入清单第一类是网络故障注入 DNS 延迟、连接超时、SSE 半途断开和 429检查 deadline、退避和取消是否正确。第二类是协议故障返回空字段、未知事件、重复 delta 和错误 Token 统计检查驱动能否归一化或拒绝。第三类是运行时故障执行中杀死 worker、延迟回调、重复投递事件检查租约和幂等是否阻止重复副作用。第四类是模型质量故障让规划节点产生环路、让脚本节点遗漏硬约束、让图片节点返回错误媒体类型。系统应该在对应验证边界停止而不是让错误一路传播到最终交付。第五类是预算故障模拟输出失控或反思循环确认硬上限能中断流程并留下完整账本。4. 一个多模态计划如何被编译执行以“根据产品资料生成短视频草案”为例前端首先解析语言、时长、画面比例、禁用信息和截止时间编译器生成资料抽取、事实核验、脚本编写、镜头规划、分镜生成、视频合成和最终检查七类节点。事实抽取与品牌约束提取可以并行脚本必须等待二者完成多个分镜节点可以并发视频合成必须等待全部分镜通过。文本节点根据复杂度进入reasoning.plan或reasoning.fast候选池图像节点进入vision.storyboard视频节点进入video.compose。运行时不关心后端最终映射到 DeepSeek-R1、Claude 3.5 Sonnet、GPT-4o、Flux.1 Pro、Midjourney V6 还是 Kling V3 API它只执行签名计划并验证统一响应。若第二个分镜失败系统只重算该分镜及其后继不重做已经通过的资料抽取和脚本。若视频后端排队超过 deadline运行时返回异步句柄或按策略终止不占用同步连接。若最终检查发现字幕超长则产生一个局部修复版本而不是让规划器重新生成整张任务图。这正是编译式架构相较自由循环的主要收益失败范围有限重算范围明确成本能够解释。5. 上线门槛一个候选版本只有同时满足以下条件才应扩大流量编译成功率不下降静态检查没有新增漏报P95 计划成本处于预算内关键路径延迟满足 SLO幂等与补偿演练通过人工接管率没有异常上升。模型质量只是其中一项不应覆盖运行时可靠性。灰度期间保留旧编译器与旧能力目录计划版本与运行时版本分别记录。发现异常时新任务回到旧版本已经执行的任务继续由兼容运行时完成避免一半使用旧语义、一半使用新语义。八、从 LLM Middleware 到 AI 编译栈未来系统的真正边界多模型 Agent 的长期形态不会只是更多 SDK 的集合而会形成类似编译器与操作系统的分层。前端负责理解目标Agent IR 固化任务语义静态分析器检查风险优化器处理缓存、并行和路由运行时管理资源与失败驱动层适配持续变化的模型协议。模型升级因此不再要求改写整条业务链路。这套架构的价值也不在于让所有任务完全自治。它首先让每次自治有边界执行前知道计划执行中看得见预算失败后能够恢复产生副作用时可以追踪。只要中间表示、事件账本和验证契约保持稳定底层模型、价格与供应商都可以替换。已有系统不必一次性重写。第一阶段先为现有 Chain 增加统一事件和成本账本第二阶段把工具输入输出改造成类型化资产第三阶段引入只读静态检查对现有计划给出诊断但不阻断最后再启用签名计划与编译期准入。渐进迁移能保留业务交付节奏也能用真实运行数据校准编译器规则。下一阶段的竞争重点将从“谁接入的模型多”转向“谁能把不确定模型变成确定工程系统”。工作流编译器不是为 Prompt 增加一层复杂包装而是把 Agent 从试验脚本推进到可测试、可审计、可演进的软件基础设施。