工作流(Worker/Graph)配置对象如何解读、子图

javascript 复制代码
const workerManageEmployee: WorkerDefinition = {
  worker_id: 'worker_manage_employee',
  graph_id: 'graph_manage_employee',
  entry: 'add_person',
  description: '员工录入和手机号修改复合子图',
  nodes: [
    {
      id: 'add_person',
      type: 'action',
      config: { mcp_tool: 'add_person', timeout: 30000, wait_result: true },
      data_bind: ['inputs.user_query'],
      output_key: 'add_result',
      error: { fallback: 'END', retry: 1 },
    },
    {
      id: 'search_person',
      type: 'action',
      config: { mcp_tool: 'search_employee', timeout: 30000, wait_result: true },
      data_bind: ['inputs.user_query'],
      output_key: 'search_result',
      error: { fallback: 'END', retry: 1 },
    },
    {
      id: 'display_status',
      type: 'render',
      config: { component: 'EmployeeAddCard', confirm_required: false },
      data_bind: ['tool_outputs.add_result.person|new_person', 'tool_outputs.search_result.target_person|target_person'],
      output_key: 'display_result',
      error: { fallback: 'END', retry: 0 },
    },
    {
      id: 'input_phone',
      type: 'interrupt',
      config: { component: 'PhoneInputCard', message: '无法修改王五的手机号,请回复我新的号码直接帮你更改。', confirm_required: true },
      data_bind: ['tool_outputs.search_result.target_person|person'],
      output_key: 'phone_input',
      error: { fallback: 'END', retry: 0 },
    },
    {
      id: 'edit_phone',
      type: 'action',
      config: { mcp_tool: 'edit_employee_phone', timeout: 30000, wait_result: true },
      data_bind: [
        'tool_outputs.phone_input.userSelections.phone_number|phone_number',
        'tool_outputs.phone_input.userSelections.person_id|person_id',
      ],
      output_key: 'edit_result',
      error: { fallback: 'END', retry: 1 },
    },
    {
      id: 'display_summary',
      type: 'render',
      config: { component: 'EmployeeResultCard', confirm_required: false },
      data_bind: ['tool_outputs.add_result|add_result', 'tool_outputs.edit_result|edit_result'],
      output_key: 'summary_result',
      error: { fallback: 'END', retry: 0 },
    },
  ],
  edges: [
    { from: 'add_person', to: 'search_person', type: 'direct' },
    { from: 'search_person', to: 'display_status', type: 'direct' },
    { from: 'display_status', to: 'input_phone', type: 'direct' },
    { from: 'input_phone', to: 'edit_phone', type: 'direct' },
    { from: 'edit_phone', to: 'display_summary', type: 'direct' },
    { from: 'display_summary', to: 'END', type: 'direct' },
  ],
};

解释一下上述代码:

这段代码定义了一个名为 workerManageEmployee工作流(Worker/Graph)配置对象。它通常用于 AI Agent 框架(如 LangGraph 的变体或类似的低代码大模型编排系统)中,用来规定 AI 如何处理"员工录入"和"修改手机号"的任务。

我们可以把这个代码看作是一张流程图的描述文件。以下是详细拆解:

1. 核心元数据 (Metadata)

  • worker_id / graph_id: 这个工作流的唯一标识符。
  • entry : 入口点。流程从 add_person 节点开始。
  • description: 描述了它的功能:复合处理"录入"和"修改"逻辑。

2. 节点解析 (Nodes) ------ 流程中的每一步

流程一共包含 6 个步骤,分为三种类型:action(后台操作)、render(前端展示)、interrupt(人工干预)。

  1. add_person (Action):

    • 做什么 : 调用名为 add_personMCP 工具(Model Context Protocol,一种大模型工具调用标准)。
    • 数据 : 它从用户的原始提问 (user_query) 中提取信息并尝试新增员工。
    • 输出 : 结果存入 add_result
  2. search_person (Action):

    • 做什么: 紧接着去搜索员工(可能是为了确认录入是否成功,或者查找现有员工)。
    • 输出 : 结果存入 search_result
  3. display_status (Render):

    • 做什么 : 在界面上渲染一个名为 EmployeeAddCard 的 UI 组件。
    • 数据绑定: 把前面新增的结果和搜索到的结果传给这个卡片展示给用户看。
  4. input_phone (Interrupt):

    • 关键点 : 这是一个中断节点
    • 做什么 : 流程会停在这里,等待用户操作。它弹出一个 PhoneInputCard(手机号输入卡片),并提示用户:"无法修改王五的手机号,请回复我新的号码..."。
    • 目的: 获取用户手动输入的新手机号。
  5. edit_phone (Action):

    • 做什么 : 当用户输入完手机号后,流程继续,调用 edit_employee_phone 工具。
    • 数据绑定 : 它从上一步用户在卡片里填写的 phone_numberperson_id 中取值。
  6. display_summary (Render):

    • 做什么 : 最后展示一个 EmployeeResultCard 总结卡片,列出新增和修改的最终状态。

3. 执行逻辑 (Edges) ------ 线条如何连接

edges 定义了节点之间的指向,这里的逻辑非常线性(Sequential):

add_personsearch_persondisplay_statusinput_phone (停下等用户) → edit_phonedisplay_summaryEND (结束)

4. 代码亮点与特性

  • MCP Tool : 使用了 mcp_tool 配置,说明这是一个遵循 Anthropic 提出的 Model Context Protocol 标准的系统,具有很强的工具集成能力。
  • 数据绑定 (Data Binding) : 使用了类似 | 的语法(如 person_id|person_id),这是一种映射机制,将上一步的输出字段映射到下一步的输入参数。
  • 容错处理 (Error Handling) : 每个节点都有 error: { fallback: 'END', retry: 1 }。如果某一步报错,它会尝试重试一次;如果还不行,就直接跳到 END 结束流程,防止程序死循环或崩溃。
  • 人机协作 (Human-in-the-loop) : 通过 interrupt 节点,完美实现了"AI 处理 -> 发现需要人工确认 -> 停下等人工 -> 拿到输入继续处理"的闭环。

总结

这是一个自动化程度很高且具备交互能力的员工管理脚本。它不仅让 AI 去后台数据库操作数据(Add/Search/Edit),还通过前端卡片(Render)与用户沟通,并在关键环节(Input Phone)请求人类干预。

详细介绍一下nodes 和 edges 有哪些属性

根据你提供的代码片段,这是一个典型的**声明式工作流(Declarative Workflow)**定义。这种结构通常用于大模型编排框架(如 LangGraph, Flowise, 或企业自定义的 Agent 引擎)。

下面我为你详细拆解 nodes(节点)和 edges(边)包含的各项属性及其含义:


一、 Nodes(节点)属性详解

节点是工作流中的基本执行单元。

属性名 类型 说明
id String 唯一标识符 。用于在 edges 中引用该节点,或在日志中追踪。
type String 节点类型 。常见取值: 1. action: 执行具体逻辑(调用 API/工具)。 2. render: 渲染 UI 界面(给前端看的卡片)。 3. interrupt: 中断流,等待人类输入(Human-in-the-loop)。
config Object 配置参数 。根据 type 的不同,内容也不同: - mcp_tool: 要调用的工具名称。 - timeout: 超时时间(毫秒)。 - wait_result: 是否等待结果返回。 - component: 前端组件名。 - message: 提示文案。 - confirm_required: 是否需要用户点击确认。
data_bind Array 数据绑定/输入映射 。定义该节点需要从哪些地方获取数据。 语法通常为:`源路径
output_key String 输出存储键。该节点执行完后,结果会以这个名字存入工作流的"上下文(Context)"中,供后续节点使用。
error Object 容错策略 : - fallback: 出错后跳转到哪个节点(如 END 表示直接结束)。 - retry: 自动重试次数。

二、 Edges(边)属性详解

边定义了节点之间的流转路径,即"接下来该做什么"。

属性名 类型 说明
from String 起始节点 ID。流程从哪个节点流出。
to String 目标节点 ID 。流程指向哪个节点。特殊值 END 表示流程彻底结束。
type String 流转类型 : 1. direct: 直接流转,上一步完了立即执行下一步。 2. conditional: (虽然代码中没写,但通常会有)条件流转,根据上一步的结果判断走哪条路。

三、 深度解析:特殊的语法设计

1. 数据管道中的 | (Pipe) 语法

data_bind 中,你会看到类似:

'tool_outputs.phone_input.userSelections.phone_number|phone_number'

  • 前半部分 (tool_outputs...):是路径,代表数据从哪里来。
  • 后半部分 (phone_number):是变量名,代表数据注入到工具或组件时的参数名。
  • 意义 :这实现了解耦,工具不需要知道数据是谁给的,只需要拿到名为 phone_number 的参数即可。
2. 中断与恢复逻辑 (type: 'interrupt')

这是 Agent 系统的高级特性:

  • 当执行到 input_phone 节点时,后端会暂停运行,并把 config 里的 component(卡片)推送到前端。
  • 工作流状态会被持久化。
  • 直到用户在前端填完手机号并提交,后端接收到信号后,才会根据 edges 里的指向,带着新数据进入 edit_phone 节点。
3. 错误降级 (fallback: 'END')

这是一种安全机制。在 add_person 节点中,如果后台接口挂了:

  • 它不会导致整个系统崩溃。
  • 它会尝试重试 1 次。
  • 如果还失败,直接跳到 END,给用户一个友好的报错或结束语。

总结这个配置的逻辑流:

  1. 录入 (add_person)
  2. 查询确认 (search_person)
  3. 展示给用户看 (display_status)
  4. 发现需要填手机号,停下来问用户 (input_phone)
  5. 用户填完后,执行修改 (edit_phone)
  6. 展示最终报告 (display_summary)
  7. 完事 (END)

edges 定义了节点之间的指向 那里看出了input_phone需要停下等用户

这是一个非常敏锐的观察!

从代码本身来看,edges 确实看不出"停下来" 。在 edges 定义中,input_phoneedit_phone 的类型依然是 direct(直接流转)。

真正决定"停下来等用户"的逻辑,不在 edges(边)上,而在 nodes(节点)的类型定义上。

以下是详细解释:

1. 关键在于 type: 'interrupt'

nodes 数组中,input_phone 节点的定义如下:

javascript 复制代码
{
  id: 'input_phone',
  type: 'interrupt', // <--- 关键在这里
  config: { 
    component: 'PhoneInputCard', 
    confirm_required: true // <--- 强化了中断逻辑
  },
  ...
}
  • type: 'interrupt' :这是工作流引擎的一个预设逻辑。当引擎解析到类型为 interrupt 的节点时,它会执行"挂起"操作。
  • 它的底层逻辑是
    1. 引擎运行到这一步。
    2. 发现是中断类型,于是将当前的整个流程状态(State)序列化并存入数据库。
    3. 向前端发送 UI 组件指令(PhoneInputCard)。
    4. 停止执行后续代码,释放服务器资源,进入休眠状态。

2. 为什么 edges 还是 direct

javascript 复制代码
{ from: 'input_phone', to: 'edit_phone', type: 'direct' }

这里的 type: 'direct' 描述的是 逻辑上的先后关系 ,而不是 执行上的瞬时关系

它的意思是:"一旦 input_phone 节点被成功完成(即用户填完表单并点击了提交),接下来的唯一目标 就是 edit_phone。"

你可以这样理解:

  • Edges (边) 是地图上的"路",它告诉程序:从 A 城只能去 B 城。
  • Nodes (节点) 是路上的"关卡"。interrupt 就像一个红灯关卡,哪怕路(Edge)是直通的,你也必须在关卡前停下,等"绿灯"(用户提交)亮了才能继续走完这条路。

3. 如何"唤醒"流程?

虽然代码里没写,但在这种架构中,通常会有一个隐含的 回调机制

  1. 用户在前端 PhoneInputCard 填好手机号,点击"提交"。
  2. 前端发起一个 API 请求,带上刚才的 worker_id 和用户输入的数据。
  3. 后端工作流引擎根据 ID 找到之前挂起的流程,把用户填的数据填入 phone_inputoutput_key 中。
  4. 引擎点击"开始"键,顺着 edge 定义的 direct 路径,走到 edit_phone

4. 辅助证据:数据来源

你再看 edit_phone 节点的数据绑定:

javascript 复制代码
data_bind: [
  'tool_outputs.phone_input.userSelections.phone_number|phone_number', 
]

这里的 userSelections 也是一个强烈的信号。在很多低代码 AI 框架中,userSelections 专门用来接收 UI 组件中用户的手动输入。如果没有"停下来等用户",AI 自身是无法生成这个字段的数据的。

总结

  • edges 负责控制 "谁接在谁后面"(结构)。
  • nodestype: 'interrupt' 负责控制 "执行到这里要不要停"(运行时行为)。
相关推荐
向日的葵0061 小时前
vue3路由的replace属性(四)
前端·javascript·vue.js·vue路由
阿猫的故乡1 小时前
Vue模板引用和组件暴露:ref拿DOM、defineExpose调方法,案例多到眼花
前端·javascript·vue.js
ZC跨境爬虫11 小时前
跟着 MDN 学JavaScript day_7:数学运算与逻辑判断实战测试
开发语言·前端·javascript·学习·ecmascript
凌云拓界11 小时前
文件管理:让AI安全操作你的电脑 ——CogitoAgent开发实战(三)
javascript·人工智能·架构·开源·node.js
凌云拓界11 小时前
联网能力:让AI看见更广阔的世界 ——CogitoAgent开发实战(四)
javascript·人工智能·架构·node.js·创业创新
HYCS13 小时前
用pixi.js实现fabric.js(六):从线性代数的角度理解编辑器交互
前端·javascript·canvas
you458013 小时前
学成在线--day02 CMS前端开发(含Vue基础知识得回顾)
前端·javascript·vue.js
想吃火锅100513 小时前
【leetcode】1.两数之和js版
javascript·算法·leetcode
xiaofeichaichai13 小时前
虚拟 DOM
前端·javascript·vue.js