人工事项定义(IssueDefinition)开发
创建人工事项定义并配置 human,支持前置节点用户数组、单人自动分配和多人领取,并说明原有候选主体配置。
IssueDefinition 是 Bundle 拥有的 ISSUE_DEFINITION 资源,定义人工事项的输入、输出和处理规则。
没有满足业务需求的现成定义时,应在自己的业务 Bundle 中创建定义,不需要等待平台提供专用类型。
workflow.human_task 只是一个可能已安装的通用定义,不是 human 节点的必经依赖,也不会由平台自动创建。
看不到它的输出合同,不妨碍开发者为自己的业务建立明确的合同。
资源与类型的区别
| 对象 | 所有者与用途 |
|---|---|
| IssueDefinition | 属于 Bundle;使用 Owner 返回的 issueDefinitionId 标识,发布精确不可变版本,随 Bundle 安装。 |
inputType / outputType | IssueDefinition 的输入、结果类型;使用平台统一 Type,可内联匿名 DataType。 |
| Type Definition | 工作区独立拥有的可复用命名类型资源,不属于 Bundle,也不进入安装台账;参见类型定义开发。 |
| human 节点 | 引用 IssueDefinition 精确版本,映射输入、指定候选主体和结果写入路径,不另写一份输出类型。 |
仅为一个业务事项定义输入输出时,可以直接内联匿名类型,不必先创建独立 Type Definition。 Bundle 版本、IssueDefinition 版本与 Workflow 版本相互独立;更新草稿不会改变任何已发布版本。
1. 确认工作区与业务 Bundle
先核对本机命令和当前授权,显式传入目标工作区,避免误用 CLI 默认工作区:
baijimu --version
baijimu auth status --verify
baijimu bundle object create --help
baijimu bundle object publish --help
baijimu bundle definition list --workspace-id <WORKSPACE_ID> --json创建、修改和发布需要业务 Bundle 所有者或所属工作区 owner/admin 权限。安装基础套件不代表拥有其
作者权限;应选择自己的业务 Bundle。没有 Bundle 时,先按创建项目与定义创建并绑定 BUNDLE 项目。
下文的 business.review、example-operations 和版本只用于示例。工作区、事项定义身份、用户 ID 和
实际版本必须从当前授权目录和发布结果取得;不能原样套用。
2. 编写输入输出合同
将以下完整资源定义保存为 issue-definition.json。例子要求人工提交审核结果和意见;这两个字段是本业务的
选择,平台不预置 approved、decision 或其他审批字段。
{
"name": "业务审核",
"description": "核对业务摘要并提交审核结果",
"tags": ["review"],
"inputType": {
"@type": "DataType",
"type": "object",
"properties": {
"summary": { "@type": "DataType", "type": "string" }
},
"required": ["summary"],
"additionalProperties": false
},
"outputType": {
"@type": "DataType",
"type": "object",
"properties": {
"accepted": { "@type": "DataType", "type": "boolean" },
"comment": { "@type": "DataType", "type": "string" }
},
"required": ["accepted", "comment"],
"additionalProperties": false
},
"processActions": ["manual_process"],
"enabled": true
}name必填,最多 200 个字符;description可省略,填写时最多 4000 个字符;文本不得为空或有首尾空白。tags和processActions可省略,默认为空数组;每项最多 100 个字符。处理动作不能代替输出字段定义。inputType、outputType和可选的statusType使用同一平台 Type 合同。用于工作流 human 的定义必须声明outputType。enabled默认true。正式引用应使用已发布、启用且随目标 Bundle 安装的资源版本。- 对象身份由 Owner 创建并返回,不放进这个 JSON;也不填写工作区、Bundle ID、资源版本或安装状态。
- 不使用旧的
inputSchema/outputSchema/statusSchema字段;平台 Type 也不是直接填写 JSON Schema。
3. 创建并发布资源版本
baijimu bundle object create <bundle> issue-definition --workspace-id <WORKSPACE_ID> --definition @issue-definition.json --json
baijimu bundle object publish <bundle> issue-definition --workspace-id <WORKSPACE_ID> \
--object-id <ownerReturnedIssueId> --version <ISSUE_VERSION> --json保存目录返回的 issueDefinitionId、所属 bundleId 和发布的精确 semanticVersion,供 human 节点的 issueDefinition 引用。
继续修改同一业务定义时使用完整更新,再发布一个符合兼容性语义的新版本:
baijimu bundle object update <bundle> issue-definition --workspace-id <WORKSPACE_ID> \
--object-id <ownerReturnedIssueId> --definition @issue-definition.json --json版本必须是严格 SemVer。不要把示例版本当作实际发布授权;发布前分别确定 IssueDefinition、Workflow 和 Bundle 的版本及兼容性影响。不能覆盖旧版本,也不能把资源发布成功当作安装完成。
使用 bundle manifest catalog <bundle> issue-definition 查询目录,bundle object get 读取 Owner 草稿。
定义 JSON 保存在业务源码中,连同精确版本一起评审;安装台账不代替定义正文。
4. 配置 human 节点
下例与上面的输入输出合同配套。替换目录返回的事项定义身份、版本和候选用户后,将节点加入完整 Workflow:
{
"type": "human",
"id": "review",
"name": "人工审核",
"input": {
"summary": "{{input.summary}}"
},
"assignment": {
"mode": "candidates",
"candidates": [
{
"identityType": "user",
"identityId": "{{input.reviewerUserId}}"
}
]
},
"result": {
"path": "reviewResult"
},
"executionPolicy": {
"completionTimeoutSecs": 86400
},
"issueDefinition": {
"bundleId": "example-operations",
"issueDefinitionId": "business.review",
"semanticVersion": "1.0.0"
}
}工作流输入需要声明 summary 和 reviewerUserId。reviewerUserId 必须来自当前工作区有效用户目录,
不能将用户姓名、设备 ID 或其他工作区用户 ID 当作候选用户。
input显式映射到事项的inputPayload;不会隐式发送整个 Workflow 输入或上下文。assignment.mode: "candidates"必须有非空候选列表。identityType支持user / department / group / role;角色填写稳定roleKey,参见角色模板开发。- 明确用户列表校验、去重后,单人直接分配到
Issue.assignee,多人由其中一人领取。含角色、部门或群组时始终是候选范围;领取或转交后的唯一处理者是Issue.assignee。 - 对工作区成员开放领取时显式使用
assignment: {"mode":"workspace_members"},不能用空候选列表表达。 result.path只决定结果位置,例子写入context.reviewResult;输出类型始终归 IssueDefinition,不配置result.type或节点级outputSchema。completionTimeoutSecs是人工等待期限,必须大于零;它不是 HTTP 请求超时,省略表示不配置期限。
人工完成时提交与 outputType 一致的结果,例如 {"accepted":true,"comment":"核对通过"}。
Issue 校验通过后,由平台回传结果并推进 human 节点;下游据 context.reviewResult.accepted 判断业务分支。
accepted:false 仍是合法业务结果,不自动等于 Workflow 执行失败。
从前置节点读取候选人
前置节点若使用 outputPath: "ownerLookup",其结果写入 context.ownerLookup。
例如实际输出为以下对象,reviewerUserId 的值必须是当前工作区有效用户目录中的真实 ID:
{
"summary": "待审核的报告摘要",
"reviewerUserId": "<VALID_WORKSPACE_USER_ID>"
}把上面完整 human 节点中的 input 和 assignment 替换为以下片段,保留原有的
issueDefinition、result 和执行策略。连线必须让前置节点先完成,再执行 human:
{
"input": {
"summary": "{{context.ownerLookup.summary}}"
},
"assignment": {
"mode": "candidates",
"candidates": [
{
"identityType": "user",
"identityId": "{{context.ownerLookup.reviewerUserId}}"
}
]
}
}路径必须按实际节点输出合同填写;若返回值还有外层 data,应引用真实的嵌套路径,不能只凭节点 ID
猜输出位置。identityId 引用的是一个主体 ID,不是用户对象、用户姓名或数组。运行时解析为空或用户身份无效会报错,不会自动开放给全工作区;相同类型与 ID 的重复候选主体会去重。
动态用户列表:单人分配,多人领取
需要使用前置节点返回的任意长度用户列表时,继续使用 assignment.mode: "candidates",将整组引用直接放在 candidates。
前置节点应返回真实的当前工作区用户 ID 字符串数组,例如:
{
"summary": "待审核的报告摘要",
"userIds": ["<VALID_WORKSPACE_USER_ID>", "<ANOTHER_VALID_WORKSPACE_USER_ID>"]
}假设该节点的 outputPath 是 ownerLookup,完整 human 节点可以写成:
{
"id": "reviewReport",
"type": "human",
"name": "审核报告",
"issueDefinition": {
"bundleId": "<BUNDLE_ID>",
"issueDefinitionId": "<ISSUE_DEFINITION_ID>",
"semanticVersion": "1.0.0"
},
"input": {"summary": "{{context.ownerLookup.summary}}"},
"assignment": {
"mode": "candidates",
"candidates": "{{context.ownerLookup.userIds}}"
},
"result": {"path": "reviewResult"}
}替换示例中的身份占位符;事项定义的 inputType / outputType 与本页定义保持一致。
Bundle 保存的是运行时数据引用,实际员工来自执行时所在工作区的用户目录。
若名单由 Event Trigger 传入 Workflow,改用 "candidates": "{{input.userIds}}",并在 Workflow inputSchema
声明对应的字符串数组。也可直接提供真实用户 ID 的非空 JSON 字符串数组;跨工作区复用的 Bundle 应使用引用。
平台使用固定规则,无需配置“直接分配”或“领取”策略:
| 校验并去重后的名单 | 行为 |
|---|---|
| 1 人 | 创建 Issue 时直接设置 Issue.assignee,该用户无需先领取。 |
| 多人 | 创建一个候选池;其中一人领取后成为唯一处理者,其他候选人不能再领取。 |
空名单、缺失路径、null 或错误类型 | human 执行失败,不创建开放事项。 |
| 任一用户不属于当前工作区 | 整组失败;不会丢弃无效用户后继续分配。 |
字符串 ID 去掉首尾空白后必须是标准正整数格式;重复 ID 只保留一份。["7","7"] 的有效人数为 1,
适用单人自动分配。数值数组、用户对象数组、姓名数组和 JSON 字符串化数组均不接受;前置节点需要先输出
字符串 ID 数组。这里的数值仅说明格式,实际配置必须使用目录返回的身份。
candidates 整组引用必须完整指向 input 或 context 中的数组;不支持拼接、隐式取第一人或在此处执行 =CEL。
多候选不代表会签,也不会创建多份事项。human 重试复用原 Issue,不覆盖已领取或转派后的负责人。
一个候选入口,统一分配规则
assignment.candidates 接受三种形式:
| 形式 | 示例 | 用途 |
|---|---|---|
| 用户 ID 字符串数组 | ["7", "8"] | 已知的当前工作区用户列表。 |
| 完整数组引用 | "{{context.ownerLookup.userIds}}" | 读取前置节点返回的用户 ID 字符串数组,也可引用 input。 |
| 候选主体对象数组 | [{"identityType":"role","identityId":"reviewer"}] | 指定 user / department / group / role 主体;每项 identityId 可引用单个值。 |
前两种形式解析为 user 候选主体,与直接填写用户主体对象使用相同的校验、去重和分配规则。
示例数字只说明格式,必须替换为目录返回的真实用户身份。字符串数组与主体对象不能混在同一个数组中。
整组引用的结果必须是用户 ID 字符串数组,不能是用户对象数组或候选主体对象数组。
纯用户候选去重后只有一人时直接分配;多人时由其中一人领取。如果包含角色、部门或群组,保留候选范围,
即使只配置一个角色,也不会将其当成一个用户直接分配。混合用户与角色的主体对象数组同样需要领取,
其中显式用户仍必须通过工作区成员校验。workspace_members 继续表示显式开放工作区领取。
不再使用独立的 mode: "users" / assignment.userIds;也不添加 mode: "direct"、分配策略开关或节点级
assignee。不要把用户数组放进某一项 identityId,该字段仍只表示一个主体 ID。
从旧配置升级
旧 users 配置应把 mode 改为 candidates,将 assignment.userIds 的原值移到
assignment.candidates,然后发布新的 Workflow 版本。该收敛合同拒绝旧 users 模式,平台升级前需核对
已发布资源、运行时投影和执行快照;不可变版本不能原地改写。
原有纯用户 candidates 也使用上述人数规则:新建事项的单一用户无需领取。已经创建的 Issue 不会因此
重新分配,重试继续保留现有负责人和领取状态。需要维持旧行为的在途流程应按旧合同完成后再切换,
不能只更新文档或平台镜像而跳过存量检查。
事件绑定、输入映射和两种表达式语法见 Event Trigger 教程。
不要用公开 wait.signal 接口绕过人工事项处理。
Workflow 按工作流开发创建、更新并发布精确版本。当前 human 使用上述
issueDefinition/input/assignment/result 字段;历史 Workflow Schema 5.0.0 的 human 示例
采用旧字段,不能用它校验或生成本页的新节点。历史合同保持原样,遇到 CLI 字段不兼容时应先核对版本,不能混用两套合同。
5. 纳入 Bundle,发布并安装
资源版本和 Workflow 版本均发布后,将它们加入绑定项目的 baijimu.bundle.json。
以下命令会在线预检并原子更新本地作者文件:
baijimu bundle manifest include <bundle> issue-definition --workspace-id <WORKSPACE_ID> \
--file baijimu.bundle.json --object-id <ownerReturnedIssueId> --version <ISSUE_VERSION>
baijimu bundle manifest include <bundle> workflow --workspace-id <WORKSPACE_ID> \
--file baijimu.bundle.json --object-id <ownerReturnedWorkflowId> --version <WORKFLOW_VERSION>
baijimu bundle manifest validate @baijimu.bundle.jsondefinition.issueDefinitions 和 definition.workflows 分别保存领域对象与精确版本;同一对象重新纳入时更新版本。
跨 Bundle 引用必须通过已声明依赖,不能改挂到当前 Bundle。
按项目分支策略提交并推送源码,再从该完整 Git 提交创建 Bundle 版本:
baijimu bundle version create <bundle> --workspace-id <WORKSPACE_ID> \
--version <BUNDLE_VERSION> --git-commit-id <40-character-commit> --json使用返回的 Bundle 版本记录 ID 安装;已经安装时执行 upgrade:
baijimu bundle install <bundle> --workspace-id <TARGET_WORKSPACE_ID> \
--version-id <BUNDLE_VERSION_ID> --json
baijimu bundle upgrade <bundle> --workspace-id <TARGET_WORKSPACE_ID> \
--version-id <BUNDLE_VERSION_ID> --json
baijimu bundle resources <bundle> --workspace-id <TARGET_WORKSPACE_ID> --jsoninstall 与 upgrade 按当前安装状态二选一。所属工作区可以走 OWNER_ONLY 直接安装,不要求先上公共市场;
跨工作区按分发与交付授权。若 CLI 要求确认未验证版本或
跨 Bundle 方法权限,应先核对安装预览,再按当前命令帮助确认。
6. 验证结果和定位阻塞
- Bundle 安装记录为目标版本,台账包含预期
ISSUE_DEFINITION和WORKFLOW的精确版本及成功状态。 - 启动测试 Workflow,确认人工事项收到显式映射的输入;
users分别验证单人无需领取、多人只允许一人领取、重复 ID 去重和空/无效名单失败。原有candidates仍按领取流程验证。 - 提交符合合同的结果,确认 human 完成,下游收到预期字段;用缺失必填字段或错误类型的结果确认校验生效。
- 验证业务拒绝分支和配置的人工等待超时;不能只以 Bundle 版本创建成功作为流程验收。
| 现象 | 应做的判断 |
|---|---|
| 没有合适的 IssueDefinition | 在自己的业务 Bundle 中创建,不是等待平台补通用资源。 |
台账有 workflow.human_task,但 detailJson 为空 | 台账只证明资源版本及安装状态,不能推断它没有输出类型,也不能推断它满足业务要求。可以创建自有定义。 |
| 创建或发布失败 | 保留 CLI 版本、脱敏命令和原始错误,区分权限、定义字段、类型或发布问题;不能仅凭空台账断言不支持创建。 |
| 草稿已创建、资源已发布,运行时仍找不到 | 检查 Manifest 是否引用、Bundle 是否创建版本并安装、human 是否引用同一精确版本。 |
| 结果提交失败 | 对照所引用版本的 outputType 检查字段、必填性和类型,不在 human 节点另加一份类型兜底。 |