ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

VoltAgent 工作流编排实战:用 `createWorkflow` 构建 AI Agent 多步骤业务流程

VoltAgent 工作流编排实战:用 `createWorkflow` 构建 AI Agent 多步骤业务流程 人工智能AI AgentAgent 框架后端多智能体RAG工具调用Agent 记忆【免费下载链接】voltagentAI Agent Engineering Platform built on an Open Source TypeScript AI Agent Framework项目地址https://gitcode.com/gh_mirrors/vo/voltagent点击查看免费下载本指南以 VoltAgent 官方示例 examples/with-workflow 为核心系统讲解 VoltAgent 工作流Workflow编排引擎从createWorkflow的基本用法、andThen/andAgent等步骤原语到人工审批、动态 Schema、定时休眠、循环分支与护栏等高级能力。读完本文你将能基于voltagent/core的createWorkflowAPI把 AI Agent 与确定性的业务步骤组合成可运行、可恢复、类型安全的多步骤流程并在本地一键启动演示服务。一、Workflow 在 VoltAgent 中的定位VoltAgent 是一个开源的 TypeScript AI Agent 框架提供模块化的组件来构建、定制和扩展 AI Agent——从 API 连接到记忆管理、从多模型支持到可观测性。Workflow 模块是其中的确定性编排能力当我们需要把 AI Agent 的灵活性与业务逻辑的确定性结合起来时例如先校验订单 → AI 判断风险 → 计算折扣 → 得出最终结论就可以用工作流把这些步骤串起来。在 with-workflow 示例 中一个完整的工作流演示程序同时注册了9 个不同类型的 workflow覆盖了 VoltAgent 工作流引擎几乎全部的核心原语#工作流演示的核心概念1order-processingandThen、andAgent、条件逻辑、setWorkflowState/getStepData2expense-approvalsuspend/resume人工介入、resumeSchema3content-analysisandTap、inputSchema数据裁剪、数据转换4article-summarizer基于输入动态生成 Schema5timed-reminderandSleep、andSleepUntil时间控制6batch-transformandForEach、andMap批量处理7loop-and-branchandDoWhile、andDoUntil、andBranch循环与分支8guardrail-workflow工作流级与步骤级护栏Guardrail9wrapped-agent-call在andThen中包装调用 Agent这些构造器均由 packages/core/src/workflow/index.ts 统一导出本文后续会逐个结合源码展开。二、快速开始运行 with-workflow 示例2.1 通过脚手架一键创建示例 README 提供了最快捷的体验方式——使用 VoltAgent 官方脚手架创建项目npm create voltagent-applatest -- --example with-workflow2.2 本地运行与构建创建后的项目即本仓库的 examples/with-workflow在 package.json 中预置了以下脚本scripts: { build: tsc, dev: tsx watch --env-file.env ./src, start: node dist/index.js, volt: volt }npm run dev使用tsx watch监听源码并热重载入口为./src即 src/index.ts可通过.env文件注入模型 API Keynpm run build执行tsc将 TypeScript 编译到dist/npm start运行编译产物node dist/index.jsnpm run volt调用 VoltAgent CLIvoltagent/cli进行管理操作。项目核心依赖包括voltagent/core工作流引擎、voltagent/logger日志、voltagent/server-honoHTTP 服务与zodSchema 校验tsconfig.json采用ES2022ESNext模块与strict模式保证类型安全。2.3 启动后的形态示例末尾将全部工作流注册进VoltAgent实例并挂载一个 Hono 服务器new VoltAgent({ agents: { analysisAgent, contentAgent }, logger, server: honoServer({ port: 3141 }), workflows: { orderProcessingWorkflow, expenseApprovalWorkflow, contentAnalysisWorkflow, articleSummarizationWorkflow, timedReminderWorkflow, batchTransformWorkflow, loopAndBranchWorkflow, guardrailWorkflow, wrappedAgentWorkflow, }, });运行后这 9 个工作流即可通过 VoltAgent 提供的接口被触发与观察。三、工作流基础createWorkflow与 Schema 配置3.1 函数签名与元信息所有工作流都通过createWorkflow创建核心实现在 packages/core/src/workflow/core.ts其第一个参数是工作流配置对象第二个及以后的参数是步骤。以示例 1 为例const orderProcessingWorkflow createWorkflow( { id: order-processing, name: Order Processing Workflow, purpose: Process orders with fraud detection and special handling for VIP customers, input: z.object({ orderId: z.string(), customerId: z.string(), amount: z.number(), items: z.array(z.string()), }), result: z.object({ orderId: z.string(), status: z.enum([approved, rejected, needs-review]), totalWithDiscount: z.number(), }), }, // ... 步骤列表 );配置项说明id工作流唯一标识用于注册、日志与状态持久化name/purpose人类可读的名称与用途描述便于观测与检索inputzod Schema定义工作流的入口数据结构运行前即做类型校验resultzod Schema定义工作流最终输出结构保证返回值符合契约。3.2 步骤执行上下文每个步骤的execute函数接收一个上下文对象示例中高频使用了以下能力data当前步骤的输入数据由前一个步骤的输出合并而来setWorkflowState(updater)写入跨步骤持久化的工作流状态workflowState读取前面步骤写入的全局状态getStepData(stepId)按步骤 id 读取任意历史步骤的输出suspend(reason, payload)挂起工作流等待外部恢复详见第五节。例如示例 1 中校验步骤通过setWorkflowState记录校验元数据andThen({ id: validate-order, execute: async ({ data, setWorkflowState }) { const isValid data.amount 0 data.items.length 0; setWorkflowState((prev) ({ ...prev, validatedAt: new Date().toISOString(), validatedBy: system, })); return { ...data, isValid, baseTotal: data.amount }; }, }),而在最后的决策步骤中通过getStepData(validate-order)?.output与workflowState.validatedAt分别读取步骤输出与全局状态完成approved/rejected/needs-review三态判定——这正是andThen串联步骤之间数据传递的标准模式。四、核心步骤原语andThen、andAgent、andTap4.1andThen确定性函数步骤andThen是最基础的步骤构造器源码见 packages/core/src/workflow/steps/and-then.ts它把一个 async 函数包装为type: func的步骤。除id与execute外它还接受四个 Schema 参数inputSchema限定本步骤可见的输入字段见 4.4outputSchema校验本步骤输出suspendSchema/resumeSchema定义挂起载荷与恢复载荷的结构见第五节。从源码可以看到andThen会捕获WORKFLOW_SUSPENDED/WORKFLOW_CANCELLED信号将它们作为正常流程而非错误处理这是挂起/取消机制能在步骤内安全工作的关键。4.2andAgentAI Agent 步骤andAgent是工作流引擎与 LLM 的桥接点。示例 1 用它让analysisAgent对订单做欺诈风险评估andAgent( async ({ data }) Analyze this order for fraud risk: Order ID: ${data.orderId} Customer ID: ${data.customerId} Amount: $${data.amount} Items: ${data.items.join(, )} Provide risk level (low/medium/high) and reasoning. , analysisAgent, { schema: z.object({ riskLevel: z.enum([low, medium, high]), reasoning: z.string(), }), }, ),三个参数分别为prompt 生成函数接收上下文、返回指令文本、Agent 实例、以及结构化输出 Schema——Agent 的返回会被强制解析为该 Schema从而让后续步骤拿到类型确定的riskLevel字段。示例 3 中andAgent还被用来同时完成情感分析、关键词抽取与摘要生成三类任务。Agent 本身通过new Agent(...)定义核心字段是name、model如openai/gpt-4o-mini与instructionsconst analysisAgent new Agent({ name: AnalysisAgent, model: openai/gpt-4o-mini, instructions: You are a data analyst. Provide clear, structured analysis., });4.3andTap旁路日志步骤andTap用于只观察、不改数据的旁路步骤源码 and-tap.ts。示例 3 用它记录分析开始与最终指标andTap({ id: log-start, execute: async ({ data }) { console.log(Starting analysis of ${data.content.length} characters); console.log(Language: ${data.language}); }, }),andTap的返回值不会覆盖当前数据流适合埋点、日志与指标采集。4.4inputSchema控制步骤可见数据示例 3 的transform-results步骤展示了inputSchema的威力——它让 AI 步骤的输出在进入后续步骤前被裁剪andThen({ id: transform-results, inputSchema: z.object({ sentiment: z.enum([positive, negative, neutral]), keywords: z.array(z.string()), summary: z.string(), }), execute: async ({ data, getStepData }) { const analysisData getStepData(text-analysis)?.output; return { sentiment: data.sentiment, keywords: data.keywords, summary: data.summary, wordCount: analysisData?.wordCount || 0, }; }, }),这里inputSchema保证data中只包含声明的三个字段而getStepData仍可跨步骤取回完整的中间数据实现数据可见性控制与数据回溯的分离。最后的andTap也通过inputSchema只接收指标字段用于日志打印。五、人工介入suspend / resume 模式示例 2expense-approval演示了 VoltAgent 工作流最具特色的能力之一——挂起等待人工决策。步骤内通过suspend暂停整个工作流外部系统随后携带决策数据恢复执行。andThen({ id: check-approval-needed, resumeSchema: z.object({ approved: z.boolean(), managerId: z.string(), comments: z.string().optional(), adjustedAmount: z.number().optional(), }), execute: async ({ data, suspend, resumeData }) { if (resumeData) { console.log(Manager ${resumeData.managerId} made decision); return { ...data, approved: resumeData.approved, approvedBy: resumeData.managerId, finalAmount: resumeData.adjustedAmount || data.amount, managerComments: resumeData.comments, }; } if (data.amount 500) { console.log(Expense of $${data.amount} requires manager approval); await suspend(Manager approval required, { employeeId: data.employeeId, requestedAmount: data.amount, category: data.category, }); } return { ...data, approved: true, approvedBy: system, finalAmount: data.amount }; }, }),要点拆解suspend(reason, payload)挂起工作流reason供人理解payload是随挂起事件对外暴露的上下文如申请人、金额、类别resumeSchema声明恢复时外部传入的数据结构——在本例中即经理的审批结论、备注与可选的调整金额运行时会强制校验resumeData当工作流被恢复时该字段携带外部决策数据步骤据此走已审批分支金额 ≤ $500 时自动通过approvedBy记为system体现规则优先、AI/人工兜底的编排思想。挂起/恢复机制在核心层由 core.ts 中的 suspend controller 与状态管理器支撑并有专门的 suspend-resume.spec.ts 测试覆盖。六、动态 Schema让约束随输入变化示例 4article-summarizer展示了一个进阶能力andAgent的schema不仅可以是一个静态 zod Schema还可以是接收data返回 Schema 的函数从而把输入参数如摘要长度范围注入到输出约束中andAgent( async ({ data }) Summarize the following article in ${data.min} to ${data.max} characters: Article: ${data.article}, contentAgent, { schema: ({ data }) { console.log(Generating schema with min: ${data.min}, max: ${data.max}); return z.object({ summary: z .string() .min(data.min, Summary must be at least ${data.min} characters) .max(data.max, Summary must be at most ${data.max} characters), }); }, }, ),工作流输入min/max带默认值50 / 150既约束了 prompt 的措辞又通过z.string().min().max()在输出侧强制执行长度校验实现prompt 约束 Schema 强校验的双保险。这种数据驱动 Schema模式特别适合参数化、可复用的 Agent 步骤。七、时间控制andSleep 与 andSleepUntil示例 5timed-reminder演示两个时间原语源码见 and-sleep.ts 与 and-sleep-until.tsandSleep({ id: pause-briefly, duration: ({ data }) Math.max(0, data.waitMs), }), andSleepUntil({ id: align-to-next-second, date: () new Date(Date.now() 1000), }), andThen({ id: complete-reminder, execute: async ({ data }) ({ userId: data.userId, status: sent, resumedAt: new Date().toISOString(), }), }),andSleep.duration既可以是毫秒数字也可以是接收上下文的函数示例用Math.max(0, data.waitMs)动态计算休眠时长andSleepUntil.date接收上下文的函数返回目标时刻示例将其对齐到下一秒Date.now() 1000从 and-sleep.ts 的实现可以看到休眠通过waitWithSignal(durationMs, state.signal)实现支持被取消信号中断不会在取消时白白等待。八、批量处理与循环andForEach、andMap、andDoWhile、andDoUntil8.1andForEachandMap批量变换示例 6batch-transform的工作流输入直接是一个数字数组input: z.array(z.number())先用andForEach对每个元素并发执行步骤再用andMap汇总结果andForEach({ id: double-each, step: andThen({ id: double, execute: async ({ data }) data * 2, }), concurrency: 2, }), andMap({ id: summarize-results, map: { original: { source: input }, doubled: { source: data }, count: { source: fn, fn: ({ data }) (Array.isArray(data) ? data.length : 0), }, total: { source: fn, fn: ({ data }) Array.isArray(data) ? data.reduce((sum, value) sum value, 0) : 0, }, }, }),从 and-foreach.ts 源码可见concurrency默认值为 1内部通过worker 池模式实现并发——concurrency会被规范化为至少 1 的整数Math.max(1, Math.floor(concurrency))支持可选的items选择数组与map逐项塑形参数空数组时直接返回[]不会执行任何子步骤。andMap提供三种取值来源source: input取工作流原始输入、source: data取上游步骤数据、source: fn由函数计算非常适合批量处理 结果聚合的流水线。8.2andDoWhile/andDoUntil条件循环示例 7loop-and-branch先用两个循环原语构造计数器状态andDoWhile({ id: warmup-loop, step: andThen({ id: increment-warmup, execute: async ({ data }) ({ ...data, counter: data.counter 1 }), }), condition: ({ data }) data.counter 1, }), andDoUntil({ id: retry-loop, step: andThen({ id: increment-retry, execute: async ({ data }) ({ ...data, counter: data.counter 1 }), }), condition: ({ data }) data.counter 3, }),andDoWhile先执行后判断只要condition为真就继续循环至少执行一次andDoUntil先执行后判断直到condition为真才退出适合重试直到成功类场景。8.3andBranch并行条件分支紧接着andBranch根据当前counter值分发到不同分支andBranch({ id: categorize-counter, branches: [ { condition: ({ data }) data.counter 3, step: andThen({ id: mark-ready, execute: async ({ data }) ({ ...data, label: ready as const }), }), }, { condition: ({ data }) data.counter 3, step: andThen({ id: mark-warmup, execute: async ({ data }) ({ ...data, label: warmup as const }), }), }, ], }),需要特别注意的是andBranch的语义见 and-branch.ts所有条件会被并行评估Promise.all所有条件命中的分支都会执行结果以数组形式返回。因此在本示例的最后一个andThen中代码需要从结果数组里挑选实际命中的分支输出andThen({ id: select-branch, execute: async ({ data }) { const results Array.isArray(data) ? data : []; const selected results.find((entry) entry ! undefined); if (!selected) { return { counter: 0, label: warmup }; } return { counter: selected.counter, label: selected.label }; }, }),如果只需要二选一的互斥分支应保证各分支条件互斥如 3与 3这正是示例的做法。九、护栏Guardrail输入输出安全过滤示例 8guardrail-workflow演示了 VoltAgent 的护栏机制可在工作流级与步骤级对输入输出做校验/改写。首先定义两个护栏const trimInput createInputGuardrail({ name: trim-input, handler: async ({ input }) ({ pass: true, action: modify, modifiedInput: typeof input string ? input.trim() : input, }), }); const redactNumbers createOutputGuardrailstring({ name: redact-numbers, handler: async ({ output }) ({ pass: true, action: modify, modifiedOutput: output.replace(/[0-9]/g, *), }), });随后在createWorkflow配置中挂载工作流级护栏并在步骤中追加步骤级护栏const guardrailWorkflow createWorkflow( { id: guardrail-workflow, name: Guardrail Workflow, purpose: Applies guardrails to sanitize inputs and outputs, input: z.string(), result: z.string(), inputGuardrails: [trimInput], outputGuardrails: [redactNumbers], }, andGuardrail({ id: sanitize-step, outputGuardrails: [redactNumbers], }), andThen({ id: finish, execute: async ({ data }) data, }), );要点createInputGuardrail/createOutputGuardrail分别创建输入、输出护栏handler返回{ pass, action: modify, modifiedInput/modifiedOutput }表示校验通过但内容被改写此处把字符串首尾空格裁掉、把数字替换为*工作流级inputGuardrails/outputGuardrails对工作流入口、出口全局生效andGuardrail可在步骤级别插入护栏实现局部敏感数据脱敏核心运行逻辑见 packages/core/src/workflow/internal/guardrails.ts并有 guardrails.spec.ts 测试覆盖。十、包装 Agent 调用在自定义步骤中直接使用 Agent示例 9wrapped-agent-call演示了不用andAgent、也能在自定义步骤中调用 Agent的灵活写法——即在andThen内部直接调用agent.generateTextandThen({ id: maybe-call-agent, execute: async ({ data }) { if (!data.useAgent) { return { summary: Skipped agent for ${data.topic}., usedAgent: false, }; } const { text } await contentAgent.generateText( Write a single-sentence summary about: ${data.topic}, ); return { summary: text.trim(), usedAgent: true, }; }, }),这体现了工作流的开放性andAgent是结构化输出 Schema 强校验的便捷封装而直接调用agent.generateText则把 Agent 调用完全交给开发者控制例如按条件跳过、组合多次调用。从源码结构与示例注释看这种调用方式还继承了父步骤的 OpenTelemetry span便于链路追踪对应wrappedAgentWorkflow注释中的 parent span inheritance。十一、把工作流接入 VoltAgent 运行时所有工作流最终统一注册进VoltAgent实例并配合日志与服务器const logger createPinoLogger({ name: with-workflow, level: debug, }); new VoltAgent({ agents: { analysisAgent, contentAgent }, logger, server: honoServer({ port: 3141 }), workflows: { orderProcessingWorkflow, expenseApprovalWorkflow, contentAnalysisWorkflow, articleSummarizationWorkflow, timedReminderWorkflow, batchTransformWorkflow, loopAndBranchWorkflow, guardrailWorkflow, wrappedAgentWorkflow, }, });agents注册工作流中引用的 AgentanalysisAgent、contentAgent供andAgent与generateText解析logger使用voltagent/logger的createPinoLogger此处设为debug级别以获得更细的步骤执行日志servervoltagent/server-hono的honoServer({ port: 3141 })提供 HTTP 服务便于通过接口触发与查看工作流workflows按 id 注册全部 9 个工作流。核心层通过WorkflowRegistry见 packages/core/src/workflow/registry.ts统一管理已注册工作流。十二、工作流全家桶更多原语与 Chaining API除本文详解的步骤外packages/core/src/workflow/index.ts 还导出了其他编排原语可供进阶探索andWhen条件式步骤示例 1 注释中提及的 conditional logic (andWhen)andAll并行执行多个步骤andRace多个步骤竞争先完成者胜出andWorkflow把一个工作流作为另一个工作流的子步骤实现嵌套编排。另外示例 README 特别提示如果你更喜欢**流式链式调用method-chaining**的写法可以查看 with-workflow-chain 示例——它使用createWorkflowChain以流畅的链式 API 构建工作流与本文介绍的createWorkflow函数式写法互为补充。十三、源码与测试指引如果想深入理解工作流引擎的实现建议按以下路径阅读当前仓库工作流核心实现packages/core/src/workflow/core.tscreateWorkflow、挂起/恢复、状态管理与取消信号步骤原语源码packages/core/src/workflow/steps/ 目录覆盖and-then.ts、and-agent.ts、and-tap.ts、and-sleep.ts、and-foreach.ts、and-branch.ts、and-loop.ts、and-map.ts、and-guardrail.ts、and-race.ts、and-when.ts等测试用例如 core.spec.ts、suspend-resume.spec.ts、guardrails.spec.ts 以及 steps 目录下的各*.spec.ts可帮助你验证各原语的真实行为边界。总结VoltAgent 的工作流模块在AI 的开放性与业务的确定性之间提供了优雅的折中andThen/andTap负责确定性的业务逻辑andAgent负责接入 LLM 并借助 zod 保证结构化输出suspend/resume引入人工决策andSleep*处理时间维度andForEach/andBranch/andDoWhile覆盖批量、分支与循环护栏机制则为输入输出安全兜底。通过 with-workflow 示例 的 9 个完整工作流你可以快速掌握这套编排能力并将其迁移到自己的 Agent 业务中。赞分享人工智能AI AgentAgent 框架后端多智能体RAG工具调用Agent 记忆【免费下载链接】voltagentAI Agent Engineering Platform built on an Open Source TypeScript AI Agent Framework项目地址https://gitcode.com/gh_mirrors/vo/voltagent点击查看免费下载相关推荐Memviz终极指南如何用可视化图表调试Go数据结构Memviz终极指南如何用可视化图表调试Go数据结构 Memviz是一款强大的Go数据结构可视化工具能够将复杂的Go程序内存结构以直观的图表形式展示出来帮用 VoltAgent 的 createWorkflowChain 以链式 API 编排 AI Agent 工作流用 VoltAgent 的 createWorkflowChain 以链式 API 编排 AI Agent 工作流 导读 VoltAgent 是一个开源的 Ty人工智能AI AgentAgent 框架后端多智能体RAG工具调用Agent 记忆Agent 工作流AI 评测MCP 服务MCP Clients语音构建复杂的多步骤AI工作流ell高级编程完全指南构建复杂的多步骤AI工作流ell高级编程完全指南 在当今AI应用开发中构建能够处理复杂多步骤任务的智能系统已成为关键需求。ell作为专业的语言模型编程库提人工智能大模型提示工程LLMOps上一篇Lucide Vue 图标尺寸调整完全指南size 属性与 CSS 控制详解下一篇基于 Splunk 检测横向移动Lateral Movement实战指南SPL 查询、事件源映射与脚本化狩猎参考创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表