查看 Markdown

语义 SDK(Semantic)

Semantic 是 AIDC 的数据平台(Data Connection + Ontology + Automate + Security)。企业数据的一切都在这里:数据从哪来、存成什么对象、谁能看、谁改了什么、变了之后自动做什么、花了多少钱。ERP / MES / OA 这些数据源永远只读;应用和智能体读对象集、用 Action 改(参数校验、谁能做、留痕)。

ERP / MES / OA ──(发布端,只读)──▶ 数据流 ──(Object Type 定义里的 datasources)──▶ Semantic(对象 · 链接 · Action)──▶ 应用 · 智能体 · 自动化 · SQL
import { semantic } from "/developer/sdk/v1/aidc.js";

先读这两页:Object:从表到对象(对象是什么、由哪几部分组成、怎样从零构建一个对象、和直接查表比有什么不同);数据管道(从源系统到对象的每一段、按需计算与数据健康、把定时看板迁进 Semantic)。

Semantic 是数据平台

要做什么 用什么 标准名
读对象、沿链接走、聚合 semantic.ontology().objects(t).where(…).fetchPage() / aggregate() / pivotTo() Ontology SDK(OSDK)
实时 objectSet.subscribe({ onChange, onOutOfDate }) Object set subscription
改数据 client.action(a).applyAction(…)(只有这一条写路径) Actions
数据从哪来 semantic.streams / semantic.stream() + Object Type 定义里的 datasources Data Connection · Streams · backing datasource
SQL semantic.sql() / semantic.database() Ontology SQL
谁能看 semantic.filesystem(Private / Group / Public / Open to Internet)· semantic.admin(当前账号、成员) Filesystem ResourceRoles · Admin
变了做什么 semantic.automate(数据变化 / 定时 → Action、模型分析、通知) Automate
留痕与用量 Action Log、editsHistory、semantic.observability、semantic.usage,平台对象类型 aidcModelUsage / aidcAppEvent / aidcAutomationRun Action log · Observability · Resource Management
建本体 分支与提案(智能体作者;谁审核合并看组织的审批策略) Global Branching · Ontology proposals · approval policy

原来的连接、数据、权限、工作流、日志、账单六个 SDK 就是上面这些部分,1.20.0 起都在 semantic 里。旧名照样能用、和新家是同一份实现:connect.stream === semantic.stream、auth.me === semantic.admin.getCurrentUser、workflow.run === semantic.automate.run、log.feedback === semantic.observability.feedback、billing.summary === semantic.usage.summary,connect.agent 搬到了 model.agent;应用清单 sdk 里写旧名也照收(归一成 semantic)。

数据从哪来:数据流与数据源

数据在源头一变,源头旁边的发布端(aidc semantic streams pipe + 适配器,只读)就把变化推上来,平台按序落账(数据流)。数据流接到哪个 Object Type、哪一列对哪个属性,写在 Object Type 的定义里(即 Ontology Manager 的 Datasources 页里选的 backing datasource)——改数据源就是改本体:

{ "kind": "objectType", "apiName": "production.order_line", "title": "工单线体进度",
  "schema": {
    "columns": [ { "name": "orderLineKey", "type": "string", "primaryKey": true }, { "name": "orderNo", "type": "string" }, { "name": "lineCode", "type": "string" }, … ],
    "datasources": [
      { "type": "stream", "stream": "production-progress", "propertyMapping": { "orderLineKey": "key", "orderNo": "aufnr", "lineCode": "line", "ok": "gmnga" }, "mode": "mirror" }
    ] } }
  • 规则(定义时就校验):一个 Object Type 恰好一个主键属性(复合键在数据源里拼成一列,如 <工单>|<线体>);属性 API name 用 camelCase,流里的列名照源系统写、在 propertyMapping 里对上;流要在本组织存在;映射到的列要在流里;主键属性必须映射;只在语义层维护的属性(writeback,即 editOnly)和派生属性不映射;同一条流在一个类型里只出现一次。还是数据源的流删不掉(先从定义里去掉)。
  • mode:mirror = 流里没了的行在对象上标记「源头已消失」;upsert = 只增改(多行汇成一个对象、保留历史)。
  • 谁能改:开发者直接定义(aidc semantic define,或下面的快捷命令);智能体在分支上改、开提案,按组织的审批策略审核合并(提案的 merge checks 多一项 datasources)。
  • 定义落了之后:平台按定义建好同步,用流的当前全量同步一次;之后流每落账一批就增量同步。定义里去掉数据源(或归档类型),同步就停,已有对象保留。
  • 没写 = 沿用:重新定义时没写 datasources,沿用现有的数据源(返回一条警告);要去掉全部数据源,明确写 "datasources": []。
aidc semantic streams create production-progress --title "生产进度" --key key --field key --field aufnr --field line --field gmnga:number
aidc semantic streams key production-progress --label "SAP 旁边的发布端"      # aidc-pk-…,只显示一次
aidc semantic datasource set production.order_line --stream production-progress --map orderLineKey=key --map orderNo=aufnr --map lineCode=line --map ok=gmnga
aidc semantic datasource list                                                    # 每个类型的数据源与同步进度
aidc semantic datasource sync                                                    # 平台数据源立即同步(= /semantic 的「立即同步」)
await semantic.streams.create({ name: "orders", title: "订单", key: "order_no", fields: [{ name: "order_no" }, { name: "qty", type: "number" }] });
const pub = semantic.stream("orders").publisher();   // 发布端:只发与上次相比的差
await pub.rows(await readErpOrders());

另一种数据源:用 SQL 读业务库(Data Connection)。ERP / MES 不装发布端时,平台直接用只读账号读:每张表一个 TableImport(一条只读 SELECT),每次执行写成一个 dataset 的事务,只把变了的行写成对象。dataset 在 Object Type 的定义里是 { "type": "dataset", "dataset": "<TableImport 的 apiName>", "propertyMapping": {…} }(SNAPSHOT 的导入 = 对象就是这些行,没了的标「源头已消失」;APPEND = 只增改)。客户内网的库经装在客户网络里的 agent proxy 连(只出站、只转发字节)。读的时候过期才同步(freshness.maxAgeSeconds),没人读就不跑。写法与命令见闭环。

建 sync 之前先探索源(本组织开发者):source 页的 Explore 列出源里的表与视图(可按表名搜索),点开一张表看列、主键、外键与被引用的表,直连的 source 还能取几行样本;勾选要的表,一次建好 batch sync(每张一条 SELECT *,之后在 sync 页改增量、挑列)。只读;样本行不落库,经 agent proxy 的 source 只看表与结构。命令行:

aidc semantic connectivity explore <connectionRid> --search order              # 表名里含 order 的表与视图
aidc semantic connectivity explore <connectionRid> --table dbo.SalesOrder        # 列、主键、外键与被引用
aidc semantic connectivity explore <connectionRid> --table dbo.SalesOrder --preview --rows 5   # 样本(只在直连的 source 上)

从底层重算:加工(Transforms)。指标不要写在导入 SQL 里每次回源系统整份算:原始数据经 TableImport 进 dataset 只读一次,指标由 Transform 从 dataset 算成新的 dataset(一条 DuckDB 的 SELECT,输入按别名当表用),再作 Object Type 的数据源("dataset": "<Transform 的 apiName>")。输入一提交新事务就自动构建;同一个 Transform 同时只跑一个,跑的时候又来了新数据就跑完再跑一次。读的时候过期,执行的是它上游的同步,跑完一路算到对象。

  • 非增量(不写 incremental):每次整份重算。适合小表、要看前后行的计算(排名、前一天的值)。
  • append:只算新加的行、追加到产出。适合逐行的清洗、过滤、补字段(新产出只取决于新输入行)。
  • mergeAndReplace:新加的行先算出受影响的键(每个输入写 key 表达式),只把这些键在输入里的全部行重算一遍,再和上一份产出按键合并。适合按键汇总(按表计 × 班日、按订单、按日期 × 车间)。产出了受影响以外的键会失败——说明 key 写错了。
  • snapshotInputs:参考表(清单、价格表),整份读,它们的变化不触发、也不使之前的结果失效。
  • 什么时候整份:第一次构建、semanticVersion 变了(改了口径要回溯历史就加一)、非 snapshot 输入被整份替换过(SNAPSHOT 事务)。输入与定义都没变时构建直接成功、不跑(--force 照跑)。requireIncremental: true 时不能增量就失败(防止大表意外整份算)。
  • 时间:dataset 里不带时区的时间在 SQL 里是北京时间(例:班日 = CAST(read_at - INTERVAL 450 MINUTE AS DATE),7:30 起算);current_date 也是北京时间。
  • 边界:只执行一条 SELECT,只能读这次的输入;一次构建读的文件 ≤ 384 MB、产出 ≤ 500 万行、300 秒内算完。一个 dataset 只有一个产出者(TableImport 或 Transform);输入不能绕回自己的产出。
{ "apiName": "meter-shift-stats", "displayName": "表计班日统计",
  "inputs": {
    "readings": { "dataset": "meter-readings", "key": ["meter_code", "CAST(read_at - INTERVAL 450 MINUTE AS DATE)"] },
    "meters": { "dataset": "meters" } },
  "sql": "SELECT r.meter_code, CAST(r.read_at - INTERVAL 450 MINUTE AS DATE) AS shift_date, min(r.read_at) AS first_time, max(r.read_at) AS last_time, arg_max(r.value, r.read_at) AS last_value, count(*) AS read_count FROM readings r SEMI JOIN meters m ON m.meter_code = r.meter_code GROUP BY ALL",
  "incremental": { "semanticVersion": 1, "snapshotInputs": ["meters"], "output": "mergeAndReplace", "key": ["meter_code", "shift_date"] } }
aidc semantic transforms put --ontology cell-demo --file meter-shift-stats.json --dry-run   # 先预演:输入、环、名字
aidc semantic transforms put --ontology cell-demo --file meter-shift-stats.json
aidc semantic transforms build <transformRid> --wait        # 构建一次(之后输入一有新数据就自动构建)
aidc semantic transforms show <transformRid>                 # 定义与上次构建:增量还是整份、受影响的键、读写多少行

实时:订阅对象集

const client = semantic.ontology();
const issues = client.objects("production.order_line").where({ status: "异常" });
const sub = issues.subscribe({
  onChange({ object, state }) { state === "REMOVED" ? drop(object.__primaryKey) : upsert(object); },
  onOutOfDate() { reload(); },            // 整个对象集要重读:刚订阅时来一次、断得太久、依赖的类型变了
  onError({ subscriptionClosed, error }) { if (subscriptionClosed) showOffline(error); },
}, { properties: ["lineCode", "gap", "status"] });
// sub.unsubscribe()

写法同 OSDK 的 objectSet.subscribe:对象进来或变了 → ADDED_OR_UPDATED(带属性),离开对象集(被过滤掉、删了、源头消失)→ REMOVED(只带主键)。同步、Action、别人的修改都会推过来;断线自动带着序号续传,不丢不重;页面隐藏超过 1 分钟断开、切回续上;应用里的连接时长计入应用的计算分钟。CLI:aidc semantic subscribe <类型> [--where '{…}']。SDK 走 /api/v1/ontologySubscriptions/ontologies/{ns}/streamSubscriptions(SSE,消息一样);官方 OSDK 直连 /api/v2/ontologySubscriptions/ontologies/{ns}/streamSubscriptions(WebSocket,子协议 Bearer-<token>)。

访问与账号

const me = await semantic.admin.getCurrentUser();      // 我是谁、什么角色、能读哪些类型、能执行哪些 Action
if (!me.signedIn) semantic.admin.signIn();
await semantic.filesystem.setResourceAccess(rid, "public");                        // Private / Group / Public / Open to Internet
await semantic.filesystem.shareResource(rid, { group: "<组 id>", role: "viewer" });  // 部门就是组
await semantic.filesystem.shareApplication({ audience: "company" });                // 应用的分享

开放程度四档、Owner / Editor / Viewer 三种角色、只有 Owner 改分享;资源是 Ontology、Object Type、数字员工、文件。详见访问与账号。

组织、用户与组

组织架构是平台自带的,不在本体里另建:组织(一家公司,RID 写 cell-…)→ 用户(主组织恰好一个;在别家持 License 是那家的访客)→ 组(用户和 / 或其他组的集合,可以嵌套)。 部门就是组,上下级 = 组的嵌套;岗位、部门名这类信息是用户属性(department、jobTitle,键 → 多值)。资源分享、Marking 成员、对象安全策略的 group 条件都可以写组;智能体是资源,不是组织成员。

aidc semantic admin groups create --name 财务 --description 财务部的人           # 组织管理员(本组织开发者)
aidc semantic admin groups add-members <财务组 id> <账号 id> <应付组 id>         # 成员是账号或组(嵌套,不能成环)
aidc semantic admin groups add-members <财务组 id> <外部审计账号 id> --expires 2026-12-31   # 临时成员
aidc semantic admin groups members <财务组 id> --transitive                     # 连嵌套组里的人
aidc semantic admin users set-attributes <账号 id> department=财务 jobTitle=会计   # 身份源属性(主组织的组织管理员)
aidc semantic filesystem share <智能体 rid> --group <财务组 id>                  # 私有智能体只给财务组用

组的 organizations 决定哪些组织看得见它;组名在主组织内唯一;multipass: 开头的属性保留给平台。接口照 AdminV2:/api/v1/admin/groups/**、/api/v1/admin/users/**、/api/v1/admin/organizations/{rid}(设计与对照:aidc-cloud docs/organizations.md)。

数据安全:Markings 与安全策略

财务、薪资、采购价、技术配方这类数据也进 Semantic,用两种控制管住。上面的开放程度和角色决定「能不能打开这个资源」,下面这些再往里管到每一行、每一列:

控制 挂在哪 怎么判
Markings(强制控制) Ontology、Object Type、数据流、TableImport;或者写在行上(marking 类型的属性) 挂着的 Marking 全都满足才看得见(同一个 DISJUNCTIVE 类别里满足任一即可)。不看角色,Owner、开发者也一样;只限制、不授予;沿层级(Object Type ← Ontology)和数据依赖(数据流 → 用它的类型的对象)传播
对象安全策略(行) Object Type 定义里的 objectSecurityPolicy 按对象的属性和读的人(组、账号、用户属性、行上的 Marking)判断每个对象看不看得见
属性安全策略(列) Object Type 定义里的 propertySecurityGroups 一组属性要另外满足的条件或 Marking;不通过的人读到 null,也不能拿它筛选、排序、求和

先建 Marking,再挂到资源上或写进定义:

aidc semantic admin marking-categories create --name 数据分级                  # 类别:本组织开发者建
aidc semantic admin markings create --name 薪资 --category <类别 id> --member <人事组 id>
aidc semantic admin markings grant <薪资 id> USE <HR 负责人账号 id>             # USE = 可以把它挂到资源上
aidc semantic filesystem mark <配方类型的 rid> <技术配方 id>                    # 整个类型挂 Marking(要 USE、是类型的 Owner)
aidc semantic filesystem markings <rid>                                         # 直接挂的 + 继承来的

Marking 和类别建了不能删。角色:ADMINISTER 管成员与角色,USE 挂上,DECLASSIFY 去掉或停止继承;角色和成员互相独立(管 Marking 的人不一定看得见它保护的数据)。

行和列写在定义里(Demo Company 的员工薪酬;Marking 一律用 id 引用,aidc semantic admin markings list 查):

{
  "kind": "objectType", "apiName": "employeeCompensation", "title": "员工薪酬",
  "schema": {
    "columns": [
      { "name": "employeeId", "type": "string", "primaryKey": true },
      { "name": "accountId", "type": "string" },
      { "name": "baseSalary", "type": "decimal" },
      { "name": "rowMarkings", "type": "array", "arraySubType": "marking", "notNull": true }
    ],
    "objectSecurityPolicy": {
      "name": "compensation-rows",
      "granularPolicy": { "type": "and", "conditions": [
        { "type": "markingProperty", "property": "rowMarkings" },
        { "type": "or", "conditions": [
          { "type": "group", "name": "人事" },
          { "type": "comparison", "comparison": { "operator": "EQUAL",
            "left": { "type": "userProperty", "userProperty": { "type": "userId", "userId": {} } },
            "right": { "type": "property", "property": "accountId" } } }
        ] }
      ] }
    },
    "propertySecurityGroups": [{ "name": "pay", "properties": ["baseSalary"], "appliedMarkings": { "<薪资 id>": "MANDATORY" } }],
    "dataSecurity": { "markingConstraint": { "markingIds": ["<高管薪酬 id>"] } }
  }
}

意思是:HR 部门或本人看得见这一行,行上带的 Marking(比如高管的行带「高管薪酬」)也要满足;金额另外要「薪资」。其他三类数据的常见配法:

数据 配法
财务 Marking「财务」挂在 ERP 财务数据流上,用这条流的类型自动带上
采购价 采购订单行对采购员可见,unitPrice 放进属性安全策略,要「采购价」
技术配方 配方类型整个挂「技术配方」,成员只给研发负责人

规则:

  • 读:所有读路径都按读的人判定——Ontology API、对象集订阅、聚合、编辑历史、旧数据 API、/semantic 页面、自动化。Agent Key 是智能体身份,不是任何 Marking 的成员;Ontology SQL(Semantic 数据库)不含受保护的类型。
  • Action:可以新建自己看不见的对象;改一个属性要看得见它现在的值;删要看得见整个对象;链接两端都要看得见;开了 Action Log 的,执行人要满足被改类型的全部 Marking。
  • 自动化:条件和效果按拥有者(最后改条件或效果的人)的权限算;邮件通知按每个收件人的权限过滤。
  • 只在读的时候判定:函数的结果、Action 写进去的值、导出的文件不带原数据的安全。
  • 改安全策略:它是本体定义的一部分。改的人要满足改前改后涉及的全部 Marking,新加 Marking 要 USE,去掉或停止继承要 DECLASSIFY + USE。智能体在分支上改、开提案,由满足这些条件的审核人批准、合并(审批策略是 yolo 时也一样:Marking 是硬闸);--dry-run 自测时权限不够照样给出结果,「要谁来批」写在 warnings 里。分支预览(--branch)按 main 与分支里更严的那份判定。
  • 上限:每个策略最多 10 个比较;权重是常量 1、集合 1,000、Marking 条件 3,000,总和小于 10,000(属性安全策略连同对象安全策略一起算);不能对组或 Marking 成员取反;策略用到的属性为空的行谁都看不见;marking 属性必须 notNull,值要在 dataSecurity.markingConstraint 列出的 Marking 里。

试策略(照 Ontology Manager 的 Test security policies;只给开发者,结果不带属性值):

aidc semantic security test employeeCompensation --user <账号 id> --pk e1,e2
aidc semantic security test employeeCompensation --user <账号 id> --object '{"employeeId":"x","rowMarkings":[]}' --policy 新策略.json

SDK:semantic.admin.createMarking / addMarkingMembers / addMarkingRoleAssignments…、semantic.filesystem.addMarkings / removeMarkings / resourceMarkings、client.testSecurity(类型, {…});读对象时带 $loadPropertySecurityMetadata: true(照 OSDK),受属性安全策略保护的值会带上它的安全标记。

文件与图片:Media sets(非结构化数据)

图片、文档、音视频、邮件放进媒体集(Media sets),字节在你公司自己的 S3 存储里,Semantic 只存元数据;对象用媒体引用属性指向其中的文件,附件用 Attachment 属性。设计与规则:aidc-cloud docs/semantic-media.md。

  • 媒体集有 schema(IMAGERY、DOCUMENT、AUDIO、VIDEO、SPREADSHEET、EMAIL、DICOM、MULTIMODAL),按文件头认格式,不符合的拒收(invalid_media_item_schema);PDF 文档媒体集可以加 TXT / DOCX / PPTX(additional input formats)。
  • 同路径覆盖:同一路径再上传,旧的变成历史版本,直接引用仍可读;删除是软删。Transactional 媒体集的写入要在事务里,提交后才可见。
  • 保留策略:上传后 N 天、或被覆盖 / 删除后 N 天永久删除;缩短立即生效。
  • 虚拟媒体集:登记公司存储里某个文件夹下已有的文件(例如知识库),不拷贝;点 Sync 登记新文件。
  • 智能体读文件:semantic.mediaSets.extractText(媒体集, 媒体项) 取 PDF / TXT 全文;metadata() 拿页数、尺寸、时长。
const photos = await semantic.mediaSets.create({ name: "巡检照片", mediaSchema: "IMAGERY" });
const { mediaItemRid } = await semantic.mediaSets.upload(photos.rid, bytes, { mediaItemPath: "line-a/pump.png" });   // ≤ 4.4 MB
await semantic.mediaSets.uploadLarge(photos.rid, file, { mediaItemPath: "video/site.mp4" });                       // 大文件直传 S3(≤ 50 GB)
const text = await semantic.mediaSets.extractText(docsRid, pdfRid);                                                   // PDF 全文

在对象上用:Object Type 的媒体引用属性要配 media source(写在定义的 datasources 里,第一个是 Upload destination);Action 参数可以是临时上传的媒体或附件,Action 提交成功后才持久化(附件一小时内要用上,一个附件一生最多关联 10 个对象)。

{ "columns": [{ "name": "inspectionId", "type": "string", "primaryKey": true }, { "name": "photo", "type": "mediaReference" }, { "name": "report", "type": "attachment" }],
  "datasources": [{ "type": "media", "mediaSourceRids": [{ "type": "mediaSetRid", "mediaSetRid": "ri.mio.aidc.media-set.…" }], "properties": ["photo"] }] }
const client = semantic.ontology();
const photo = await client.uploadMedia(fileBytes, "site-north.png");            // 临时媒体 → MediaReference
const report = await client.uploadAttachment(pdfBytes, "巡检单.pdf");           // 附件 → { rid, filename, sizeBytes, mediaType }
await client.action("record-inspection").applyAction({ inspectionId: "I-1", photo, report: report.rid });
const meta = await client.media("inspection", "I-1", "photo").fetchMetadata();  // { path, sizeBytes, mediaType }
const bytes = await (await client.media("inspection", "I-1", "photo").fetchContents()).arrayBuffer();

访问:媒体集沿 Ontology 继承(可再分享给人、部门,或设为 Public);把媒体集配成属性的 media source = 访问控制交给本体——看得见对象和这个属性的人就能读它的媒体。Agent Key 只读(受限 Key 见下)。读内容时服务端 302 到预签名 S3 地址(10 分钟有效),fetch 会自动跟随;整页 HTML、SVG 这类会执行的内容只在 Object View 的沙箱 iframe 里显示,直接在地址栏打开会去 Object View 的全屏视图(?embedded=true)。

大文件往属性上传(照 Upload Media Content,直传形态):client.uploadMediaContent(类型, 属性, 文件, { mediaItemPath, contentType }) 开会话、把字节直传公司的 S3、完成后拿 MediaReference,一小时内交给 Action——字节不经过平台,多大都行。

const html = await client.uploadMediaContent("loopReport", "html", file, { mediaItemPath: "daily-output.html", contentType: "text/html" });
await client.action("publish-loop-report").applyAction({ slug: "daily-output", title: "日产量日报", sha256, html });

机器发布(受限 Agent Key):客户箱上的脚本定期发布整页报表,用一把受限 Agent Key(application restrictions:operations = api:use-ontologies-read / api:use-ontologies-write,resources = 列出的对象类型与 Action)。它只能读列出的类型、往它们的媒体属性直传、执行列出的 Action,别的接口一律 403,聊天网关也不认它。Key 由本组织管理员在控制台签发(restrictions 字段)。箱上用 Python 标准库脚本 publish_loop_report.py(在 developer/semantic-agent/):内容没变就一个请求都不发,变了只有 3 个很小的 JSON 请求 + 1 次直传 S3,发布后不回读。

AIDC_AGENT_KEY=aidc-sk-… AIDC_SEMANTIC_ONTOLOGY=cell-demo \
python3 publish_loop_report.py --file out/daily-output.html --slug daily-output --title "日产量日报" --data-date 2026-10-01
# → {"ok": true, "decision": "published", "pageUrl": "https://www.ai-dc.ai/semantic/cell-demo/objects/loopReport/daily-output", …}
aidc semantic media-sets create --name 巡检照片 --schema IMAGERY
aidc semantic media-sets upload <媒体集 RID> pump.png --path line-a/pump.png
aidc semantic media-sets items <媒体集 RID> --path line-a/pump.png     # 版本历史
aidc semantic media-sets text <媒体集 RID> <媒体项 RID>                 # PDF 全文
aidc semantic upload-media loopReport html daily-output.html --content-type text/html --json   # 往属性直传 → MediaReference

Space:每个人与智能体自己的空间

Space 在 www.ai-dc.ai/semantic/<组织>/space。本组织的每个人、每个智能体都有自己的 Space(Your files)。人与智能体在 Space 里是一样的:都能放东西、都能被分享到。

放什么 是什么
页 Markdown。保存时带上次读到的版本,过期的保存被拒(不悄悄覆盖别人的修改)
文件 字节直传到公司自己的 S3,单个最大 5 GB(智能体 64 MB)
站点 一份自包含的 HTML(≤ 1.5 MB)自动部署成网页,有托管地址;换内容地址不变
Project 共享的容器。分享 Project,里面的东西一起给到(只加不减)
  • 分享:给人、智能体、组;角色 Owner / Editor / Viewer;开放程度 Private / Group / Public / Open to Internet(站点设成 Open to Internet,不登录也能打开)。只有 Owner 能分享、放进回收站、永久删除。
  • 智能体读的不超过它的负责人(owner):owner 看不到的,智能体也读不到。分享给有 owner 的智能体时加 --also-owner(SDK:alsoOwner: true),同时分享给它的 owner。
  • 智能体建的东西:智能体是 Owner;它有已核验的 owner 时,owner 也是 Owner。智能体不能把东西开到 Public 或 Open to Internet:要人来设。
  • 删除:先放进回收站(站点随即停止服务、可以恢复),再永久删除(字节、站点、分享一起删)。
  • 读内容:页 = Markdown 原文;文件 = 302 到预签名地址;站点 = 浏览器去托管页,Key 直接拿 HTML 原文。
aidc space deploy weekly-report.html --title "周报" --json        # 部署站点 → siteUrl
aidc space share <id> --tier internet                              # 不登录也能打开
aidc space share <id> --user zhangsan --agent procurement --also-owner --role viewer   # 分享给人、智能体(及它的 owner)
aidc space page "周会纪要" --file notes.md                          # 建页;aidc space edit <id> --file notes.md 改页
aidc space upload contract.pdf photo.png                            # 上传文件(.html 自动部署成站点)
aidc space ls --tab shared                                          # 分享给我的;--tab favorites / yours,--view pages / sites / images / trash
aidc space get <id> --out back.html                                 # 下载:页、文件、站点的 HTML
aidc space people                                                   # 分享的候选:本组织的人、智能体(AI)、组
aidc space empty-trash --dry-run                                    # 回收站有多少项、多少字节;去掉 --dry-run 就清空(永久删除,释放存储)
const site = await semantic.space.deploySite({ displayName: "周报", html });
await semantic.space.share(site.id, { to: [{ type: "agent", id: "procurement" }], alsoOwner: true, tier: "group" });
const shared = await semantic.space.list({ tab: "shared" });            // 分享给我的
const { markdown, version } = await semantic.space.readPage(pageId);
await semantic.space.update(pageId, { markdown: markdown + "\n- 新的一行", baseVersion: version });

接口在 /api/v1/space/**:items(列表、建、取、改、放进回收站)、items/{id}/content、items/{id}/share(取 / 分享)、items/{id}/favorite、restore、permanentlyDelete、trash/empty(清空回收站,支持 dry-run)、uploads(直传会话)与 uploads/{id}/complete、recent、principals。Space 里的东西算进 owner 的存储(回收站里的照样算,清空才释放),见 aidc me。认网页登录、开发者 Key 与 Agent Key(受限的 Agent Key 要有 api:use-filesystem-read / api:use-filesystem-write)。

自动化(Automate)

数据一变(或到了时间)就做事:写在工作流应用的清单 workflow 里,按 Automate 的写法——条件(trigger.change = 对象新建 / 修改,when 过滤;trigger.schedule = 时间;手动)加效果(Action、模型分析、通知)。

const { run } = await semantic.automate.run({ rfq_no: "RFQ-001" }, { slug: "quote-workflow", mode: "preview" });
semantic.automate.watch(run.id, { onRun: draw, onDone: finish }, { slug: "quote-workflow" });

触发读的是 Semantic 的变化账(和对象集订阅同一条),不轮询、不写 cron。详见自动化。

组织级的 Automation(aidc semantic automations upsert --file)用 Automate 的条件与效果:对象集条件(Objects added / modified / removed)、时间条件、Run on all objects(到点对对象集里现在的全部对象跑效果——「逾期」「超过一天没处理」这种因为时间过去才进集合的提醒用它)。邮件通知的收件人可以取自触发对象的属性({ "type": "propertyBacked", "property": "assigneeAccountId" }),"executionMode": { "type": "perObject" } 每个对象一封:

{
  "apiName": "dev-task-overdue", "displayName": "任务逾期", "status": "active",
  "condition": { "type": "runOnAllObjects", "every": "1d", "at": "09:30", "weekdays": [1, 2, 3, 4, 5],
    "objectSet": { "type": "filter", "objectSet": { "type": "base", "objectType": "devTask" }, "where": { "type": "and", "value": [
      { "type": "in", "field": "status", "value": ["待接受", "进行中", "阻塞"] },
      { "type": "relativeDateRange", "field": "dueDate", "relativeEndTime": { "value": 0, "timeUnit": "DAYS" }, "timeZoneId": "Asia/Shanghai" } ] } } },
  "effects": [{ "type": "notification", "channel": "email", "executionMode": { "type": "perObject" },
    "recipients": [{ "type": "propertyBacked", "property": "assigneeAccountId" }],
    "title": "任务逾期:{{title}}", "template": "{{#objects}}任务「{{title}}」截止 {{dueDate}},现在是「{{status}}」。{{/objects}}" }]
}

效果有三种:Action("type": "action":以 automation 的拥有者——最后一次改条件或效果、保存它的人——的身份执行一个 Action Type,按他现在的权限,和他自己在界面里执行一样:参数校验、提交条件、Action Log、留痕都照常)、Function("type": "function":执行一个已发布的函数版本,在平台的隔离运行时里跑;运行里只记结果摘要,函数返回的 Ontology 编辑不生效——要改对象用 Action)、邮件通知。发钉钉 / 企业微信、回写 ERP 这类「调外部系统」写成 Action 的 side effect webhook,再用 Action 效果执行它。

{
  "apiName": "close-overdue", "displayName": "逾期工单自动关", "status": "active",
  "condition": { "type": "objectsAdded", "objectSet": { "type": "filter", "objectSet": { "type": "base", "objectType": "ticket" },
    "where": { "type": "eq", "field": "status", "value": "overdue" } }, "evaluation": { "everyMinutes": 10 } },
  "effects": [
    { "type": "action", "actionType": "close-ticket", "parameters": { "ticket": { "$effectInput": "object" }, "note": "自动关闭" },
      "executionSettings": { "retryConfig": { "backoffStrategy": { "type": "constantBackoff", "attemptLimit": 3, "durationMillis": 60000 } } } },
    { "type": "function", "function": "summarizeTicket", "version": "1.2.0", "autoUpgrade": true, "parameters": { "ticketId": { "$effectInput": "primaryKey" } } }
  ],
  "fallbackEffects": [ { "type": "action", "actionType": "log-failure",
    "parameters": { "message": { "$effectInput": "failureMessage" }, "event": { "$effectInput": "eventId" }, "automation": { "$effectInput": "automationRid" } } } ]
}
  • 效果输入:参数写 { "$effectInput": "…" } 就代入触发对象——object(一个对象:每个对象执行一次)、objects(这一批对象:对象集 / 对象列表参数)、primaryKey、property:<属性>(触发时的值)、automationRid、eventId;failureMessage 只在失败效果里有值。只有暴露对象的条件(对象集条件、Run on all objects)能用对象类输入;objects 不能和单对象输入混用。
  • 执行方式:不写就按输入推断(单对象输入 → 每个对象一次;objects → 这批对象一次;没用效果输入 → 每次触发一次);"executionMode": { "type": "perBatchOfObjects" } + "executionSettings": { "batchSize": 100 } 按批(批大小是上限,不凑满)。
  • 顺序、重试、失败效果:Action / Function 效果按列出的顺序执行,一个对象在某个效果上失败了,就不进入后面的效果;executionSettings.retryConfig.backoffStrategy 配重试(constantBackoff { attemptLimit, durationMillis } / exponentialBackoff { attemptLimit, stepDurationMillis, maxDurationMillis },可加 jitter:{ "type": "jitterFactor", "jitterFactor": 0.25 } 或 { "type": "jitterDurationMillis", "jitterDurationMillis": 5000 });重试用完仍失败,对失败的那批对象执行 fallbackEffects。效果至少执行一次:Action 与函数要能承受重复执行。
  • 保存时就校验:Action / 函数与版本要在、参数名对、必填参数有值、效果输入和参数类型对得上、拥有者能执行这个 Action。
  • 函数:aidc semantic functions publish <源码.js> --api-name … --version … --output '{…}' 发布(见下面「动力部分」);autoUpgrade: true 自动用同一大版本里更新的稳定版本。
  • 已停用:钉钉 / 企业微信通知与 agentScript(在客户箱上跑 Loop 脚本)——新的 automation 不再接受(automate_legacy_effect),已经在跑的照常运行;迁移表见闭环。

应用(Applications,Workshop 模块)

看板、报表、工作台不用再写成一份 HTML 整页上传:在 Semantic 里建一个 Application(Workshop 模块),只存定义——页面、分区、组件、变量——数据每次打开时按看的人的权限从 Ontology 现算,没人打开就不计算、不同步。组件照 Workshop:Metric Card、Object Table、Chart: XY(柱 / 横向柱 / 折线,可分段)、Chart: Pie、Pivot Table、Filter List、Markdown、Data Freshness、Object Set Title;变量是对象集(REST API v2 的 ObjectSet,可套 Filter List 的筛选)、对象集聚合、静态值。

# 保存一个新版本(没有就新建);先 dryRun 校验:类型、属性、变量引用全部按你的权限检查
curl -X POST "$AIDC/api/v1/workshop/modules?ontology=cell-demo&dryRun=true" -H "authorization: Bearer $AIDC_API_KEY" -H "content-type: application/json" -d @cloud-costs.json
# 用应用:取一页的数据(智能体也用这个;每个组件一份结果)
curl -X POST "$AIDC/api/v1/workshop/modules/ri.aidc.workshop.cell-demo.module.cloud-costs/evaluate" -H "authorization: Bearer $AIDC_API_KEY" -H "content-type: application/json" -d '{"page":"overview","filters":{"vendorFilter":{"vendor":"Vercel"}}}'
{
  "apiName": "cloud-costs", "displayName": "云费用看板",
  "definition": {
    "header": { "title": "云费用看板" },
    "variables": [
      { "id": "vendorFilter", "type": "objectSetFilter", "objectType": "cloudCost" },
      { "id": "costs", "type": "objectSet", "objectSet": { "type": "base", "objectType": "cloudCost" }, "filters": ["vendorFilter"] },
      { "id": "totalUsd", "type": "numeric", "aggregation": { "objectSet": "costs", "metric": { "type": "sum", "field": "costUsd" } } }
    ],
    "pages": [{ "id": "overview", "title": "总览", "sections": [
      { "widgets": [{ "id": "filters", "type": "filterList", "objectSet": "costs", "output": "vendorFilter", "filters": [{ "property": "vendor", "kind": "select" }] }] },
      { "widgets": [{ "id": "kpi", "type": "metricCard", "metrics": [{ "label": "合计(美元)", "variable": "totalUsd" }] }] },
      { "layout": "columns", "sections": [
        { "widgets": [{ "id": "byVendor", "type": "chartXY", "chart": "bar", "objectSet": "costs", "groupBy": { "type": "exact", "field": "vendor" }, "metric": { "type": "sum", "field": "costUsd" } }] },
        { "widgets": [{ "id": "byMonth", "type": "pivotTable", "objectSet": "costs", "rows": [{ "type": "exact", "field": "month" }], "metrics": [{ "label": "美元", "metric": { "type": "sum", "field": "costUsd" } }], "totals": true }] }
      ] }
    ] }]
  }
}
  • 日历区间(本月、本年、上月)用 Date / Timestamp 变量({ "id": "monthStart", "type": "timestamp", "transformation": { "startOf": "month", "timeZoneId": "Asia/Shanghai" } }),在过滤里写 { "type": "gte", "field": "createdAt", "value": "{{monthStart}}" };relativeDateRange 是相对今天前后几天,不对齐日历。
  • 只算当前页(Workshop 的 lazy loading);读由数据源同步的类型前,过期才按需同步(页面上的「立即同步」最多等 20 秒)。
  • 版本与发布:每次保存是一个新版本;用户看到的是发布的那个版本。智能体可以保存版本;谁能发布看组织的审批策略(和本体提案同一条规矩):review(缺省)下,作者是智能体的版本要人在 Semantic 的应用页上点「发布」;yolo 下,开发者 Key(含智能体在用的)也能发布(aidc semantic applications publish <rid> <版本>)。每次发布都记进审计日志。
  • 权限:打开应用看组织在这个 Ontology 上的角色(成员只看已发布的,开发者看草稿与任一版本);应用里的数据另外按类型判定——读不到的类型,组件显示无权限,不会漏数据。
  • 页面:https://www.ai-dc.ai/semantic/<组织>/applications。筛选、翻页、切换页面都在 URL 里,可以直接分享。

留痕与用量

  • 改数据的留痕:开了 actionLog 的 Action 每次成功提交写一个 Action Log 对象;client.editsHistory(类型, { primaryKey }) 看一个对象的每次修改。
  • 应用日志:semantic.observability.track / feedback / error 记使用、反馈、错误;summary / events 看(应用日志)。
  • 用量与账单:semantic.usage.summary / records / check / prices / estimate(用量与账单)。
  • AIDC 平台对象类型:平台替你的组织记下的应用、模型用量、应用日志、自动化运行,可以作为只读的 Object Type 进你的 Ontology——aidcApplication、aidcModelUsage(按天 × 应用 / Key × 模型)、aidcAppEvent、aidcAutomationRun。本组织开发者打开 /semantic 时,智能体(数据库 Adis)会开一个提案,审核合并后才出现(组织的审批策略是 yolo 时,检查通过就自动合并;不需要就关掉提案,同一批定义不会再提);之后按需同步(合并后、点「立即同步」、超过 1 小时有人看时)。用量、日志、自动化运行只给本组织开发者(可以在 Share 里开给别人),应用列表和 Nexus 里看到的一样。有了它们,看账单、查反馈就是查对象集,超支提醒就是一个自动化:
const byDay = await client.objects("aidcModelUsage").aggregate({ $select: { "costUsd:sum": "desc" }, $groupBy: { day: "exact" } });
const openFeedback = await client.objects("aidcAppEvent").where({ kind: "feedback", status: "open" }).fetchPage();

Ontology

语义层的建模语言、名字和 API 形状全部用标准的 Ontology 构件(设计:docs/semantic-ontology.md)。上面的写法(describe、objects、action().apply)继续可用;新写法是 semantic.ontology(),与 OSDK 同形。示例取自 Demo Company 的示例本体(打开示例,要先登录 AIDC 账号;命名空间 cell-demo,全部是虚构数据;定义与数据在 developer/apps/ontology-demo-data/,应用在 developer/apps/ontology-demo/)。

语义部分(名词)

构件 是什么 Demo 里的例子
Object Type 一类对象:主键、title、属性 customer 客户公司、agent 智能体、application 应用、modelUsage 模型用量、cloudCost 云费用
Property 属性;base type 照官方(string、integer、long、double、decimal、boolean、date、timestamp、array、struct、geopoint、vector、timeseries…) customer.location(geopoint)、customer.contact(struct)、modelUsage.dailyTokens(timeseries)
Derived Property 沿链接读时计算(最多 3 跳;count、sum、avg、min、max、collectList、collectSet) customer.agentCount = 智能体个数;customer.modelCostUsd = 模型费用合计
Link Type 两个 Object Type 的关系,两端各有名字;1:N 用外键,N:M 另存每一条链接 customerAgents:customer.agents ↔ agent.customer;applicationAgents(N:M)
Interface 多个 Object Type 共有的形状,可以继承 Billable(继承 Monthly):modelUsage 和 cloudCost 都实现它,可以一起按月汇总成本
Shared Property 跨类型复用的属性定义 costUsd、month
Value Type 带约束的类型(enum、range、length、regex…),写入时校验 cellId(cell- 开头)、yearMonth、customerStage(试点 / 付费 / 暂停)

动力部分(动词、函数)

构件 是什么 Demo 里的例子
Action Type 受控的写操作:参数 + 规则(createObject、modifyObject、createOrModifyObject、deleteObject、createLink、deleteLink)+ 提交条件(submission criteria) adjust-seats:座位数不能少于成员数;assign-agent:给应用接入一个智能体(建一条 N:M 链接)
Action Log 开了 actionLog 的 Action,每次成功执行都写一个 log.<action> 对象 log.adjust-seats:谁在什么时候把哪家的座位数改成多少
Object Set 对象的集合:过滤、并 / 交 / 差、沿链接走(searchAround)、按接口取、派生属性 付费客户的全部智能体
Function 代码写的逻辑,在隔离运行时里执行;语义化版本,发布后不能改 aidc semantic functions publish count.js --api-name countPaidCustomers --version 1.0.0 --output '{"type":"integer"}'(ES module,默认导出 (params, ctx) => 结果,ctx 读对象);查询经 /api/v2/ontologies/{ns}/queries/countPaidCustomers/execute 执行,也能做自动化的 Function 效果

定义

定义还是 JSON,kind 用标准名(objectType、linkType、actionType、interfaceType、sharedPropertyType、valueType;旧的 object、link、action、enum 照旧可用)。

{
  "kind": "linkType",
  "apiName": "customerAgents",
  "title": "公司的智能体",
  "schema": {
    "from": "customer", "to": "agent", "cardinality": "ONE_TO_MANY",
    "apiNameAtoB": "agents", "apiNameBtoA": "customer",
    "foreignKey": { "side": "to", "property": "customerId" }
  }
}
{
  "kind": "actionType",
  "apiName": "adjust-seats",
  "title": "调整座位数",
  "schema": {
    "parameters": [
      { "name": "customer", "type": "object", "objectType": "customer", "required": true },
      { "name": "seats", "type": "integer", "required": true, "min": 1, "max": 10000 }
    ],
    "rules": [{ "type": "modifyObject", "objectType": "customer", "object": "$customer", "values": { "seats": "$seats" } }],
    "submissionCriteria": [{
      "condition": { "type": "comparison", "left": { "param": "seats" }, "operator": "gte", "right": { "param": "customer", "property": "members" } },
      "failureMessage": "座位数不能少于成员数"
    }],
    "actionLog": true
  }
}

名字照官方大小写:Object Type 与 Interface 用 PascalCase(大写字母开头、只含字母和数字,如 Employee、GreigeInStore;Object Type 名在本体里不分大小写唯一,ontology、object、link 这类保留字不能用),Property、Link Type 两端、Value Type、Shared Property 用 camelCase,Action Type 用 kebab-case。早先小写开头的 Object Type 名(如 customer、production.order_line)照常能用,定义时给警告;新的类型请用 PascalCase。

提交条件里比较的值可以是参数({ "param": … },对象参数可带 property)、常量({ "literal": … }),或执行人({ "user": "id" | "name" | "role" | "authorKind" })。authorKind 是执行人是人还是智能体(human / agent;Agent Key 和声明了智能体身份的开发者 Key 都是 agent)。「只有人能批」写成 { "type": "comparison", "left": { "user": "authorKind" }, "operator": "is", "right": { "literal": "human" } }——用肯定的写法,不要写成「不是 agent」。用了 authorKind 的 Action 暂时只能经 v1 接口、CLI 或 Semantic 界面执行,v2 接口(OSDK)会回 403。

从零做一个会执行的 Action(定义、只校验、执行、提交条件、命令行 / SDK / REST、做成应用、交给自动化):Academy 课程《动手:做一个会执行的 Action》,配套样板见样板应用的「座位申请」。新的 Object Type 只能有一个主键属性(旧的复合主键类型照旧可用,定义时给警告)。

定义里写了不认识的字段(多半是拼错了,比如把 submissionCriteria 写成 submissionCriterias)会直接被拒,错误信息给出路径——以前这类字段会被悄悄丢掉,Action 就少了提交条件。

Action 调外部系统:webhook(writeback 与 side effect)

webhook 挂在 Data Connection 的数据源上,凭证在数据源里(平台加密保存),不经过调用方。Action 可以把 webhook 配成两种:

  • writeback(一个):校验通过之后、规则之前调用;外部系统拒绝(或超时)就整个 Action 不生效,语义层一条都不改,原因原样返回给执行人(webhook_failed)。输出在规则里用 $writeback.<输出名>。
  • side effect(sideEffects,最多 10 个):改动提交之后调用,可以多个、不保证顺序;失败不回滚改动、也不报给执行人——结果记在这次 Action 的执行记录里(失败另记一条错误事件)。适合发消息、通知、写到别的系统。
{
  "kind": "actionType",
  "apiName": "stop-ec2-instance",
  "title": "关机",
  "schema": {
    "parameters": [{ "name": "instance", "type": "object", "objectType": "ec2Instance", "required": true }, { "name": "reason", "type": "string" }],
    "submissionCriteria": [{ "condition": { "type": "comparison", "left": { "param": "instance", "property": "state" }, "operator": "is", "right": { "literal": "running" } }, "failureMessage": "只有运行中的实例能关机" }],
    "webhooks": {
      "writeback": { "webhook": "aws/ec2-stop-instances", "inputs": { "region": "$instance.region", "instanceId": "$instance.instanceId", "expectedLaunchTime": "$instance.launchTime" } },
      "sideEffects": [{ "webhook": "im-robot/send-text", "inputs": { "content": "$reason" } }]
    },
    "rules": [{ "type": "modifyObject", "objectType": "ec2Instance", "object": "$instance", "values": { "lastAction": "stop", "lastActionAt": "$now", "lastActionResult": "$writeback.currentState" } }],
    "roles": ["developer"],
    "actionLog": true
  }
}
  • webhook 写成 <数据源>/<名字>(如 aws/ec2-stop-instances、im-robot/send-text),或 webhook 的 RID。输入的写法与规则相同:$参数、$对象参数.属性、字面量;side effect 的输入还可以用 $writeback.<输出名>。定义时校验:webhook 存在、必填输入都给了、没有多余的输入、$writeback.<输出> 是它的输出、这个组织能用那个数据源。
  • 规则只写只在语义层维护的属性(writeback: true);状态这类从数据源来的属性等数据源同步回来——规则改它会一直盖住之后同步来的值(定义时会提醒)。
  • 只校验($validateOnly)与预演不调用外部系统(预演给出会怎么调);有 writeback 的 Action 一次只能提交一个请求(不收 applyBatch)。
  • 平台提供的数据源 aws 只给 AIDC 自己的组织(aws/ec2-stop-instances、aws/ec2-start-instances、aws/ec2-set-tag)。样板:developer/apps/aws-servers。

自己的系统:REST API 数据源上的 webhook

自己的系统(企业 IM 的机器人、工单系统、ERP 的接口……)先建一个 REST API 数据源(Connection,configuration.type 写 rest:一个或多个 domain,每个 domain 的认证 Basic / Bearer Token / API Key(请求头或查询参数),带认证的 domain 必须是 HTTPS;附加秘密给模板用),再在它上面建 webhook:

{
  "connection": "im-robot",
  "apiName": "send-text",
  "displayName": "群里发一条文本",
  "inputs": { "content": { "type": "string" } },
  "calls": [{
    "method": "POST",
    "path": "/robot/send",
    "body": { "type": "json", "value": { "msgtype": "text", "text": { "content": "{{content}}" } } },
    "extract": { "errcode": "/errcode", "errmsg": "/errmsg" }
  }],
  "outputs": { "errcode": { "type": "integer" }, "errmsg": { "type": "string" } },
  "limits": { "timeoutMs": 10000, "rateLimit": { "executions": 20, "per": "minute" } }
}
  • 输入:boolean、integer、long、double、string(allowedValues 限定取值)、date、timestamp、list(elementType)、record(fields 要求的键 / valueType 其余键)、optional(wrappedType,可以不给);不是 optional 的都必填。
  • 请求(calls,最多 10 个,按顺序执行):method、domain(数据源有多个 domain 时写 host)、相对路径 path、query、headers、body——json(写成 JSON)、formUrlEncoded、text(contentType 可选 text/plain、application/json、application/xml、text/xml、text/html)。数据源的认证自动加上,请求里不再写。最多一个会改外部系统的请求(GET / HEAD / OPTIONS 以外的方法;换令牌这类不改数据的 POST 标 "isHttpMethodSafe": true)。
  • 模板:{{名字}} 原样插入文本,{{json 名字}} 插入 JSON,{{名字.键.0}} 取记录的键 / 列表的下标;json 请求体里整个字符串恰好是一个 {{名字}} 时换成那个值本身(数字仍是数字)。{{secrets.<名字>}} 取数据源的附加秘密——只在发送那一刻解开,预演与任何回显里都打码。
  • 串起来:extract 用 JSON pointer 从响应里取值("/" 整个响应、"/a/b" 按键、"/items/0" 按下标),取出来的变量给后面的请求用({{accessToken}})——比如先 GET /gettoken 换令牌,再带着令牌发消息。
  • 输出:outputs 的 from 指一个抽取变量(不写 = 同名的抽取变量,再没有就取最后一个响应里同名的顶层字段)。很多 IM 接口出错时仍回 HTTP 200、把错误放在 errcode 里:把它配成输出,执行记录里就看得到。
  • 上限:timeoutMs(缺省 20 秒,最多 180 秒)、rateLimit(每秒 / 分钟 / 小时 / 天几次,缺省每分钟 30 次)、concurrency(同时几个,缺省 10)、retryableStatusCodes(遇到就再试,最多 2 次)。
  • 出口:平台从公网直连;解析到内网 / 本机地址的 domain 会被拒绝。
  • 建(按 apiName 幂等,定义变了版本 +1)、读、删(还有 Action 在用时拒绝)、手动试:
aidc semantic connectivity webhook put --ontology cell-demo --file send-text.json [--dry-run]
aidc semantic connectivity webhooks --ontology cell-demo [--connection im-robot]
aidc semantic connectivity webhook test <webhookRid> --inputs '{"content":"测试"}' --dry-run   # 只渲染请求(秘密打码),不发
aidc semantic connectivity webhook test <webhookRid> --inputs '{"content":"测试"}'             # 真发一次:输出、每个请求的状态 / 耗时 / 大小

API:GET|POST /api/v1/connectivity/webhooks?ontology=<组织>、GET|PUT|DELETE /api/v1/connectivity/webhooks/{webhookRid}、POST /api/v1/connectivity/webhooks/{webhookRid}/execute({ "inputs": {…}, "dryRun": true })。webhook 的权限跟着数据源走:看、建、改、删、手动试都只给本组织开发者(数据源、同步、agent、出口策略的配置同样只给开发者看——连到哪里、怎么认证、查什么只该让管线开发者知道;其他人经 Object Type 拿数据);经 Action 调用只看 Action 的权限。

Action 的通知:执行后发邮件

Action 的 Notification side effect:Action 可以配 notifications——所有改动提交之后,给收件人每人发一封邮件。派任务、转派、提交验收、验收通过这类「要让某个人知道」的 Action 用它。

{
  "kind": "actionType",
  "apiName": "create-dev-task",
  "title": "派任务",
  "schema": {
    "parameters": [{ "name": "title", "type": "string", "required": true }, { "name": "assignee", "type": "object", "objectType": "employee", "required": true }],
    "rules": [{ "type": "createObject", "objectType": "devTask", "values": { "taskId": "$uuid", "title": "$title", "assigneeId": "$assignee", "assigneeAccountId": "$assignee.accountId", "assignedAt": "$now", "status": "待接受" } }],
    "notifications": [{
      "recipients": "$assignee.accountId",
      "subject": "新任务:{{{title}}}",
      "body": "{{{actionTriggerer}}} 派给你一个任务:{{{title}}}",
      "link": { "text": "打开任务", "target": { "type": "newObject", "objectType": "devTask" } }
    }],
    "actionLog": true
  }
}
  • 收件人:$参数、$对象参数.属性(对象上存的 AIDC 账号 ID)、$user(执行人),或固定的账号 ID;可以写成数组。收件人必须是这个组织的人(本组织账号、持本组织 License)。
  • 内容:subject(≤ 250 字)、body(≤ 1,000 字,超长截断);{{{参数}}}、{{{对象参数.属性}}}(对象参数写它的标题)、{{{actionTriggerer}}}(执行人)。内容按改动之前渲染。link 指对象参数、这次新建的对象(newObject),或一个 URL(https://… / 站内 /…)。
  • 权限:缺省有一个收件人不合格(不是本组织的人、账号停用、看不到这次引用的数据)整个 Action 就不执行;"notificationSettings": { "renderingSettings": "anyNotificationRenderingCanFail" } 改成只发给合格的人。
  • 预演($validateOnly + preview)返回会发给谁、标题与正文,不发。每封都记在外发账里(aidc notify 看得到);邮件通道没配时记为「未配置」。

到期提醒(逾期、超过一天没接受)用上面「自动化(Automate)」里的 Run on all objects:见 developer/apps/dev-work/automations/。

读与写(OSDK 写法)

const client = semantic.ontology();                        // 应用里自动取应用所在公司;CLI / 智能体用 Key 所属公司

const paying = client.objects("customer").where({ stage: "付费", seats: { $gt: 30 } });
const page = await paying.fetchPage({ $orderBy: { seats: "desc" }, $pageSize: 20 });
// page.data[i]:{ __primaryKey, __apiName, __title, name, seats, location: { type: "Point", coordinates: [...] }, … }

const agents = await paying.pivotTo("agents").fetchPage();  // 沿链接走(searchAround)
const one = await client.objects("customer").fetchOne("cell-demo-a");

// 聚合(结果形状同 OSDK)
const byMonth = await client.interface("Billable").aggregate({ $select: { "costUsd:sum": "desc" }, $groupBy: { month: "exact" } });

// 派生属性
const withCost = client.objects("customer").withProperties({ apps: (b) => b.pivotTo("applications").aggregate("$count") });

// Action:先只校验,再执行
await client.action("adjust-seats").applyAction({ customer: "cell-demo-a", seats: 60 }, { $validateOnly: true });
const r = await client.action("adjust-seats").applyAction({ customer: "cell-demo-a", seats: 60 }, { $returnEdits: true });
// r.validation.result = VALID / INVALID(参数逐项、提交条件逐条);r.edits:新建 / 修改 / 删除了哪些对象和链接

where 写法:$eq $ne $gt $gte $lt $lte $isNull $in $contains $startsWith $containsAnyTerm $containsAllTerms $containsAllTermsInOrder $matchesRegex $within $and $or $not;聚合:$count、属性:sum|avg|min|max|exactDistinct|approximateDistinct,分组 exact、$fixedWidth、$ranges、$duration。

Python(客户箱上的智能体与 Loop 脚本)

客户箱上的智能体(数字员工)和它们的 Loop 脚本用 aidc_semantic.py(developer/semantic-agent/,只用 Python 标准库),写法和上面一一对应:

from aidc_semantic import ontology, sql, connect, publish_loop_report

client = ontology()
stock = client.objects("stock.finishedInStore").where({"storeNo": "G02", "stockQty": {"$gt": 0}})
page = stock.fetch_page(page_size=50, order_by={"storeInDate": "desc"}, select=["orderNo", "stockQty"])
for o in stock.iterate(select=["orderNo", "stockQty"]): ...            # 一页一页读完
stock.aggregate({"$select": {"stockQty:sum": "desc"}, "$groupBy": {"materialTypeName": {"$exactWithLimit": 100}}})
stock.count()
client.action("adjust-seats").apply({"customer": "cell-demo-a", "seats": 60}, validate_only=True)

rows = sql('SELECT "orderNo", sum("stockQty") AS kg FROM "stock.finishedInStore" GROUP BY 1')   # Ontology SQL
conn = connect(source="hsdyeingerp")              # 原来直连 ERP 的脚本:只换连接,T-SQL 照写(改写到原表镜像;改写器 aidc_semantic_tsql.py 随箱上安装)
publish_loop_report(html, slug="daily-output", title="日产量日报")    # 整页看板发布进 Semantic(受限 Key)
  • 凭证按顺序找,环境变量没有就读 $HERMES_HOME/.env(智能体自己的 profile;不去 ~/.env、./.env 找):AIDC_SEMANTIC_TOKEN(Automate 运行时自带,只认环境变量)→ AIDC_API_KEY(显式给的开发者 Key 或只读 Agent Key,本机调试用)→ 平台给箱上系统用户发的只读 Key(/etc/aidc/semantic/<用户>.key,与 aidc-semantic 命令同一个文件;组织也从这里来)。智能体不用配,也不该自己去找 Key:能读什么由它的服务用户在组织里的授予决定(下一节)。发布看板另用受限 Key AIDC_AGENT_KEY。组织 AIDC_SEMANTIC_ONTOLOGY。
  • 智能体的 Key 在 Semantic 上代表这个智能体的服务用户:不能登录、默认没有任何角色,组织管理员把它加进一个组、给组授予 Ontology(或某些 Object Type)上的 Viewer 后才读得到;组成员可以带到期时间(临时开通)。人持有的 Key(账号认领的、桌面兑换的)按这个人自己的权限判。没有角色时接口回 403,信息里写着是哪个服务用户(svc.<组织>.<智能体>)。
  • 只读 Key 的 scope:api:use-ontologies-read 管读对象的全部接口(查 / 聚合 / 计数、对象集、链接、媒体与附件、元数据),只读列出的类型(* = 全部公司级类型);Ontology SQL 另要 api:use-sql-queries-execute,且只给 * 的 Key。
  • Key 只发给 https://www.ai-dc.ai(调试可用 localhost),不跟随重定向。
  • 源查询的目录路径 AIDC_SEMANTIC_CATALOG 同样先读环境变量,再读 $HERMES_HOME/.env。未配置时使用共享目录 /opt/aidc-semantic/state/erp-catalog.json,SDK 副本不会到自己的安装目录另找一份;其他目录请显式配置。配置路径改变后重新加载目录,指定文件读取失败时报错,不退回旧缓存。
  • 多个 $groupBy 字段时,总组数受第一个字段的上限约束——要的组多,每个字段的上限都写够。
  • fresh=True(fetch_page / aggregate):由 ERP 同步来的类型过期时先等同步完(最多 20 秒)。

本体由智能体构建

智能体不能直接改 main 上的本体。它在分支上改,开提案,再按组织的审批策略审核、合并:

  1. aidc semantic branch create add-department:开分支(基线 = 当前语义版本)。
  2. aidc semantic branch modify add-department ontology/:把定义放到分支上(一整份清单,--dry-run 试跑,--expected-version 防止并发覆盖)。
  3. aidc semantic objects agent --branch add-department:在分支上预览(读接口都收 ?branch=);branch validate 看 merge checks,branch conflicts 看和 main 冲突的地方,branch rebase 跟上 main。
  4. aidc semantic branch propose add-department --title … --trigger "为什么要改":开提案。平台自动附上按资源的改动、校验结果、影响面(30 天的写入与活跃用户、依赖的应用)、破坏性改动。
  5. 逐项批准(破坏性改动要输入资源名确认),全部批准、merge checks 通过后合并:落到 main,发一个语义版本。审批策略是 review 时,人在 /developer/<公司>/ontology/proposals/<id> 上做;是 yolo 时,合格的作者开提案就自动批准、合并,别的提案也可以用 aidc semantic proposal approve <id> / proposal merge <id> 做。

作者由凭证决定:Agent Key 一律是智能体;开发者 Key 在环境变量 AIDC_AGENT_ID 存在时,CLI 自动带 x-aidc-author: agent:<id>,作者也记为智能体。智能体作者直接定义 main 会得到 409 branch_required;智能体作者也不能直接写数据(新建、修改、删除、导入会得到 403),改数据走 Action。

审批策略:review 与 yolo

每个组织有一个审批策略,管提案的批准、合并与应用的发布。aidc semantic approval-policy 查看,aidc semantic approval-policy set review|yolo [--dry-run] 修改(只给本组织开发者本人:网页登录,或没有声明智能体身份的开发者 Key;智能体不能改)。

review(缺省) yolo
谁能批准、合并 本组织开发者的网页登录 网页登录,加上能改这个本体的 Key:开发者 Key(含智能体在用的),或代表的主体在 Ontology 上是 Editor / Owner 的 Agent Key
作者自己的批准 不算数 作者能改这个本体就算数(Contributor approval)
检查通过后 等人点「合并」 自动合并
发布智能体写的应用版本 人在网页上点 开发者 Key 也能发布

两种策略下都不变:安全策略的改动要满足相关 Marking 的人批准(作者满足不了,这一项留给别的审核人);merge checks 不过合不了;任何一项被驳回都合不了。每一次批准、驳回、合并、发布、改策略都记进审计日志(谁、经网页还是 Key、结果)。只读(Viewer)的智能体照样能开提案,批准要交给能改这个本体的审核人。改回 review 时,智能体给的批准作废、回到待审核。

和 ERP、OA 的关系

ERP、MES、OA 缺省只读:发布端把数据推进数据流,按 Object Type 定义里的 datasources 同步进来。人和智能体的改动只走 Action,落在语义层(对象的 edits),数据源下一次同步不会冲掉它们。要真的改源系统(关一台服务器、回写一张单据),给 Action 配 writeback webhook(见上一节):源系统先接受,语义层才记一笔。

Semantic 平台(www.ai-dc.ai/semantic)

登录 ai-dc.ai/semantic/app 就进到自己组织的 Semantic;不属于任何组织的账号落到 Public。界面分成下面这些应用,只调这一页写的同一套 API:

页面 地址 做什么
概览 /semantic/<cell> Object Type 一览(对象数、属性、链接、Public 标记)、最近的变化、待审核的提案、数据库状态
Ontology 图 /semantic/<cell>/graph 画布:Object Type 是节点、Link Type 是边(多对多虚线);拖动、缩放、点开看属性与关系
Object Types /semantic/<cell>/object-types[/<apiName>] Ontology Manager:属性(base type、SQL 列、主键 / 标题 / Value Type / 派生 / 只在语义层)、链接、用到它的 Action、数据源、Share
Object Explorer /semantic/<cell>/objects/<apiName>[/<主键>] 表格:搜索、筛选、排序、按属性看分布;Object View:属性、每条链接上的对象、编辑历史、能执行的 Action
Actions /semantic/<cell>/actions[/<apiName>] 参数表单:先「只校验」(VALIDATE_ONLY)再提交;Action Log
SQL Console /semantic/<cell>/sql Ontology SQL(见下一节);开发者在「连接」里轮换口令拿只读直连串
Proposals /semantic/<cell>/proposals 智能体开的 Ontology proposal:逐项批准(可一次批准全部非破坏性的)、合并
Access /semantic/<cell>/access 开放程度(Private / Group / Public / Open to Internet)、分享给谁、角色,见 访问与账号
Public /semantic/public 所有登录的 AIDC 账号都看得见的 Ontology、Object Type、数字员工、文件,以及「分享给我」

网页会话调 /api/v1/ontologies/** 时,角色由统一的访问判定决定(Private / Group / Public):本组织开发者 = developer(与开发者 Key 同权);本组织成员(Ontology 对组织可见时)= member;别的组织的人按授予——Editor = editor、Viewer = viewer(只读);Ontology 与所有 Object Type 都没有角色 = 403。

Semantic 数据库(Ontology SQL)

每个组织一个 Postgres schema(ont_<组织>),第一次用时按需建好,定义变了下一次查询时自动重建。按 Ontology SQL 的规则:

  • 表:每个 Object Type 一个视图,表名 = API name、列名 = 属性 API name(列类型:string → text、integer / long → bigint、double → double precision、decimal → numeric、date、timestamp → timestamptz,其余 jsonb)。每个多对多 Link Type 一个视图,两端的列名 <objectTypeApiName>_<relationApiName>(值是走这条链接到达的对象的主键);每个 Interface 一个视图(实现它的类型 UNION ALL,另有 __objectType、__primaryKey)。一对多直接 join。派生属性是读时算的,不进 SQL。
  • 数据:视图直接读当前值(数据源 ⊕ 语义层改动),不复制;删除的、源头已消失的不出现。
  • 上限:只能一条 SELECT(可以 WITH / VALUES / TABLE 开头),最多 10,000 行、20 秒;位置参数 $1、$2…;dryRun = EXPLAIN。写入永远走 Action。
  • 两个只读角色:reader(本组织看得见的全部类型:本组织成员、开发者 Key、Agent Key、在 Ontology 上有 Viewer 以上授予的人)与 public(只有授予了 Everyone 的类型:只看得见 Public 的外部账号)。应用票据不走 SQL——在应用里用 semantic.ontology()。
  • 直连:本组织开发者可以轮换口令,拿到 reader 的连接串,用 psql、BI 工具、Notebook 只读直连(只读事务、20 秒超时、最多 10 个连接、只看得见本组织的视图)。口令由服务端派生、不落库,库里只有 SCRAM 校验值;再轮换一次旧口令立即失效。
const r = await semantic.sql(`
  SELECT o.name, count(a.*) AS agents
  FROM organization o LEFT JOIN agent a ON a."organizationId" = o."organizationId"
  GROUP BY 1 ORDER BY 2 DESC`);
const cost = await semantic.sql('SELECT month, sum("costUsd") FROM "modelUsage" WHERE "organizationId" = $1 GROUP BY 1', { parameters: ["cell-aidc"] });
const db = await semantic.database();                       // 表与列、我用哪个角色
const conn = await semantic.rotateDatabaseCredentials();    // 开发者:psql "<conn.uri>"
aidc semantic sql 'SELECT stage, count(*) FROM organization GROUP BY 1' [--csv]
aidc semantic database --rotate
方法 路径 说明
POST /api/v1/sqlQueries/executeOntology 执行(照官方 ExecuteOntologySqlQueryRequest:query、parameters、rowLimit、dryRun、ontologyIdentifier);响应是 JSON(官方是 Arrow)
GET /api/v1/ontologies/{ns}/database 数据库信息;开发者另有直连信息(不含口令)
POST /api/v1/ontologies/{ns}/database/sync 按当前定义重建视图(开发者)
POST /api/v1/ontologies/{ns}/database/credentials 轮换直连口令,新连接串只返回这一次(开发者)

旧写法(1.2.x:describe / objects / action / define / publish)

1.2.x 起的写法照样能用(和上面同一份数据、同一套 Action 引擎),新代码请用上面的 semantic.ontology()。

三个概念

概念 是什么 例子(生产进度看板)
对象类型 一类业务对象:主键 + 属性。属性要么来自数据源(同步进来,只读),要么只在语义层维护(writeback:备注、负责人、异常状态…) production.order_line(工单线体进度):工单、线体、计划、累计合格 ← SAP;异常状态、异常说明、登记人 ← 语义层
链接 对象之间的关系。最常见的是一个属性引用另一个类型的主键(references) 工单线体 → 线体(lineCode)
Action 受控的写操作:参数(类型 / 必填 / 长度 / 枚举)+ 改哪些属性 + 谁能做 + 日志里的一句话 production.flag_issue 登记异常:参数「异常说明」「级别」;写 issue、status、owner = 执行人

改数据只有两条路:成员用 Action(校验、权限、留痕);开发者用旧数据层直接改(管理用)。两条路的改动都落在语义层(对象的 edits),数据源下一次同步只更新它自己那一层,不会冲掉人改过的值。

读:说明书与对象

const space = await semantic.describe();
// space.types:看得见的对象类型(属性、单位、同义词、链接、对象数)
// space.actions:Action 与「我能不能执行」(allowed)
// space.markdown:给大模型读的整份说明书——智能体先读它再干活
// space.release:当前语义版本(v3…)

const hit = semantic.search(space, "合格数");        // 按业务说法定位:[{ kind: "property", type: "production.order_line", name: "ok" }]

const issues = await semantic.objects("production.order_line")
  .where({ status: { in: ["关注", "异常"] }, day: "2026-09-26" })
  .sort("-gap")
  .list();                                           // { objects, total, seq }

const order = await semantic.objects("production.order_line").get("100000012345|L01-05");
const line = await semantic.objects("production.order_line").linked(order.pk, "production.order_line.lineCode");
const byLine = await semantic.objects("production.order_line").aggregate({ groupBy: ["lineCode"], metrics: { ok: ["ok", "sum"] } });

每个对象:props(当前值 = 数据源的值被语义层改动覆盖后)、rev(每改一次 +1)、edited(语义层改过的属性)、overridden(被改动盖住、数据源现在是另一个值的属性 → 数据源的值)、sourceGone(数据源里已经没有这一行)。

条件写法:{ 属性: 值 } 相等;{ 属性: { gt, gte, lt, lte, ne, in, nin, contains, startsWith, null } };多个属性之间是「且」;$or: [{…}, {…}] 任意一组成立。

实时

const view = semantic.objects("production.order_line").where({ day: today }).sort("-ok").live({
  onUpdate(objects, change) { render(objects); },   // 先全量,之后数据一变就回调(同步、Action、别人的修改都算)
  onStatus({ connection }) { badge(connection); },
});
// view.close()

底层是旧数据层的 watch(SSE,断线按序号续传,不丢不重)。

写:执行 Action

const r = await semantic.action("production.flag_issue").apply(
  { issue: "缺料:顶蓬面料未到", severity: "异常" },
  { object: "100000012345|L01-05", ifRev: order.rev },
);
// r.object:改后的对象;r.event.summary:「L01-05 登记异常:缺料…」(进操作记录)
  • 参数按定义校验(不合法 422,信息里写明哪一项);semantic.checkParams(actionInfo, params) 可以在表单提交前本地预检。
  • 谁能执行:应用清单 semantic.actions 登记了它,且访客角色在 Action 的 roles 里(缺省 developer / member / editor)。只读访客(公开链接、只读分享)永远不能写;一律登录起没有匿名访客。
  • ifRev:对象当前 rev 不等于它就 409 rev_mismatch(别人刚改过,刷新再改)。
  • dryRun: true:只校验、返回计划,不落库。

定义与发布(开发者:CLI / 智能体)

定义就是 JSON。四种词条:enum、object、link、action。

{
  "kind": "object",
  "apiName": "production.order_line",
  "title": "工单线体进度",
  "description": "每个工单在每条线体上的当日进度(SAP 生产进度报表)",
  "schema": {
    "titleColumn": "lineCode",
    "synonyms": ["工单行", "生产任务"],
    "columns": [
      { "name": "orderLineKey", "type": "text", "primaryKey": true, "title": "工单|线体" },
      { "name": "orderNo", "type": "text", "title": "工单" },
      { "name": "lineCode", "type": "text", "title": "线体", "references": { "entity": "production.line", "column": "lineCode" } },
      { "name": "ok", "type": "integer", "title": "累计合格", "unit": "件", "synonyms": ["合格数", "良品数"] },
      { "name": "status", "type": "text", "enumRef": "production.issue_status", "writeback": true, "title": "异常状态" },
      { "name": "issue", "type": "text", "writeback": true, "title": "异常说明" }
    ]
  }
}
{
  "kind": "action",
  "apiName": "production.flag_issue",
  "title": "登记异常",
  "schema": {
    "objectType": "production.order_line",
    "operation": "modify",
    "parameters": [
      { "name": "issue", "type": "text", "title": "异常说明", "required": true, "maxLength": 200 },
      { "name": "severity", "type": "text", "title": "级别", "enumRef": "production.issue_status" }
    ],
    "edits": { "issue": "$issue", "status": "$severity", "owner": "$userName", "flaggedAt": "$now" },
    "roles": ["developer", "member", "editor"],
    "summary": "{lineCode} 登记异常:{issue}"
  }
}

名字:一个 Object Type 恰好一个主键属性;Object Type 名用 PascalCase(小写开头的旧名照收、给警告);属性与 Action 参数的 API name 是 camelCase(小写字母开头、只含字母和数字)。早先定义的 snake_case 属性 / 参数与复合主键原样保留(定义时给警告),新加的一律按这条规则,不合规的整批拒收。

取值表达式:$参数名、$now(当前时间)、$user(执行人账号)、$userName(执行人名字)、$uuid(新主键,create 用);其他是字面量(以 $ 开头的字面量写成 $$…)。operation:modify 改一个对象、create 新建(edits 要给出主键)、delete 删除(语义层墓碑)。

aidc semantic define ontology/            # 目录里的 *.json 整批提交:一起校验、按 枚举 → 对象 → 链接 → Action 落(有则改)
aidc semantic define ontology/ --dry-run  # 只检查:整批引用是否闭合(批内互相引用算数)、相对上一个语义版本有哪些破坏性变更
aidc semantic publish --notes "加了异常登记"   # 发一个语义版本 vN(只增;定义没变不占号)
aidc semantic describe --markdown         # 给智能体读的说明书
aidc semantic act production.flag_issue --object "100000012345|L01-05" --param issue=缺料 --param severity=异常
  • 引用闭合:Action 改的属性、引用的参数、外键目标、枚举都必须存在,否则定义直接 422。一个目录是一批(semantic.defineAll(定义数组) / POST …/semantic/{命名空间}/types):在「整批改完之后」的全体定义上校验,批内互相引用算数,不闭合一条都不写。
  • 破坏性变更(删类型 / 删属性 / 改类型 / 改主键 / Action 删参数或新增必填参数…)会在定义时返回、在发布时记档(changeKind: breaking)。发布前先确认调用它的应用都改好了。
  • 语义版本就是这家公司 Ontology 的版本号,与应用版本号一起出现在应用日志里;自进化 SDK 采纳的语义改进会自动发新版本。

权限一览

谁 读 执行 Action 直接写(旧数据层) 定义 / 发布
开发者 Key(CLI / 智能体) 本公司全部 全部 全部 ✓
应用里的 developer 访客 清单 semantic.types 登记的(含部门级) 清单登记 + roles 允许 清单 semantic.write 登记的 —
应用里的 member / editor 清单登记、且对公司全员可见的 清单登记 + roles 允许 — —
viewer(只读分享 / 公开链接) 同上 — — —

应用清单里这样登记:

{
  "sdk": ["semantic", "ui"],
  "semantic": {
    "types": ["production.order_line", "production.line"],
    "actions": ["production.flag_issue", "production.resolve_issue"],
    "write": []
  }
}

"*" 表示看得见的全部(数据浏览器这类通用应用)。

上表之外,数据安全(Markings、对象 / 属性安全策略)对所有人生效,包括开发者 Key:挂了 Marking 的数据,不是成员就读不到。

API

方法 路径 说明
GET /api/v1/developer/semantic/{命名空间} 说明书(按凭证裁剪)
GET / POST /api/v1/developer/semantic/{命名空间}/types 全部定义(开发者)/ 一次定义一批({definitions: […]},整批校验)
GET / PUT / DELETE /api/v1/developer/semantic/{命名空间}/types/{apiName} 读 / 定义 / 归档
POST /api/v1/developer/semantic/{命名空间}/actions/{apiName} 执行 Action
GET / POST /api/v1/developer/semantic/{命名空间}/releases 语义版本列表 / 发布

旧的数据层(/api/v1/developer/data/…:查询、聚合、订阅、直接写)照样能用;新代码用下面的 Ontology API 与对象集订阅。命名空间 = 公司 cellId(cell-…);应用里自动取应用所在公司。

Ontology API 是 Ontology REST API v2 的形状,前缀是 /api/v1/ontologies/{命名空间},响应体放在信封的 data 里、字段照官方:

方法 路径 官方操作
GET /ontologies、/ontologies/{ns}、/{ns}/fullMetadata List / Get Ontology、Full Metadata
GET /{ns}/objectTypes[/{type}[/fullMetadata | /outgoingLinkTypes[/{link}]]] Object Type、Outgoing Link Types
GET /{ns}/actionTypes、/interfaceTypes、/sharedPropertyTypes、/valueTypes、/queryTypes(各带 /{apiName}) 各类型的 List / Get
GET /{ns}/objects/{type}、/{type}/{pk}、/{type}/{pk}/links/{link}[/{pk2}] List Objects、Get Object、Linked Objects
POST /{ns}/objects/{type}/search、/aggregate、/count Search、Aggregate、Count
GET / POST /{ns}/objects/{type}/{pk}/timeseries/{property}/firstPoint、lastPoint、streamPoints Time Series
POST /{ns}/objectSets/loadObjects、/aggregate、/createTemporary;GET /{ns}/objectSets[/{rid}] Object Set
POST /{ns}/objectTypes/{type}/editsHistory Edits History
POST /{ns}/actions/{action}/apply、/applyBatch(最多 20 个,一个事务) Apply Action
GET / POST /{ns}/functions(?dryRun=true 只校验) AIDC:已发布的函数(最新版本与全部版本)/ 发布一个版本(开发者;智能体作者只能发预发布版本)
POST /api/v1/ontologySubscriptions/ontologies/{ns}/streamSubscriptions(SSE) Object set subscription(SDK 用)
GET /api/v2/ontologySubscriptions/ontologies/{ns}/streamSubscriptions(WebSocket) Object set subscription(官方 OSDK 直连)
POST /{ns}/datasources/platform/sync 同步 AIDC 平台数据(平台对象类型;开发者)
GET / POST /{ns}/branches[/{name}[/modify | validate | conflicts | discard | rebase | lock | fullMetadata | proposals]] Global Branching
GET / POST /{ns}/proposals[/{id}[/tasks/{apiName}/review | merge | close]] Ontology proposal(review、merge:审批策略 review 只收网页登录,yolo 也收能改这个本体的 Key)
GET / PUT /{ns}/approval-policy 组织的审批策略(PUT 只给本组织开发者本人,x-aidc-dry-run: true 只看会变什么)
POST /{ns}/objectTypes/{type}/security/test AIDC:Test security policies(Ontology Manager 的同名功能,官方没有公开 API)

Markings 的管理用 AdminV2 / FilesystemV2 的接口:/api/v1/admin/markingCategories[/{id}]、/api/v1/admin/markings[/{id}[/markingMembers[/add \| /remove] \| /roleAssignments[/add \| /remove]]]、/api/v1/admin/markings/getBatch、/api/v1/admin/users/{userId}/getMarkings、/api/v1/filesystem/resources/{rid}/markings \| addMarkings \| removeMarkings。

完整字段见 OpenAPI。

本页由 developer/docs/semantic.md 生成 · Markdown 原文 · llms.txt