以代码构建工作流
使用 Python 和 JavaScript SDK 构建、编辑并进行版本控制智能体工作流
概览
工作流以节点和边组成的图结构存储。手动编写该图意味着你需要自行确保边 ID、edge_order 列表和条件对象保持一致。Python 和 JavaScript SDK 中的 Workflow 构建器让你可以通过链式方法调用描述同一图结构,然后生成 agents.create() 和 agents.update() 已支持的 workflow 值。
可用于:
- 通过代码构建工作流,并像审查其他代码变更一样审查它。
- 加载智能体工作流,更改一个节点后推送回去,而不影响图中的其他部分。
- 将工作流以 JSON 格式存入版本控制,并在 CI 中验证。
构建器完全在 SDK 内运行。它不会调用新的 API 端点,构建的任何内容都可以 在控制台的可视化编辑器中打开和编辑。
要求
- Python:使用
elevenlabs包。构建器从elevenlabs.agent_workflows导入。 - JavaScript:使用
@elevenlabs/elevenlabs-js包。构建器从包根目录导出。
构建工作流
Workflow 对象代表起始节点。每个动词方法都会添加一个节点并返回该节点,因此你可以从该节点继续链式调用下一步:
路由方法决定哪条边通向下一个节点:
直接在工作流上调用的动词方法会通过无条件边从起始节点分支。以下示例将来电者路由至订单查询;如果查询失败,则重试身份识别;并转接 VIP 或感到沮丧的来电者:
build() 会验证整个图并返回请求模型。它还会:
- 为起始节点分配 API 所需的 ID
start_node。 - 生成
source__target格式的边 ID。 - 按添加边的顺序填充每个节点的
edge_order。 - 为所有未设置位置的节点定位,使图在可视化编辑器中从左到右排列。
将工作流写成一条链
up() 会返回当前节点链式调用所来自的节点,因此你可以在一个表达式中描述整个工作流,而无需将每个节点存入变量。在单条链中,请使用带节点 ID 的 go_to() / goTo(),因为没有可传入的变量:
对于通过 wf.node(id) 获取的节点句柄,up() 会返回第一条进入该节点的边所来自的节点。对于起始节点,它会返回起始节点。
节点选项
Python 中的可选设置通过关键字参数传入,JavaScript 中则通过末尾的选项对象传入。其名称与 API 中节点字段一致:
如果要自行放置节点,每个动词方法还接受 position。Python 中的 Workflow(prevent_subagent_loops=True),或 JavaScript 中的 new Workflow({ preventSubagentLoops: true }),会阻止对话再次进入已访问过的子智能体。
转接目标
条件
when() 接受普通字符串、Condition 或 Expr:
- 字符串是 LLM 条件:由 LLM 决定其是否成立。
Condition.llm(text, label=...)的作用相同,但会在可视化编辑器的边上显示标签。使用Condition.expr(expr, label=...)为表达式添加标签。Expr会根据动态变量求值,无需调用 LLM。
使用 Expr.variable(name) 和 Expr.literal(value) 构建表达式。通过 eq、neq、gt、gte、lt 和 lte 比较,通过 add、sub、mul 和 div 进行算术运算。通过 all_of / allOf、any_of / anyOf 和 if_else / ifElse 组合表达式。普通值会自动包装为 Expr.literal()。Expr.llm(description) 会要求 LLM 从对话中提取一个值;传入 type 和 enum 可获取字符串、数字或固定集合中的一个值,而不是布尔值。
循环和反向边
API 允许任意两个节点之间存在一条边,方向不限。要让对话沿原路返回,请使用 back 为该边提供反向条件:
go_to() / goTo() 会为你处理常见情况。当目标节点已有一条边指向当前节点时,新边会成为该边的反向条件。在第一个示例中,failed.go_to(identify) 会作为 identify → lookup_order 边的反向条件发送。相同两个节点之间的任何其他第二条边,以及从节点指向自身的任何边,都会导致验证失败。
编辑现有智能体
Workflow.from_agent() / Workflow.fromAgent() 会加载由 agents.get() 返回的智能体工作流。节点 ID、边 ID、编辑器位置和边顺序都会保留,因此推送回去时只会更改你修改的内容。
insert_between() / insertBetween() 会将一个携带被替换边条件的分支传入你的函数。函数返回其添加的最后一个节点,随后该节点会连接到原始目标。该方法返回该节点;若两个节点之间没有边,则返回 None / undefined。
在版本控制中存储工作流
to_json_string() / toJSONString() 会以 API 的传输格式写入工作流:使用 snake_case 键、每一级排序,并以 2 个空格缩进。它与 REST API 和 CLI 使用的结构相同,且两个 SDK 对相同工作流写出的文件逐字节一致,因此差异会保持很小。Workflow.from_json() / Workflow.fromJSON() 会将其读回,也接受包含 workflow 键的完整智能体配置,例如 CLI 的 agent_configs/ 目录中的文件。
典型设置:
可视化工作流
CLI 会将工作流文件绘制为流程图,因此无需打开控制台即可检查代码构建的内容。它接受由 to_json_string() / toJSONString() 写入的纯工作流文件,或带有 workflow 键的智能体配置:
默认情况下,它会在终端中绘制方框和箭头,每条边的条件都会在边上编号,并在下方图例中完整列出。使用 --format mermaid 可改为输出 Mermaid 源码,或使用 --format mermaid-md 将其包装在 GitHub 可渲染的围栏代码块中,例如用于拉取请求评论:
该命令仅读取本地文件,因此无需 API 密钥,也可在 CI 中运行。
验证
链式调用本身不会失败。build()、to_json() / toJSON() 和 to_json_string() / toJSONString() 会检查整个图,并引发或抛出一个 WorkflowValidationError。其 issues 列表会列出每个问题,每项都包含 code、message 以及相关的 node_id / nodeId。
错误包括:
- 相同两个节点之间存在两条边,或存在从节点指向自身的边。
- 指向起始节点的边,或从结束节点发出的边。
- 从工具节点发出但并非成功或失败边的边,或从任何其他类型节点发出的成功或失败边。
- 两个节点具有相同 ID,或存在指向不存在节点的边。
无法从起始节点到达的节点会通过 on_warning / onWarning 报告为警告,但不会阻止构建。
比 SDK 更新的节点类型
从 API 或文件加载的工作流可能包含 SDK 版本尚未识别的节点类型。它们会通过 from_json() / fromJSON() 和 to_json_string() / toJSONString() 原样往返保留,且 build() 会将每个此类节点报告为警告。类型化请求模型无法携带它们,因此请升级 SDK,或直接发送传输格式: