第一个 Action:新建一个对象
参数、规则、日志三样东西;先只校验、再执行;读懂逐项结果和改动清单;到 Action Log 和编辑历史里找到这一次。

本课目标
读完这一课,你将能够
- 写出一个 createObject 的 Action:参数、规则、日志
- 先只校验再执行,读懂返回的逐项结果和改动清单
- 在 Action Log 和编辑历史里找到这一次执行
一个 Action 的三个部件
最小的 Action 只需要三样东西。把下面的文件存成 starter/02-register-customer.json:
{
"kind": "actionType",
"apiName": "register-customer",
"title": "登记客户",
"description": "新建一家客户公司。第一个 Action:只有参数、一条规则和一份记录。",
"schema": {
"parameters": [
{ "name": "customerId", "type": "string", "title": "公司 ID", "required": true, "maxLength": 40 },
{ "name": "name", "type": "string", "title": "名称", "required": true, "maxLength": 60 },
{ "name": "stage", "type": "string", "valueType": "customerStage", "title": "阶段", "required": true },
{ "name": "seats", "type": "integer", "title": "座位数", "required": true, "min": 1, "max": 10000 },
{ "name": "members", "type": "integer", "title": "成员数", "required": true, "min": 0, "max": 10000 }
],
"rules": [
{
"type": "createObject",
"objectType": "customer",
"values": { "customerId": "$customerId", "name": "$name", "stage": "$stage", "seats": "$seats", "members": "$members" }
}
],
"summary": "登记客户 {name}",
"actionLog": true
}
}
- 参数 parameters
调用方要填什么。类型、必填、取值范围(
min、max、maxLength)、Value Type 的约束,都在入口处检查。 - 规则 rules
改什么。这里一条
createObject:用参数拼出一个新的客户公司。规则一共六种,下一课会用到modifyObject。 - 日志 actionLog
actionLog: true让每次成功执行都留一个日志对象;summary是写进日志的一句话,{name}取参数的值。
规则的值里,$customerId 是取参数。能写的还有:$参数.属性(取对象参数的某个属性)、$now(当前时间)、$user(执行人的账号 ID)和 $userName(执行人的名字)、$uuid(一个新的主键);其他都是字面量,比如 "submitted"。
放进去,先只校验
aidc semantic define starter && aidc semantic publish --notes "登记客户"
aidc semantic apply register-customer \
--param customerId=acme-east --param name="ACME East" --param stage=试点 \
--param seats=0 --param members=14 --validate-only --json
座位数填了 0,不在 1 到 10000 之间。只校验不写入,返回每个参数的结果,出错的那一项带着信息,命令行退出码是 2:
{
"validation": {
"result": "INVALID",
"submissionCriteria": [],
"parameters": {
"customerId": { "result": "VALID", … },
"seats": {
"result": "INVALID",
"evaluatedConstraints": [{ "type": "range", "gte": 1, "lte": 10000 }],
"required": true,
"message": "座位数 要在 1–10000 之间"
},
"members": { "result": "VALID", … }
}
}
}
执行,读结果
改成合格的数,去掉 --validate-only,加上 --return-edits(要求把改动一起返回):
aidc semantic apply register-customer \
--param customerId=acme-east --param name="ACME East" --param stage=试点 \
--param seats=20 --param members=14 --return-edits --json
{
"operationId": "ri.actions.aidc.action.cmuni87b5000d01alepn05gf9",
"validation": { "result": "VALID", … },
"edits": {
"type": "edits",
"edits": [{ "type": "addObject", "primaryKey": "acme-east", "objectType": "customer" }],
"addedObjectCount": 1,
"modifiedObjectsCount": 0,
"deletedObjectsCount": 0,
"addedLinksCount": 0,
"deletedLinksCount": 0
}
}
validation
逐项的结果:每个参数、每条提交条件,通过还是不通过。
edits
这一次到底改了什么:新建、修改、删除了哪些对象和关系。
operationId
这一次执行的编号,Action Log 和编辑历史里都能凭它找到。
找到这一次
aidc semantic objects customer # 现在的客户
aidc semantic objects log.register-customer --json # Action Log
aidc semantic edits-history customer --pk acme-east # 这个对象的每一次修改
Action Log 本身也是对象:类型叫 log.register-customer,主键就是 operationId,里面有时间、执行人、summary、改了哪些对象(editedObjects),以及这次的参数值。编辑历史里同一个 operationId 会出现在这个对象的 createEdit 上。
{
"__primaryKey": "ri.actions.aidc.action.cmuni87b5000d01alepn05gf9",
"__apiName": "log.register-customer",
"timestamp": "2026-09-30T02:46:58.040Z",
"summary": "登记客户 ACME East",
"editedObjects": ["customer:acme-east"],
"customerId": "acme-east", "name": "ACME East", "stage": "试点", "seats": 20, "members": 14
}
再登记三家,后面几课都要用。它们的座位数和成员数各不相同,第 4 课的提交条件会用到:
aidc semantic apply register-customer --param customerId=acme-west --param name="ACME West" --param stage=试点 --param seats=48 --param members=41
aidc semantic apply register-customer --param customerId=acme-north --param name="ACME North" --param stage=试点 --param seats=36 --param members=33
aidc semantic apply register-customer --param customerId=acme-pause --param name="ACME Pause" --param stage=暂停 --param seats=10 --param members=4
要点
- 一个 Action = 参数 + 规则 + 日志;
createObject用参数和$now、$uuid这类内置值拼出新对象。 - 先
--validate-only,再执行;不通过退出码是 2,信息指到具体的参数。 - 返回里三样:
validation(逐项)、edits(改了什么)、operationId(这一次的编号)。 - 每次成功执行都进 Action Log(也是对象,可查)和编辑历史,用同一个编号。
练一练
登记四家客户
在你自己的公司里做;执行过的客户会留在数据里,后面几课接着用。
分别试 seats=0、stage=不存在、漏掉 name,各加 --validate-only:每种提示指到哪个参数?
登记 ACME East,然后对照 objects log.register-customer 的 __primaryKey 和 edits-history 里的 operationId:是同一个吗?再看 objects customer 里 ACME East 的座位数、成员数是不是你填的。
用同一个 customerId 再登记一次:返回什么状态码、什么错误码?数据有没有被改?
小测
选一个答案,马上看解析。
Q1校验不通过时,命令行的退出码是多少?
退出码 2 专门留给「校验不通过」,脚本和智能体据此判断,不用解析文字。
Q2用一个已经存在的 customerId 再登记一次,会怎样?
createObject 只新建;主键已存在就整个不执行。要「有则改、无则建」,规则用 createOrModifyObject。
Q3Action Log 里每条记录的主键,和什么对得上?
日志对象的主键就是 operationId;编辑历史里对象的每次改动也带同一个编号,所以能从一头查到另一头。