一个 Action 的解剖
参数、规则、提交条件、副作用、日志:五个部件各管什么。从零写出 confirm-order 并试跑。

本课目标
读完这一课,你将能够
- 说出 Action 的五个部件各管什么
- 读懂并写出
confirm-order的完整定义 - 用
--validate-only与--return-edits试跑一个 Action
为什么改数据只有一个入口
上一门课的最后一节用只读 SQL 把数据读了出来。读可以有很多种办法,改只有一个入口:Action。
Action 是一次事务:按事先写好的逻辑,同时改一个或多个对象、属性和关系。它表达的是业务意图,比如「确认订单」「下达工单」,而不是「把 status 字段改成 confirmed」。
| 直接改字段 | 执行 Action | |
|---|---|---|
| 谁能改 | 凡是有写权限的人,什么字段都能改 | 只有能执行这个 Action、又通过了提交条件的人 |
| 能改成什么 | 想填什么填什么 | 只能是定义里写好的那一种改法 |
| 留下什么 | 靠自觉记一笔 | 日志和编辑历史自动留下 |
| 各处是否一致 | 每个界面各写一套校验 | 界面、命令行、工作流、智能体走同一份逻辑 |
谁来调用它都一样:/semantic 里的表单、命令行、SDK、工作流里执行 Action 的一步、智能体,执行的都是同一个 Action,走同一套校验,留下同样的记录。
所以设计 Action 从一个问题开始:这是哪一种业务动作?名字用动词加对象,写成 kebab-case,比如 confirm-order。
一个 Action 的五个部件
参数
调用方要填的输入:一张订单、一个数量、一句理由。每个参数有类型,也可以带限制。
规则
把参数变成编辑:新建、修改、删除对象,建立或解除关系。
提交条件
能不能提交的判断:看参数、看对象现在的值、看是谁在做。不满足就拒绝,并给出一句写好的原因。
副作用
改完之后向外发生的事:通知某个人,或调用外部系统。第 5 节专门讲。
日志
每次成功执行留下的记录:谁、什么时候、什么参数、改了哪些对象。
- 01校验参数类型、必填、限制
- 02判断提交条件全部满足才继续
- 03应用规则一个事务
- 04写日志同一个事务
- 05副作用事务之后
「只校验」在第二步之后停下,什么也不写。副作用发生在事务提交之后,它不在事务里,第 5 节和第 7 节会回到这一点。
从零写 confirm-order
示例工厂的销售订单从 draft 开始。「确认订单」只做一件事:把一张草稿订单改成 confirmed。定义是一份 JSON,kind 写 actionType:
{
"kind": "actionType",
"apiName": "confirm-order",
"title": "确认订单",
"description": "把一张草稿订单确认下来,交给生产。",
"schema": {
"parameters": [
{ "name": "order", "type": "object", "objectType": "salesOrder", "title": "订单", "required": true }
],
"rules": [
{ "type": "modifyObject", "objectType": "salesOrder", "object": "$order", "values": { "status": "confirmed" } }
],
"submissionCriteria": [
{
"condition": { "type": "comparison", "left": { "param": "order", "property": "status" }, "operator": "is", "right": { "literal": "draft" } },
"failureMessage": "只有草稿订单可以确认"
}
],
"summary": "订单 {order} 已确认",
"actionLog": true,
"toolDescription": "Confirm a draft sales order so it can go to production."
}
}
四段各管一件事。parameters 声明输入:只有一个必填的订单对象。rules 里一条 modifyObject 把订单的 status 写成字面量 confirmed。submissionCriteria 要求订单现在必须是 draft,否则返回你写的 failureMessage。actionLog: true 让每次成功执行多写一个 log.confirm-order 对象。summary 是日志里的一句话,toolDescription 是写给智能体看的说明。
先校验,再执行
开发者把定义存成文件后,先用 aidc semantic define ontology/ --dry-run 检查,再去掉 --dry-run 提交;智能体则在分支上改,走提案(第 10 门课讲)。定义就绪后,先只校验、再执行:
aidc semantic apply confirm-order --param order=SO-1001 --validate-only
aidc semantic apply confirm-order --param order=SO-1001 --return-edits
第一条什么也不写,只返回逐个参数、逐条提交条件的结果,不通过时退出码是 2。第二条正式执行,--return-edits 让返回里带上这次新建、修改、删除了哪些对象和关系。SDK 里对应 applyAction(params, { $validateOnly: true }) 和 { $returnEdits: true }。返回的样子(节选):
{
"validation": {
"result": "VALID",
"submissionCriteria": [{ "result": "VALID" }],
"parameters": { "order": { "result": "VALID", "required": true } }
},
"edits": { "type": "edits", "addedObjectCount": 0, "modifiedObjectsCount": 1, "deletedObjectsCount": 0 }
}
命名照统一的规矩:Action 用 kebab-case,Object Type 用 PascalCase,属性和值类型用 camelCase。已有的小写类型名兼容,但会告警。本课示例沿用已有的 salesOrder;新建类型应写 SalesOrder。
下一节把参数拆开讲:release-work-order 该让调用方填什么,又不该让他填什么。
要点
- Action 是一次事务,表达一种业务意图,不是一个改字段的按钮。
- 五个部件:参数、规则、提交条件、副作用、日志。
- 执行顺序:校验参数,判断提交条件,规则在一个事务里落地,日志与修改同一个事务。
- 定义是 JSON,名字用 kebab-case;先
--validate-only,再执行。
练一练
把一次手工修改写成 Action
先读一个真的 Action,再自己写一个;校验不会写入任何东西,放心试。
运行 aidc semantic action-types 列出你所在组织的 Action,选一个用 aidc semantic action-types 加它的名字读出定义。把五个部件各用一句话写下来;哪个部件没有,就写「没有」。
为示例工厂写 close-defect:参数是一个 defect 对象和一句处理说明,规则把 status 改成 closed,提交条件要求缺陷现在是 open(这两个取值是本练习的假设)。写成完整的 JSON。
对任意一个 Action 用 --validate-only 传一个不存在的参数名,再传一个不合格的值。两次返回的信息各指向哪里?
小测
选一个答案,马上看解析。
Q1把 confirm-order 做成「让调用方填 status 参数」,主要问题是什么?
Action 应该表达一种业务意图。status 由规则写死成 confirmed,提交条件才能围绕「必须是草稿」来写。
Q2订单已经是 confirmed,运行 aidc semantic apply confirm-order --param order=SO-1001 --validate-only 会怎样?
只校验也会判断提交条件,只是不写入。条件不满足时返回你写好的失败信息,退出码是 2。
Q3log.confirm-order 里的记录是什么时候写入的?
日志与修改同一个事务提交:修改回滚,日志也不会存在;失败的调用不产生日志。