javascript
{
"agent_id": "personnel_business_agent",
"supervisor_prompt": "# 人事业务主图(前端自治版本)\n\n你是一名人事业务工作流编排助手。根据用户语言识别意图,动态调度 Worker 完成业务。\n\n可用 Workers:\n- employee_onboard: 员工入职子流程。职责:校验员工信息完整性 → 校验工号/部门有效性 → 统一参数校验 → 创建新员工。\n\n- employee_transfer: 员工异动(部门调整)子流程。职责:匹配目标员工 → 输入目标部门 → 执行部门调整。\n\n- employee_offboard: 员工离职子流程。职责:匹配目标员工 → 确认离职类型和时间 → 执行离职操作。\n\n- employee_info_maintain: 员工信息维护子流程。职责:匹配员工 → 获取信息 → 并行校验 → 用户确认 → 执行修改。\n\n- employee_info_query: 员工信息查询子流程。职责:接收搜索条件 → 执行AND逻辑检索 → 返回人员信息。\n\n\n规则:\n1. 根据用户语言识别意图,返回 action=\"execute\" 和对应的 next_worker。\n2. 如果用户指令模糊或缺失关键信息,返回 action=\"clarify\" 和友好的澄清提示语。\n3. 当已完成的 Workers 足以满足用户请求时,返回 action=\"complete\"。\n\n输出 JSON 格式:\n{\n \"action\": \"execute\" | \"clarify\" | \"complete\",\n \"next_worker\": \"...\",\n \"worker_inputs\": {...},\n \"clarification_prompt\": \"...\"\n}\n",
"workers": [
{
"id": "employee_onboard",
"description": "员工入职子流程。职责:校验员工信息完整性 → 校验工号/部门有效性 → 统一参数校验 → 创建新员工。\n",
"worker_id": "sg_employee_onboard",
"entry": "validate_name_integrity",
"outputs": [
"status",
"person_id",
"details"
],
"inputs": null,
"dependencies": null,
"schema": {
"type": "object",
"properties": {
"person_name": {
"type": "string",
"nullable": true,
"description": "员工姓名"
},
"surname": {
"type": "string",
"nullable": true,
"description": "姓"
},
"given_name": {
"type": "string",
"nullable": true,
"description": "名"
},
"person_code": {
"type": "string",
"nullable": true,
"description": "工号"
},
"department_name": {
"type": "string",
"nullable": true,
"description": "部门名称"
},
"entry_date": {
"type": "string",
"nullable": true,
"description": "入职日期"
},
"email": {
"type": "string",
"nullable": true,
"description": "邮箱"
},
"phone": {
"type": "string",
"nullable": true,
"description": "电话"
},
"gender": {
"type": "string",
"nullable": true,
"description": "性别"
},
"position": {
"type": "string",
"nullable": true,
"description": "职位"
},
"user_query": {
"type": "string",
"nullable": true,
"description": "用户原始查询语句"
},
"user_selections": {
"type": "object",
"nullable": true,
"description": "用户在前端的选择结果"
}
},
"required": []
}
},
{
"id": "employee_transfer",
"description": "员工异动(部门调整)子流程。职责:匹配目标员工 → 输入目标部门 → 执行部门调整。\n",
"worker_id": "sg_employee_transfer",
"entry": "match_employee",
"outputs": [
"status",
"person_id",
"details"
],
"inputs": null,
"dependencies": null,
"schema": {
"type": "object",
"properties": {
"person_name": {
"type": "string",
"nullable": true,
"description": "员工姓名"
},
"person_code": {
"type": "string",
"nullable": true,
"description": "工号"
},
"target_department_name": {
"type": "string",
"nullable": true,
"description": "目标部门名称"
},
"user_query": {
"type": "string",
"nullable": true,
"description": "用户原始查询语句"
},
"user_selections": {
"type": "object",
"nullable": true,
"description": "用户在前端的选择结果"
}
},
"required": []
}
},
{
"id": "employee_offboard",
"description": "员工离职子流程。职责:匹配目标员工 → 确认离职类型和时间 → 执行离职操作。\n",
"worker_id": "sg_employee_offboard",
"entry": "match_employee",
"outputs": [
"status",
"person_id",
"details"
],
"inputs": null,
"dependencies": null,
"schema": {
"type": "object",
"properties": {
"person_name": {
"type": "string",
"nullable": true,
"description": "员工姓名"
},
"person_code": {
"type": "string",
"nullable": true,
"description": "工号"
},
"offboard_type": {
"type": "string",
"nullable": true,
"description": "离职类型,默认辞职"
},
"offboard_date": {
"type": "string",
"nullable": true,
"description": "离职日期,默认当天"
},
"user_query": {
"type": "string",
"nullable": true,
"description": "用户原始查询语句"
},
"user_selections": {
"type": "object",
"nullable": true,
"description": "用户在前端的选择结果"
}
},
"required": []
}
},
{
"id": "employee_info_maintain",
"description": "员工信息维护子流程。职责:匹配员工 → 获取信息 → 并行校验 → 用户确认 → 执行修改。\n",
"worker_id": "sg_employee_info_maintain",
"entry": "validate_employee_exists",
"outputs": [
"status",
"person_id",
"details"
],
"inputs": null,
"dependencies": null,
"schema": {
"type": "object",
"properties": {
"person_name": {
"type": "string",
"nullable": true,
"description": "员工姓名"
},
"person_code": {
"type": "string",
"nullable": true,
"description": "工号"
},
"update_fields": {
"type": "object",
"nullable": true,
"description": "需要修改的字段及值"
},
"user_query": {
"type": "string",
"nullable": true,
"description": "用户原始查询语句"
},
"user_selections": {
"type": "object",
"nullable": true,
"description": "用户在前端的选择结果"
}
},
"required": []
}
},
{
"id": "employee_info_query",
"description": "员工信息查询子流程。职责:接收搜索条件 → 执行AND逻辑检索 → 返回人员信息。\n",
"worker_id": "sg_employee_info_query",
"entry": "query_employee_info",
"outputs": [
"status",
"total",
"persons"
],
"inputs": null,
"dependencies": null,
"schema": {
"type": "object",
"properties": {
"person_name": {
"type": "string",
"nullable": true,
"description": "姓名"
},
"person_code": {
"type": "string",
"nullable": true,
"description": "工号"
},
"department_name": {
"type": "string",
"nullable": true,
"description": "部门"
},
"card_no": {
"type": "string",
"nullable": true,
"description": "卡号"
},
"status": {
"type": "string",
"nullable": true,
"description": "人员状态"
},
"user_query": {
"type": "string",
"nullable": true,
"description": "用户原始查询语句"
},
"user_selections": {
"type": "object",
"nullable": true,
"description": "用户在前端的选择结果"
}
},
"required": []
}
}
],
"dependencies": {}
}
这是一个基于 AI Agent(智能体)架构的人事业务工作流编排配置(Schema)。
简单来说,它是一套给 AI "大脑"使用的说明书。通过这份配置,AI 能够理解如何处理关于员工入职、调动、离职、修改信息及查询的指令。
以下是该配置的详细拆解:
1. 核心身份(Agent Role)
- Agent ID :
personnel_business_agent(人事业务助手)。 - 职责 :它扮演的是"中枢调度员"的角色。它的任务不是直接去数据库改数据,而是听懂用户的意图,然后决定把活儿分给哪个具体的"执行员"(Worker)。
2. 五大业务模块(Workers)
该 Agent 下挂载了 5 个专门处理特定业务的"工具人":
employee_onboard(入职):负责新员工入职流程,包括姓名、工号、部门、入职日期等信息的校验和录入。employee_transfer(异动):处理员工跨部门调动,只需匹配员工并指定目标部门。employee_offboard(离职):处理离职手续,记录离职类型和日期。employee_info_maintain(信息维护):修改员工的现有信息(如改电话、改邮箱等)。employee_info_query(信息查询):通过姓名、工号、部门等条件进行搜索。
3. 工作逻辑(Workflow Rules)
配置中定义了 AI 的决策逻辑(即 supervisor_prompt 里的规则):
- 执行(execute):如果用户意图明确(例如"帮我办理张三入职"),AI 直接调度对应的 Worker。
- 澄清(clarify):如果用户说得太模糊(例如"帮我改一下信息",没说改谁,也没说改什么),AI 会返回一段提示语向用户追问。
- 完成(complete):当所有步骤执行完毕,AI 告诉前端流程结束。
4. 技术特征
- 结构化输入(Schema) :每个模块都严格定义了需要的参数(如
person_name,person_code等),这确保了 AI 在调用后台接口时数据格式是标准的。 - 前端自治版本:这表明该系统设计为"前端驱动",AI 返回 JSON 格式的指令,由前端页面根据指令决定下一步是弹出确认框、显示搜索结果,还是继续引导用户填表。
- AND 逻辑检索:在查询模块中特别注明了多条件查询采用"且"关系。
5. 应用场景举例
- 用户说:"王小明今天入职研发部,工号是 1001。"
- AI 处理 :
- 识别为
employee_onboard意图。 - 提取参数:姓名=王小明,部门=研发部,工号=1001。
- 返回 JSON:
{"action": "execute", "next_worker": "employee_onboard", "worker_inputs": {...}}。 - 系统自动跳转到入职校验流程。
- 识别为
总结: 这是一个典型的人机交互(LUI)后台管理系统配置,通过 LLM(大语言模型)将复杂的 HR 业务流程简化为对话式操作。
为了让你更清晰地理解这个系统是如何工作的,
我们可以模拟三个典型的应用场景:直接执行(入职) 、需要澄清(调动) 、以及精准查询。
以下是完整的交互逻辑展示:
场景一:直接执行(信息完整)
用户输入: "帮我给新入职的王小明办下入职手续,工号是 HR007,今天入职,分配到研发部。"
- AI 内部意图识别:
- 意图:员工入职 (
employee_onboard) - 提取实体:姓名=王小明,工号=HR007,部门=研发部,日期=2023-10-27(假设当前日期)
- 意图:员工入职 (
- AI 返回的 JSON:
json
{
"action": "execute",
"next_worker": "employee_onboard",
"worker_inputs": {
"person_name": "王小明",
"person_code": "HR007",
"department_name": "研发部",
"entry_date": "2023-10-27",
"user_query": "帮我给新入职的王小明办下入职手续,工号是 HR007,今天入职,分配到研发部。"
},
"clarification_prompt": ""
}
- 后续动作: 系统前端收到该指令,自动跳转到"入职办理"界面,并自动填好了上述信息,等待确认提交。
场景二:需要澄清(缺失关键信息)
用户输入: "把张三调到市场部去。"
- AI 内部意图识别:
- 意图:员工异动 (
employee_transfer) - 提取实体:目标部门=市场部,姓名=张三
- 发现问题: 同名同姓的人可能很多,且系统中通常需要"工号"或"当前部门"来精准匹配张三。
- 意图:员工异动 (
- AI 返回的 JSON:
json
{
"action": "clarify",
"next_worker": "employee_transfer",
"worker_inputs": {
"person_name": "张三",
"target_department_name": "市场部"
},
"clarification_prompt": "系统中查询到多个名叫'张三'的员工,请问您指的是哪一个?或者请输入他的工号以便我准确办理。"
}
- 后续动作: 前端对话框直接弹出"澄清提示语",引导用户提供更精准的信息。
场景三:信息维护(更新特定字段)
用户输入: "工号为 1024 的程序员李四换手机号了,新号码是 13800138000。"
- AI 内部意图识别:
- 意图:信息维护 (
employee_info_maintain) - 提取实体:工号=1024,姓名=李四,更新内容=手机号
- 意图:信息维护 (
- AI 返回的 JSON:
json
{
"action": "execute",
"next_worker": "employee_info_maintain",
"worker_inputs": {
"person_code": "1024",
"person_name": "李四",
"update_fields": {
"phone": "13800138000"
},
"user_query": "工号为 1024 的程序员李四换手机号了,新号码是 13800138000。"
},
"clarification_prompt": ""
}
- 后续动作: 系统调起"信息维护子流程",自动定位到工号 1024 的员工,并准备修改其
phone字段。
场景四:综合查询
用户输入: "帮我找一下研发部所有还在职的员工。"
- AI 内部意图识别:
- 意图:员工查询 (
employee_info_query) - 提取实体:部门=研发部,状态=在职
- 意图:员工查询 (
- AI 返回的 JSON:
json
{
"action": "execute",
"next_worker": "employee_info_query",
"worker_inputs": {
"department_name": "研发部",
"status": "在职",
"user_query": "帮 me 找一下研发部所有还在职的员工。"
},
"clarification_prompt": ""
}
- 后续动作: 系统执行数据库查询,前端以列表或卡片形式展示所有符合条件的员工名单。
总结
这个架构的核心价值在于:
- 容错性 :如果用户说得不清不楚,AI 不会报错,而是通过
clarify进行追问。 - 结构化:无论用户说话多随意,输出永远是整齐的 JSON,方便程序员写后端代码。
- 自动化:自动识别该调哪个子流程(Worker),无需用户在复杂的 ERP 菜单里层层点击。
要让这套"人事业务主图"真正运转起来,需要将 AI 调度中心(Supervisor)、业务执行单元(Workers)和前端界面三者有机结合。
以下是实现这一工作流的四个核心步骤:
第一步:意图识别与分发(中枢指挥)
当用户输入一句话时,你的 Supervisor Agent 首先介入。它不执行具体的业务,只负责"看地图"和"指路"。
- 接收输入:用户说:"张三要离职。"
- 匹配 Worker :Supervisor 查阅
workers列表,发现employee_offboard最匹配。 - 提取参数 :AI 从一句话中提取出
person_name: "张三"。 - 下达指令 :输出 JSON,告知系统执行
employee_offboard,并带上参数。
第二步:子流程的内部流转(Worker 协作)
每个 Worker 内部其实是一个微型工作流 。根据你提供的 JSON,每个 Worker 都有 entry(入口点)和一套职责。
以 employee_onboard(入职) 为例,它的工作流是线性的:
- 触发点 :接收到
execute指令。 - 数据校验 :调用
validate_name_integrity(校验姓名是否完整)。 - 合法性检查:检查工号是否重复、部门是否存在。
- 业务处理:一切 OK 后,调用后台接口"创建新员工"。
- 反馈结果 :输出
status: "success"和person_id。
第三步:多轮对话与状态保持(动态纠偏)
工作流最难的是处理"信息不全"。这时候需要 Supervisor 和 User 之间的反复横跳:
- 场景:用户说:"帮我办入职。"
- AI 识别 :动作是
onboard,但缺少姓名、部门。 - 状态切换 :AI 返回
action: "clarify",提示语为"请问入职员工的姓名和部门是什么?" - 前端处理:前端对话框显示提示语,并保持当前的业务上下文。
- 用户补全:用户回答:"李四,财务部。"
- 工作流继续 :AI 将新信息与旧信息合并,再次发送
execute指令给 Worker。
第四步:前端自治调度(实现自动化)
由于你这个版本是"前端自治版本",这意味着 前端代码(如 React/Vue)扮演了"调度员"角色:
- 前端监听:前端捕获 AI 返回的 JSON。
- 逻辑判断 :
- 如果
action === "clarify":直接弹出气泡询问用户。 - 如果
action === "execute":- 前端根据
next_worker的 ID(如sg_employee_onboard),去调用对应的 API 或渲染对应的表单。 - 将
worker_inputs里的值自动填入表单。
- 前端根据
- 如果
- 界面反馈 :当 Worker 执行成功返回
status后,前端调用 AI 的complete动作,并提示用户:"办理成功,员工 ID 是 XXX。"
总结:完整的工作流逻辑图
#mermaid-svg-pRIW3hUg30JMRSRp{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-pRIW3hUg30JMRSRp .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-pRIW3hUg30JMRSRp .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-pRIW3hUg30JMRSRp .error-icon{fill:#552222;}#mermaid-svg-pRIW3hUg30JMRSRp .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-pRIW3hUg30JMRSRp .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-pRIW3hUg30JMRSRp .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-pRIW3hUg30JMRSRp .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-pRIW3hUg30JMRSRp .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-pRIW3hUg30JMRSRp .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-pRIW3hUg30JMRSRp .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-pRIW3hUg30JMRSRp .marker{fill:#333333;stroke:#333333;}#mermaid-svg-pRIW3hUg30JMRSRp .marker.cross{stroke:#333333;}#mermaid-svg-pRIW3hUg30JMRSRp svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-pRIW3hUg30JMRSRp p{margin:0;}#mermaid-svg-pRIW3hUg30JMRSRp .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-pRIW3hUg30JMRSRp .cluster-label text{fill:#333;}#mermaid-svg-pRIW3hUg30JMRSRp .cluster-label span{color:#333;}#mermaid-svg-pRIW3hUg30JMRSRp .cluster-label span p{background-color:transparent;}#mermaid-svg-pRIW3hUg30JMRSRp .label text,#mermaid-svg-pRIW3hUg30JMRSRp span{fill:#333;color:#333;}#mermaid-svg-pRIW3hUg30JMRSRp .node rect,#mermaid-svg-pRIW3hUg30JMRSRp .node circle,#mermaid-svg-pRIW3hUg30JMRSRp .node ellipse,#mermaid-svg-pRIW3hUg30JMRSRp .node polygon,#mermaid-svg-pRIW3hUg30JMRSRp .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-pRIW3hUg30JMRSRp .rough-node .label text,#mermaid-svg-pRIW3hUg30JMRSRp .node .label text,#mermaid-svg-pRIW3hUg30JMRSRp .image-shape .label,#mermaid-svg-pRIW3hUg30JMRSRp .icon-shape .label{text-anchor:middle;}#mermaid-svg-pRIW3hUg30JMRSRp .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-pRIW3hUg30JMRSRp .rough-node .label,#mermaid-svg-pRIW3hUg30JMRSRp .node .label,#mermaid-svg-pRIW3hUg30JMRSRp .image-shape .label,#mermaid-svg-pRIW3hUg30JMRSRp .icon-shape .label{text-align:center;}#mermaid-svg-pRIW3hUg30JMRSRp .node.clickable{cursor:pointer;}#mermaid-svg-pRIW3hUg30JMRSRp .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-pRIW3hUg30JMRSRp .arrowheadPath{fill:#333333;}#mermaid-svg-pRIW3hUg30JMRSRp .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-pRIW3hUg30JMRSRp .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-pRIW3hUg30JMRSRp .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pRIW3hUg30JMRSRp .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-pRIW3hUg30JMRSRp .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pRIW3hUg30JMRSRp .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-pRIW3hUg30JMRSRp .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-pRIW3hUg30JMRSRp .cluster text{fill:#333;}#mermaid-svg-pRIW3hUg30JMRSRp .cluster span{color:#333;}#mermaid-svg-pRIW3hUg30JMRSRp div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-pRIW3hUg30JMRSRp .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-pRIW3hUg30JMRSRp rect.text{fill:none;stroke-width:0;}#mermaid-svg-pRIW3hUg30JMRSRp .icon-shape,#mermaid-svg-pRIW3hUg30JMRSRp .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pRIW3hUg30JMRSRp .icon-shape p,#mermaid-svg-pRIW3hUg30JMRSRp .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-pRIW3hUg30JMRSRp .icon-shape .label rect,#mermaid-svg-pRIW3hUg30JMRSRp .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pRIW3hUg30JMRSRp .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-pRIW3hUg30JMRSRp .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-pRIW3hUg30JMRSRp :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 信息不足
意图明确
入职
异动
查询
成功
报错
用户输入
Supervisor Agent
Clarify: 追问用户
执行对应的 Worker
Worker: Onboard
Worker: Transfer
Worker: Query
调用后端业务 API
Complete: 流程结束并反馈
搭配建议:
- 上下文关联 :在传输
worker_inputs时,务必带上user_query(原始语句),这样在 Worker 内部如果需要二次处理,AI 能参考上下文。 - 用户确认环节 :在执行"离职"或"修改信息"这种高危操作时,Worker 的流转中应加入一个
User Confirmation(人工确认)节点,不要只靠 AI 直接修改数据库。 - 错误处理:如果 Worker 执行时发现后端接口报错(如部门已撤销),应将错误信息反馈给 Supervisor,让它用自然语言向用户解释。
和子图如何关联起来
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' },
],
};
这段代码定义了一个 Worker 的具体执行逻辑图(Workflow Graph)。
如果说你之前提供的 JSON 是"地图"(告诉 AI 有哪些路可以走),那么这段代码就是其中一条路的详细导航步骤(告诉系统在执行"员工管理"这个具体任务时,第一步干什么,第二步干什么)。
1. 这是什么?
这是一个基于 DAG(有向无环图) 的工作流定义。它定义了一个名为 worker_manage_employee 的复合子流程,专门处理"录入员工"+"修改手机号"的组合业务。
- 节点 (Nodes):代表具体的动作(调接口、弹窗、给用户看结果)。
- 边 (Edges):代表执行顺序。
- 数据绑定 (Data Bind):代表信息如何在步骤之间传递(例如把第一步搜到的 ID 给第五步用)。
2. 它如何与前面的 Supervisor 搭配?
它们是 "统帅"与"士兵" 的关系:
-
Supervisor(统帅 - 你之前提供的 JSON):
- 负责听用户的话(自然语言)。
- 决定派哪个 Worker 出场。
- 比如用户说:"帮我录入张三,顺便改下他的手机号。" Supervisor 识别后,会指向这个
worker_manage_employee。
-
Worker Graph(士兵 - 这段代码):
- 负责按部就班地执行任务。
- 它不关心用户说的是中文还是英文,它只负责运行
add_person->search_person等预设好的节点。
3. 完整的执行流程(业务视角)
假设用户输入:"帮我录入王五,他的手机号好像填错了,帮我改一下。"
第一阶段:中枢调度(Supervisor)
- AI 识别到这是一个复合需求(录入+修改)。
- AI 匹配到
worker_id: worker_manage_employee。 - AI 将用户原始话语放入
inputs.user_query。
第二阶段:子图执行(这段代码的工作流)
-
节点
add_person(Action):- 系统调用
add_person工具,尝试把王五存入数据库。 - 结果存入
add_result。
- 系统调用
-
节点
search_person(Action):- 系统紧接着调用查询工具,确认王五的信息(可能是为了获取他在数据库里的
person_id)。 - 结果存入
search_result。
- 系统紧接着调用查询工具,确认王五的信息(可能是为了获取他在数据库里的
-
节点
display_status(Render):- 前端介入 :屏幕上弹出一个
EmployeeAddCard卡片,展示刚才录入的王五信息。 - 用户看到:"王五已录入成功"。
- 前端介入 :屏幕上弹出一个
-
节点
input_phone(Interrupt - 关键点):- 工作流中断 :系统停下来,弹出一个
PhoneInputCard输入框。 - 人机交互:界面显示:"无法修改王五手机号,请回复我新的号码"。
- 用户在界面输入
13912345678并点击确认。此时流程才会继续。
- 工作流中断 :系统停下来,弹出一个
-
节点
edit_phone(Action):- 系统获取用户刚才输入的号码,调用
edit_employee_phone工具。 - 使用
data_bind自动从上一步(phone_input)拿到新号码和 ID。
- 系统获取用户刚才输入的号码,调用
-
节点
display_summary(Render):- 结束反馈 :弹出
EmployeeResultCard,显示"入职及手机号修改已全部完成"。
- 结束反馈 :弹出
4. 核心亮点说明
- Interrupt(中断机制) :
input_phone节点非常重要。它允许工作流在执行中途停下来,等待人工干预。这解决了 AI 无法自行决定某些关键信息(如新手机号)的问题。 - Data Binding(数据流转) :你可以看到
edit_phone的data_bind引用了tool_outputs.phone_input.userSelections。这就像接力棒,不需要全局变量,每个步骤只拿它需要的数据。 - 自治性:前端收到这个 Graph 定义后,可以全自动地渲染 UI(卡片、输入框),不需要后端频繁下指令,极大地提高了交互流畅度。
总结
Supervisor 负责**"找对人",而这个 Worker Graph 负责"把事办稳"**。通过这种搭配,你可以用非常结构化的方式,处理非常复杂的自然语言需求。