百积木文档
功能指南

工作流

创建、修改和验证工作流,说明节点类型、连线规则、启动和执行记录。

工作流用于把多个业务步骤串成可追踪、可重试的自动化流程。它适合审批、线索跟进、报表生成、消息通知、跨系统同步,以及需要把智能体、模块方法和人工确认组合起来的场景。

机器可读入口

本页同时发布为 Markdown。不要从 HTML 内嵌数据反推结构。以下链接只用于读取历史版本,不是当前 CLI 作者输入格式。当前引用结构以本页为准;人工节点请使用IssueDefinition 开发教程的定义和节点示例,不要混用旧 Schema:

当前作者定义通过领域目录选择对象:Module 使用 module: {bundleId, moduleId},Agent 使用 agent: {bundleId, agentKey},子流程使用 workflow: {bundleId, workflowKey}。这些身份必须直接使用目录返回值,不能从显示名称推导。引用必须位于当前 Bundle 的源清单或显式依赖闭包内;源清单为对象选择精确版本。CLI 自动读取 Bundle 绑定项目的 Git 提交,服务端按这一快照校验和编译引用,作者无需填写源提交或内部资源定位字段。

方法名和参数合同仍从目标工作区当前 Runtime 的 methodDefinition 获取。安装物化由平台完成,作者只选择对象和版本。历史 Bundle Resource Locator 属于内部安装合同,不能复制到当前作者定义。创建 Workflow 前只需冻结其实际引用的对象;Bundle 中尚未引用的应用或模块不会阻塞这一步。

同一 Bundle 中,每个稳定 workflowCode 只有一份可变作者定义。服务端 revision 只用于乐观并发控制和审计,不是作者字段、资源版本或 CLI 查询选择器;不可变发布使用严格 SemVer:

baijimu bundle workflow list --workspace-id <WORKSPACE_ID> <bundle> --json
baijimu bundle workflow get --workspace-id <WORKSPACE_ID> <bundle> <workflowCode> --json
baijimu bundle workflow create --workspace-id <WORKSPACE_ID> <bundle> --definition @workflow.json --json
baijimu bundle workflow update --workspace-id <WORKSPACE_ID> <bundle> --definition @workflow.json --json
baijimu bundle workflow publish --workspace-id <WORKSPACE_ID> <bundle> <workflowCode> <semanticVersion> --json

get --json 返回标准 CModel 响应,完整定义位于顶层 data 字段中的 definition;同层的 object 包含 type: "WORKFLOW" 与 Owner 返回的 workflowKey。本页示例描述 create/update --definition 接受的可写文档,不包含响应 envelope 以及 idbundleId、时间戳、当前 Plan 等只读字段;从 get 结果生成更新文件时,只复制 definition 中的作者字段,不复制 envelope 或内部 ID。

创建工作流

创建工作流时,先确定流程的输入、输出和触发方式,再设计节点。

  1. 进入目标工作区,确认当前账号具备工作流管理权限。
  2. 新建工作流,填写名称、稳定编码和描述。
  3. 定义启动输入,例如客户信息、表单数据、订单 ID、触发来源。
  4. 添加 start 节点和业务节点。
  5. 使用连线连接节点,并在需要分支的位置设置连线条件。
  6. 设置各节点的输出合同和写入路径;Agent 使用 result.type + result.path,其他节点按各自合同配置。
  7. 保存后启动一次测试实例,查看执行记录。

条件写在连线上

工作流不再使用独立的 condition 节点表达分支。分支判断应写在节点之间的连线条件里,避免流程图出现只负责转发的判断节点。

节点类型

节点类型用途关键配置
start流程入口。节点 ID、名称、启动输入约定。
end流程结束并整理输出。输出字段、输出路径。
http调用外部 HTTP 接口。请求方法、URL、请求头、请求体、超时、重试。
wait等待外部 signal(推荐)或按计划轮询 HTTP/Runtime 状态。signalstate + until 二选一、超时、输出路径。
module_method调用已安装 Bundle Module 的方法。module.bundleId + module.moduleId、方法名、参数、超时、重试、输出路径。
emit_event调用已安装 Bundle Module 声明的事件方法。module.bundleId + module.moduleId、事件名、事件体、幂等键。
agent调用 Bundle 中的智能体资源。agent.bundleId + agent.agentKey、任务消息、结构化结果合同、完成等待策略。
human按 IssueDefinition 创建并等待人工事项。IssueDefinition 精确资源版本、显式输入、候选主体、result.path
subflow调用并等待子流程完成,使用子流程结果。workflow.bundleId + workflow.workflowKey、输入、元数据、超时、输出路径。
join汇合并发分支。汇合策略、输出路径。
for_each顺序遍历数组并运行内嵌节点。数组路径、迭代变量、上限、失败策略、内嵌节点。

类型、配置与输出合同

节点的 type 表示处理或执行类型,例如 humanhttpagent;它不等于节点的业务输出类型。4.0.0 删除了 runtimeKindscope,4.1.0 为公开 wait 增加了 signal 模式,5.0.0 把 Agent 节点统一为 message + result + executionPolicy;合同继续使用封闭的强类型节点集合,未知节点类型和未知字段会被 CLI、workflow-engine 与 workflow-worker 拒绝。signal_wait 仅存在于编译后的内部 Plan,作者定义和管理界面都不得直接创建它。

多数节点使用 outputPath 指定结果位置;Agent 使用 result.type + result.path,human 使用 IssueDefinition 的 outputType 和节点的 result.path。结果类型属于实际调用合同,不能由下游猜测。

subflow:等待子流程结果

subflow 是流程内的组合调用:子流程完成后,父流程才继续该节点的后续连线,outputPath 接收子流程结果。 子流程包含 human 时,父流程也必须等待人工处理结束。timeoutSecs 控制等待超时,不表示后台执行。 节点不接受 waitForCompletion,不论值是 true 还是 false

{
  "type": "subflow",
  "id": "review_report",
  "workflow": {"bundleId": "operations", "workflowKey": "report-review"},
  "input": {"reportId": "{{input.reportId}}"},
  "outputPath": "reportReview"
}

示例中的 Bundle 和工作流身份必须替换为领域目录返回值。

如果主检查流程在报告落库后就应结束,应在报告落库后发布业务事件,由 Event Trigger 启动独立的人工处理流程。 完整配置、输入映射和安装步骤见 Event Trigger 绑定工作流与输入映射。 发布节点成功表示事件发布调用成功,不表示人工待办已经创建或处理完成。人工处理失败由其独立流程记录和处置。

迁移旧定义时,显式 waitForCompletion: true 可移除;false 必须先改成事件触发的独立流程。 已发布资源应从作者源修改后重新发布和安装,不直接改写不可变定义或运行中的快照。

human:先创建业务事项定义,再引用

human 创建事项后异步等待人工提交;异步表示等待状态可以持久化和恢复,并不表示节点或所在 Workflow 已完成。 如果业务要求报告生成后当前 Workflow 就结束,人工处理应由业务事件触发独立流程。并发分支、joinwait.signal 都不能替代这一业务边界。

没有合适的定义时,开发者应在自己的 Bundle 中创建 ISSUE_DEFINITION,无需等待平台提供专用定义。 完整步骤和配套 JSON 见人工事项定义开发: 声明 inputType/outputType → 创建并发布资源精确版本 → 配置 human → 将 IssueDefinition 和 Workflow 加入 Bundle → 发布并安装 → 验证人工提交与下游结果。

workflow.human_task 不是默认依赖。通用定义的输出合同不可见,不应阻塞创建自己的业务定义。

  • issueDefinition 指定 bundleId + issueDefinitionId + semanticVersion,精确版本必须与 Bundle 源清单或依赖闭包一致。
  • input 显式映射到事项输入,不会隐式发送整个 Workflow 输入和上下文。
  • assignment.modecandidates 时,assignment.candidates 必须非空。对工作区成员开放领取须显式使用 workspace_members
  • 候选主体支持 user / department / group / roleidentityType: "user"identityId 来自有效用户目录;identityType: "role" 使用稳定 roleKey,角色成员按当前有效关系解析。部门候选不自动包含子部门。
  • 候选池决定谁可领取,领取或转交后的唯一处理者记录在 Issue.assignee
  • 输出结构由所引用 IssueDefinition 的 outputType 拥有。result.path 只配置落点,不配置 result.type 或节点级 outputSchema
  • 不使用旧的 formSchemaroleinstructionsplannerProjection、顶层 candidates/outputPath 字段。
  • 人工等待期限使用 executionPolicy.completionTimeoutSecs,与 HTTP 超时不同。

assignment.candidates 当前必须是显式 JSON 数组;每项 identityId 可以用 {{context.ownerLookup.reviewerUserId}} 引用前置节点的单个用户 ID,但不能把整个候选数组写成表达式。 单人候选仍需领取,human 当前没有直接设置 Issue.assignee 的分配模式。 完整示例及错误说明见从前置节点读取候选人

下面展示角色候选节点;实际领域身份和版本应替换为业务资源发布结果:

{
  "type": "human",
  "id": "approve_order",
  "input": {
    "orderId": "{{input.orderId}}"
  },
  "assignment": {
    "mode": "candidates",
    "candidates": [
      {
        "identityType": "role",
        "identityId": "crm.sales"
      }
    ]
  },
  "result": {
    "path": "approval"
  },
  "issueDefinition": {
    "bundleId": "example-crm",
    "issueDefinitionId": "order.approval",
    "semanticVersion": "1.0.0"
  }
}

Issue 服务按资源版本的 inputType 校验输入、按 outputType 校验人工提交的 resultPayload。 校验通过后由平台回传结果,写入 context.approval 并推进节点;下游消费该定义实际声明的字段。 不存在通用的“批准/拒绝”输出约定,不通过公开 wait.signal 接口绕过人工事项。

wait 的两种模式

公开的 wait 节点保留一个类型,但配置必须二选一:

  • signal 模式(推荐):配置 signal 和可选 timeoutSecs。worker 持久化等待状态后释放执行资源,由有权限的业务动作提交 signal 唤醒,不持续占用线程,也不产生周期性 HTTP 请求。
  • 轮询模式:配置 stateuntil、可选 failWhenschedule。只用于目标系统不能主动通知、也不能可靠产生事件的兼容场景;每次探测都会形成实际执行成本。

signal 名称分为成功、失败和取消三组,同一个名称不能跨组重复。successSignalNames 为空表示任何发往该节点的 signal 都成功完成等待;生产定义通常应填写明确名称,避免业务事件含义不清。signal payload 会成为等待节点的输出,并按 outputPath 写入上下文。

{
  "type": "wait",
  "id": "wait_for_inspection_review",
  "signal": {
    "successSignalNames": ["COMPLETED"],
    "failureSignalNames": ["FAILED"],
    "cancellationSignalNames": ["CANCELLED", "STOPPED"]
  },
  "timeoutSecs": 3600,
  "outputPath": "inspection.review"
}

向公开 signal 等待节点提交消息时,调用当前工作区的 POST /workflow-engine/workspaces/{workspaceId}/workflow/signals,不要填写或保存 worker 主机地址:

{
  "namespace": "workflow.node",
  "correlationKey": "instance:{instanceId}:node:{nodeId}",
  "signalName": "COMPLETED",
  "payload": {
    "decision": "approved"
  },
  "dedupeKey": "inspection-review:{businessEventId}"
}

workspaceId 来自当前授权工作区,instanceIdnodeId 来自实例执行记录,dedupeKey 必须稳定标识同一次业务提交。服务端会校验实例属于该工作区、目标确实是作者定义中的 wait.signal,并拒绝借此唤醒 Agent、Human 或其他平台内部等待。调用方不能自选内网地址、内部 namespace 或伪造其他工作区目标。

Agent 节点也使用同一持久化等待原语,但其 signal 由 agent-session 的事务 outbox 自动投递。workflow-engine 在编译时只生成平台内部逻辑节点;agent-session 到 workflow-worker 的地址来自环境资源登记和服务依赖注入,不写入 Workflow 定义,也不在编译时固化某台主机。Agent 完成、失败、停止或取消后都会触发对应终态 signal,worker 恢复流程并只读取一次最终消息。Capability Signal 合同 1.1.0 使用 nodeId 定位节点、signalName 表示事件名称;旧调用未传 nodeId 时仍按原合同解释。

agent 配置合同

字段必填含义
type固定为 agent
id工作流定义内唯一且稳定的节点 ID;运行时用它与实例 ID 派生内部会话 ID。
agent从目录选择的 {bundleId, agentKey}
message发给 Agent 的任务消息,可引用 inputcontext
result.type平台统一的低代码 Type;可使用 RefType 引用命名类型,也可内联匿名 DataType
result.path结果写入 context 的路径;省略时使用节点 ID。
executionPolicy.completionTimeoutSecs等待 Agent 会话进入终态的最长秒数,默认 300;不表示单次 HTTP 请求超时。

result.type 与模块 Interface 使用的是同一个平台 Type 合同,不是 Workflow 自定义 Schema。 创建 Runtime Projection 时,平台使用统一类型解析器将 RefType 物化为具体 DataType; Agent 只接收物化后的 Type,并由适配层转换为模型厂商的 结构化输出参数及执行返回后的本地校验规则。解析结果属于 Workflow Runtime Projection, 不会再写入 Bundle Runtime Plan,也不会引入第二套类型定义。

workspaceIduserIdsessionId 均由运行时从受信上下文确定,不是工作流作者参数。 Agent 节点只创建工作区级会话,不支持 projectIdprojectIdPath。项目 ID 如属于任务业务 数据,可以在 message 中引用,但不会改变会话归属、身份、计费主体或授权边界。

4.x Schema 中的 promptTemplateoutputFormatprojectIdPathworkspaceIdPathuserIdPathsessionIdTemplate 和节点级 timeoutSecs 已被 5.0.0 删除,不存在双读、别名或兼容优先级。 Agent 资源的创建、发布和 Manifest 引用见 Bundle Agent 定义、发布与 Workflow 引用

{
  "type": "agent",
  "id": "review_order",
  "message": "审核订单 {{input.orderId}}",
  "result": {
    "path": "reviews.order",
    "type": {
      "@type": "DataType",
      "type": "object",
      "properties": {
        "approved": {
          "@type": "DataType",
          "type": "boolean"
        },
        "reason": {
          "@type": "DataType",
          "type": "string"
        }
      }
    }
  },
  "executionPolicy": {
    "completionTimeoutSecs": 600
  },
  "agent": {
    "bundleId": "example",
    "agentKey": "order-reviewer"
  }
}

module_method 配置合同

字段必填含义
type固定为 module_method
id工作流定义内唯一且稳定的节点 ID。
module从目录选择的 {bundleId, moduleId}
method该服务当前 methodDefinition 中声明的方法名。
params与当前方法参数合同一致的 JSON;可引用运行时数据。
timeoutSecs非负整数超时秒数。
retryPolicymaxAttempts、初始/最大延迟和退避倍数。
outputPath节点结果写入 context 的路径。

下面是可保存为 workflow.json 的完整作者定义。示例对象身份、方法和参数均为占位值;真正提交前必须替换为目录返回的对象身份和目标 Runtime 返回的精确方法合同。旧 5.0.0 Schema 不适用于此作者文档。

{
  "code": "operations-analysis",
  "name": "运营分析示例",
  "description": "演示 module_method 整理输入、Agent 生成结构化分析报告并由 end 输出的完整流程。",
  "status": "draft",
  "startNodeId": "start",
  "inputSchema": [
    {
      "name": "period",
      "type": {
        "@type": "DataType",
        "type": "string",
        "nullable": false
      },
      "description": "分析周期"
    }
  ],
  "outputSchema": {
    "@type": "DataType",
    "type": "object",
    "properties": {
      "analysis": {
        "@type": "DataType",
        "type": "object"
      }
    },
    "required": [
      "analysis"
    ],
    "nullable": false
  },
  "nodes": [
    {
      "type": "start",
      "id": "start",
      "name": "开始"
    },
    {
      "type": "module_method",
      "id": "collect_analysis_input",
      "name": "获取并整理分析输入",
      "method": "buildAnalysisInput",
      "params": {
        "period": "{{input.period}}"
      },
      "timeoutSecs": 30,
      "retryPolicy": {
        "maxAttempts": 3,
        "initialDelayMs": 1000,
        "maxDelayMs": 5000,
        "backoffMultiplier": 2
      },
      "outputPath": "analysisInput",
      "module": {
        "bundleId": "example-operations",
        "moduleId": "operations-data"
      }
    },
    {
      "type": "agent",
      "id": "analyze_operations",
      "name": "生成分析、建议和报告",
      "message": "请基于 {{context.analysisInput}} 完成分析,给出建议并生成可供后续节点消费的报告。",
      "result": {
        "path": "analysisReport",
        "type": {
          "@type": "DataType",
          "type": "object",
          "properties": {
            "summary": {
              "@type": "DataType",
              "type": "string"
            },
            "recommendations": {
              "@type": "DataType",
              "type": "array",
              "items": {
                "@type": "DataType",
                "type": "string"
              }
            },
            "report": {
              "@type": "DataType",
              "type": "string"
            }
          },
          "required": [
            "summary",
            "recommendations",
            "report"
          ]
        }
      },
      "executionPolicy": {
        "completionTimeoutSecs": 600
      },
      "agent": {
        "bundleId": "example-operations",
        "agentKey": "operations-analyst"
      }
    },
    {
      "type": "end",
      "id": "end",
      "name": "结束",
      "output": {
        "analysis": "{{context.analysisReport}}"
      }
    }
  ],
  "edges": [
    {
      "from": "start",
      "to": "collect_analysis_input"
    },
    {
      "from": "collect_analysis_input",
      "to": "analyze_operations"
    },
    {
      "from": "analyze_operations",
      "to": "end"
    }
  ],
  "tags": [
    "example",
    "agent"
  ]
}

emit_event 配置合同

emit_event 发布已安装 Module 声明的类型化事件。它与模块后端使用的是同一个 Runtime 事件方法,不保存 或调用固定主机地址:

字段必填含义
type固定为 emit_event
id工作流定义内唯一且稳定的节点 ID。
module从目录选择的 {bundleId, moduleId}
eventName目标 Module 当前版本声明的事件名。
payload与事件 paramDefinitions 一致的 JSON,可引用运行时数据。
idempotencyKey同一次业务发布的稳定幂等键。
timeoutSecs事件方法调用的超时秒数。
{
  "type": "emit_event",
  "id": "emit_inspection_submitted",
  "eventName": "inspectionTaskSubmitted",
  "payload": {
    "taskId": "{{input.taskId}}",
    "submittedAt": "{{context.inspection.submittedAt}}"
  },
  "idempotencyKey": "inspection:{{input.taskId}}:submitted",
  "timeoutSecs": 30,
  "module": {
    "bundleId": "example-supervision",
    "moduleId": "supervision"
  }
}

Workflow 作者不得填写 Runtime businessId、HTTP URL、内部主机或 Authorization。安装物化会从当前 Runtime 的 Bundle 安装资源解析服务并生成授权;通用 http 节点不能替代这一步。Module 事件声明、独立 后端回调发布和订阅触发的完整边界见 模块事件与发布机制

节点数据引用

节点配置可以引用运行时根对象中的数据:

引用含义
input启动流程实例时传入的数据。
context前序节点写入的输出和流程运行状态。
signal等待节点收到的运行时提交消息;它不是输出结构的定义来源。
instance当前流程实例元信息。
node当前节点元信息,例如节点 ID 和类型。

例如模块方法节点可以把 input.customerName 传给创建线索方法,再把结果写入 context.crm.createLead,后续节点再读取该路径。

配置连线

连线决定节点执行顺序。普通顺序流只需要连接前后节点;分支流需要设置条件;并发流需要在多个分支后使用 join 汇合。

设计连线时注意:

  • 每个流程必须有且只有一个清晰的起点。
  • end 节点外,业务节点应有明确后继节点。
  • 分支条件要互斥或有默认路径,避免流程停在无匹配路径。
  • 并发分支需要明确汇合策略,避免部分分支失败后状态不清。

修改工作流

修改工作流前,先确认变更是否影响已经运行中的实例。

  • 只改名称、描述、节点展示文案,通常可以直接保存。
  • 改节点 ID、输出路径、方法名、参数结构,会影响后续节点读取数据,应重新跑完整测试。
  • 改分支条件、人工节点引用的 IssueDefinition 或外部调用,必须覆盖成功、拒绝、超时、失败重试等路径。
  • 已经有线上实例运行时,不要直接删除它们正在等待的 humanjoin 节点。

完成修改并验证后,以新的精确 SemVer 发布不可变资源版本,由后续安装或升级引用新版本;已启动实例继续使用其固定的执行快照,不回读后来修改的作者定义。

启动和推进实例

工作流保存后,可以从页面、后端服务、模块方法、定时任务、Webhook 或外部 API 启动实例。启动时传入的 input 应包含业务主键、工作区上下文和触发来源,方便排查日志。

手动启动和查询示例:

baijimu runtime workflow start --workspace-id <WORKSPACE_ID> \
  <APPLICATION_RUNTIME_ID> <environmentKey/bundleId/WORKFLOW/workflowCode> \
  --input @input.json --metadata '{"source":"manual"}' --json
baijimu runtime workflow list --workspace-id <WORKSPACE_ID> \
  --application-runtime-id <APPLICATION_RUNTIME_ID> --json
baijimu runtime workflow get --workspace-id <WORKSPACE_ID> <INSTANCE_ID> --json
baijimu runtime workflow executions --workspace-id <WORKSPACE_ID> <INSTANCE_ID> --json

执行用户来自平台验证后的可信请求上下文,并作为 executionSubjectUserId 固定在 Workflow 实例上。 Timer 链路中,这个用户来自安装时生成的 ServiceReference 授权绑定;后续 module_method 调用继续 使用实例保存的执行用户。--metadata 只传递触发来源等可观测信息,其中的 metadata.requestUserId 会被删除,不能声明或覆盖执行用户。

当流程停在 human 节点时,在对应人工事项中提交符合精确版本 IssueDefinition.outputType 的结果。平台校验后回传 signal,并按 human 的 result.path 写入 context;用户不直接调用公开 signal 接口推进 human。

查看执行记录

每次实例运行都会生成节点执行记录。排查问题时按这个顺序看:

  1. 实例状态:运行中、等待人工、失败、完成或取消。
  2. 当前节点或失败节点。
  3. 节点入参和输出。
  4. HTTP、模块方法、事件或智能体调用日志。
  5. 重试记录和错误信息。

失败实例应从失败节点重试,而不是重新启动一个无关联的新实例。等待人工的实例必须通过 signal 推进,不能用普通恢复动作绕过人工决策。

查询权限

查询对象CLI权限规则
Bundle Workflow 作者定义bundle workflow list/get目标工作区的有效成员可查询;创建、修改、删除和发布仍要求 Bundle 所有者或工作区 owner / admin
已安装 Bundle 和 Workflow 资源台账bundle list/get/resourceslist 对工作区有效成员返回其可见的活跃安装;getresources 要求工作区 owneradmin
Workflow 实例runtime workflow list/get有效签名用户必须是目标工作区成员;实例必须属于该工作区
节点执行记录runtime workflow executions与实例查询相同;实例必须属于目标工作区
Timer 状态和执行记录runtime app timer status/executions有效签名用户必须是目标工作区成员;Application Runtime 必须属于该工作区

这些接口不接受调用方自报的 userId 作为权限凭据。CLI 登录凭证必须有效,--workspace-id 必须 指向当前用户已经加入的工作区;需要查看完整安装详情或资源台账时,由工作区所有者把用户设为 owneradmin

发布前检查

  • 每个节点 ID 稳定、可读,不与其他节点重复。
  • 所有模块方法对应的模块已经由目标 Bundle 在工作区 Runtime 中物化成功;不要单独安装模块。
  • 所有 HTTP 节点的鉴权、超时和错误返回可追踪。
  • 所有人工节点都选择了正确且已发布的 IssueDefinition,其表单、处理规则和提交结果合同清楚。
  • 所有分支至少覆盖成功、失败和默认路径。
  • 测试实例能完成一遍真实业务路径,并能在执行记录中看到每个节点的结果。

本页内容