Convert natural language process descriptions into Flowable BPMN 2.0 XML, and automatically create the process in the JeecgBoot system via API.
Prerequisites
The user must provide the following information (or have it confirmed with AI guidance):
- API address: JeecgBoot backend address (e.g.
https://api3.boot.jeecg.com) - X-Access-Token: JWT login token (obtained from browser F12)
If the user does not provide it, prompt:
Please provide the JeecgBoot backend address and X-Access-Token (copy it from browser F12 → Network → Request Headers of any request).
Interaction Flow
Step 0: Parse user requirements
Extract the following information from the user's description:
| Information | Default value | Example |
|---|---|---|
| Process name | User-specified or auto-generated | "Employee Leave Approval Process" |
| Process type | oa |
Dictionary bpm_process_type value |
| Node list | Parsed from the description | Start→Employee Submission→Manager Approval→HR Approval→End |
| Gateway logic | Parsed from the description | "Approved→Next step, Rejected→End" |
| Approver configuration | Parsed from the description | assignee/candidateUsers/candidateGroups/expression |
Step 1: Identify nodes and build the process structure
Supported node types:
| User description keywords | BPMN node type | XML element |
|---|---|---|
| Start | Start event | startEvent |
| End | End event | endEvent |
| Approve/review/process/submit | User task | userTask |
| Conditional judgment/branch/approve or reject | Exclusive gateway | exclusiveGateway |
| Simultaneous/parallel | Parallel gateway | parallelGateway |
| Conditional parallel/partial parallel | Inclusive gateway | inclusiveGateway |
| Subprocess/nested | Embedded subprocess | subProcess |
| Call subprocess/main-sub process | Call subprocess | callActivity |
| Countersign subprocess | Call subprocess + multi-instance | callActivity + multiInstance |
Approver configuration mapping:
| User description | BPMN attribute | Example |
|---|---|---|
| "Initiator/Applicant" | flowable:assignee="${applyUserId}" |
Process initiator auto-filled |
| "admin/specified username" | flowable:assignee="admin" |
Fixed specified person |
| "Manager role/role group" | flowable:candidateGroups="manager" + groupType="role" |
System role candidate |
| "Approval role" | flowable:candidateGroups="xxx" + groupType="approvalRole" |
Dedicated approval role |
| "Zhang San or Li Si" | flowable:candidateUsers="zhangsan,lisi" |
Multiple candidates |
| "Approval by a certain department" | flowable:candidateGroups="部门ID" + groupType="dept" |
Department approval |
| "Approval by a certain position" | flowable:candidateGroups="岗位ID" + groupType="deptPosition" |
Department position approval |
| "Position level approval" | Expression + groupType="position" |
Job level approval |
| "Department head (expression)" | flowable:assignee="${deptLeader}" |
Dynamic expression |
| "Assigned by previous node" | isAssignedByPreviousNode=true |
Selected by previous approver |
| "Draft/Rejected initiator" | flowable:assignee="${applyUserId}" + sameMode=2 |
Draft node |
| "Countersign/Multiple simultaneous approvals" | flowable:countersignRule + multiple instances |
Parallel/Sequential countersign |
| "Select approver from form field" | groupType="formData" |
Dynamically obtained from form |
Approver data query: When the user mentions a specific role/user/department name, the database can be queried to obtain the exact code:
- Role code:
SELECT role_code, role_name FROM sys_role - Username:
SELECT username, realname FROM sys_user - Department/Position ID:
SELECT id, depart_name, org_category FROM sys_depart(org_category: 1=Company, 2=Department, 3=Position, 4=Subsidiary)
Step 2: Display the process summary and confirm
The following content must be displayed, and execution must wait until the user confirms:
## 流程摘要
- 流程名称:员工请假审批流程
- 流程类型:oa
- 目标环境:https://api3.boot.jeecg.com
### 流程节点
| 序号 | 节点名称 | 类型 | 审批人 |
|------|---------|------|--------|
| 1 | 开始 | startEvent | - |
| 2 | 员工提交申请 | userTask | ${applyUserId} |
| 3 | 部门经理审批 | userTask | manager (角色组) |
| 4 | 审批结果 | exclusiveGateway | 条件分支 |
| 5 | HR审批 | userTask | hr (角色组) |
| 6 | 结束 | endEvent | - |
### 连线与条件
开始 → 员工提交申请 → 部门经理审批 → 审批结果
├─ 通过 (result==1) → HR审批 → 结束
└─ 拒绝 (result==0) → 结束
确认以上信息正确?(y/n)
Step 3: Generate BPMN XML and call the API
After the user confirms, execute the following steps:
3.1 Generate a unique identifier
import time
ts = str(int(time.time() * 1000))
process_key = f"process_{ts}"
3.2 Construct the BPMN XML
Read the following reference files (as needed):
references/bpmn-xml-skeleton.md— XML skeleton + basic node template (required reading)references/bpmn-assignee-types.md— Approver configuration + expression approvers + groupType quick reference (required reading)references/bpmn-layout.md— Node ID naming + layout calculation (required reading)references/bpmn-countersign.md— Countersign configuration (read when countersigning is needed)references/bpmn-task-extend.md— Complete list of taskExtendJson + listeners (read when configuring node behavior)references/bpmn-examples.md— Complete examples + Python scripts + process patternsreferences/bpmn-advanced.md— Conditional expressions + CC + buttons + service tasks + APIreferences/bpmn-subprocess-gateway.md— Gateways + subprocesses (read when using subprocesses/gateways)references/bpmn-db-config.md— Database configuration tablesreferences/example/*.bpmn— Real production process examples(Before generating, first read the most similar example to learn the writing style)
Key points:
- Use the
bpmn2:namespace prefix (new designer specification) - Must include a process end listener and a task creation listener
- Must include
bpmndi:BPMNDiagramgraphical layout information - Node IDs use meaningful names (such as
task_apply、gateway_result)
3.3 Construct the nodes parameter
Extract from all userTask nodes, format:
id=<节点ID>###nodeName=<节点名称>@@@id=<节点ID>###nodeName=<节点名称>@@@
3.4 Use Python to call the API (must use Python, do not use curl)
Important restrictions (real-world pitfalls):
- In a Windows environment, curl sending Chinese characters will cause garbled text, so Python's urllib must be used to ensure UTF-8 encoding
- Do not use
python3 -c "..."inline, because expressions such as${applyUserId}in the BPMN XML will be expanded by bash as shell variables, causingunexpected EOFerrors - You must first use the Write tool to write
.pyto a temporary file, then execute it with Bash, and finally delete the temporary file
Execution steps:
1. Write 工具 → 写入 create_process.py(项目根目录)
2. Bash 工具 → python create_process.py
3. Bash 工具 → rm create_process.py(清理)
Escaping key points in Python f-strings:
- BPMN expression
${applyUserId}→ in an f-string write it as${{applyUserId}}(double curly brace escaping) - The
valueattribute of taskExtendJson usessingle quotesWrap JSON →value='{{"sameMode":2,...}}'(to avoid conflict with XML double quotes; JSON curly braces also need double curly brace escaping) flowable:candidateUsers="${flowNodeExecution.getDepartLeaders(execution)}"→ written in f-string as${{flowNodeExecution.getDepartLeaders(execution)}}
Python script template:
import urllib.request
import urllib.parse
import json
import time
API_BASE = '{用户提供的后端地址}'
TOKEN = '{用户提供的 X-Access-Token}'
ts = str(int(time.time() * 1000))
process_key = f'process_{ts}'
process_name = '流程名称'
# 用 f-string 构造 XML,注意 ${{}} 双花括号转义
bpmn_xml = f'''<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions ...>
<bpmn2:process id="{process_key}" name="{process_name}">
...
<bpmn2:userTask id="task_apply" name="申请人填写" flowable:assignee="${{applyUserId}}">
<bpmn2:extensionElements>
<flowable:taskExtendJson value='{{"sameMode":2,...}}' />
...
</bpmn2:extensionElements>
</bpmn2:userTask>
...
</bpmn2:process>
<bpmndi:BPMNDiagram>...</bpmndi:BPMNDiagram>
</bpmn2:definitions>'''
nodes_str = 'id=task_apply###nodeName=申请人填写@@@...'
data = {
'processDefinitionId': '0',
'processName': process_name,
'processkey': process_key,
'typeid': 'oa',
'lowAppId': '',
'params': '',
'nodes': nodes_str,
'processDescriptor': bpmn_xml,
'realProcDefId': '',
'startType': 'manual'
}
encoded_data = urllib.parse.urlencode(data).encode('utf-8')
req = urllib.request.Request(
f'{API_BASE}/act/designer/api/saveProcess',
data=encoded_data,
headers={
'X-Access-Token': TOKEN,
'X-Sign': '00000000000000000000000000000000',
'X-Tenant-Id': '1',
'X-Timestamp': str(int(time.time() * 1000)),
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
},
method='POST'
)
resp = urllib.request.urlopen(req)
result = json.loads(resp.read().decode('utf-8'))
print(json.dumps(result, ensure_ascii=False, indent=2))
print(f'\\nProcess Key: {process_key}')
3.5 Check results
success: true→ Process created successfully, record the returnedobj(process ID)success: false→ Output error message, check whether processkey is duplicated, etc.
Step 4: Output results
## 流程创建成功
- 流程ID:{obj}
- 流程名称:{processName}
- 流程Key:{processkey}
- 目标环境:{API_BASE}
请在流程设计器中查看:打开 JeecgBoot 后台 → 流程管理 → 流程设计 → 找到该流程
Edit existing process
If the user wants to modify an existing process, provide processDefinitionId(process data table ID), call the same API, and change processDefinitionId to the actual ID.
Error handling
| Error | Solution |
|---|---|
| Token expired (401/authentication failed) | Prompt the user to obtain a new X-Access-Token |
流程ID重复 |
Regenerate the timestamp as processkey |
不是最新版本 |
First query the latest processDefinitionId and then save |
| Chinese garbled text | Confirm that Python urllib is used (do not use curl) |
| Connection timeout | Confirm the backend address is reachable, check the network |
Database configuration table
After the process is created, node behavior, form binding, and field permissions can be further configured through the following database tables:
| Table name | Description | Purpose |
|---|---|---|
ext_act_process |
Process main table | Process attributes, XML, initiation method, reminder/withdrawal/notification, etc. |
ext_act_process_form |
Form binding | Association between process and business form, title expression, form type (1=Online/2=DesForm/3=Custom) |
ext_act_process_node |
Node configuration | Function switches for each approval node (edit/copy/send/assign/add approver/reject, etc.) |
ext_act_process_node_auth |
Field permissions | Display/hide/editable/disabled control of form fields on each node |
For detailed field descriptions and values, see references/bpmn-db-config.md。
Reference documents
- Read
references/bpmn-templates.mdto get the reference file index (already split into 8 sub-files)