一个 Action 的解剖

第 1 课 · 共 7 课 约 8 分钟

参数、规则、提交条件、副作用、日志:五个部件各管什么。从零写出 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 的五个部件

PARAMETERS

参数

调用方要填的输入:一张订单、一个数量、一句理由。每个参数有类型,也可以带限制。

RULES

规则

把参数变成编辑:新建、修改、删除对象,建立或解除关系。

CRITERIA

提交条件

能不能提交的判断:看参数、看对象现在的值、看是谁在做。不满足就拒绝,并给出一句写好的原因。

SIDE EFFECTS

副作用

改完之后向外发生的事:通知某个人,或调用外部系统。第 5 节专门讲。

LOG

日志

每次成功执行留下的记录:谁、什么时候、什么参数、改了哪些对象。

  1. 01校验参数类型、必填、限制
  2. 02判断提交条件全部满足才继续
  3. 03应用规则一个事务
  4. 04写日志同一个事务
  5. 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 加它的名字读出定义。把五个部件各用一句话写下来;哪个部件没有,就写「没有」。

小测

选一个答案,马上看解析。

Q1把 confirm-order 做成「让调用方填 status 参数」,主要问题是什么?

Q2订单已经是 confirmed,运行 aidc semantic apply confirm-order --param order=SO-1001 --validate-only 会怎样?

Q3log.confirm-order 里的记录是什么时候写入的?

延伸阅读