工作流 SDK

把已经发布到 Nexus 的应用的能力组合成一个完整的流程:营业部的询价、设计中心的材料清单、采购部的行情、制造部的产能、财务部的核价口径……各自是独立的应用,工作流把它们串起来,算、分析,最后写回结果。可以手动运行、预演,也可以在语义层数据一变时自动运行。每一步用了谁的能力、输入从哪来、产出了什么,画布上看得清清楚楚。

import { workflow } from "/developer/sdk/v1/aidc.js";

三个概念:

概念 是什么 写在哪
能力(capability) 一个已发布应用对外提供的一件事:带参数的语义层查询 / 单条读取 / 聚合 / Action 提供方应用的清单 exports(或自动提取)
工作流(workflow) 把能力、计算、AI 分析连成的有向无环图,外加触发方式与结果 工作流应用的清单 workflow
运行(run) 工作流被执行一次:每一步的状态、耗时、输出、token 平台记录,workflow.runs() / 画布

1. 能力:已发布应用对外提供什么

显式导出(推荐)

在提供方应用的 aidc.app.json 里声明 exports:名字、参数、它做什么。条件里的值可以是字面量,也可以是 = 开头的表达式(只能用 input)。

"exports": [
  {
    "name": "bom_of",
    "kind": "query",
    "title": "零件的初始材料清单",
    "input": { "product": { "type": "text", "title": "零件", "required": true } },
    "type": "demo.bom_line",
    "where": { "product": "=input.product" },
    "select": ["material", "usage_kg", "scrap_rate", "process"]
  },
  {
    "name": "logistics_rate",
    "kind": "get",
    "title": "物流包装费率",
    "input": { "destination": { "type": "text", "required": true } },
    "type": "demo.logistics_rate",
    "pk": "=input.destination"
  }
]
kind 做什么 关键字段 输出
query 查一组对象 type where select sort limit { rows, count, total }(每行带 _pk)
get 按主键取一个对象 type pk { row }(没有为 null)
aggregate 分组汇总 type where groupBy metrics { rows, count }
action 执行一个 Action(写语义层) action object params { object, rev, event };预演时 { preview: true, plan }

导出的类型 / Action 必须登记在本应用的 semantic.types / semantic.actions 里——能力不能超出应用自己的权限。

自动提取

已经发布的应用不用改一行就有能力:它登记的每个语义类型自动成为查询能力 <slug>/<类型 apiName>(参数 where sort limit),每个 Action 自动成为 <slug>/<Action apiName>(参数 = Action 的参数 + object)。

const caps = await workflow.capabilities();          // 公司的能力目录
// [{ ref: "quote-design/bom_of", kind: "query", auto: false, input: {...}, app: { slug, title, version, department } }, …]
aidc workflow capabilities                 # ● 显式导出  ○ 自动提取
aidc workflow capabilities --app quote-sales

谁的身份在执行

能力以「提供方应用 × 成员角色」执行:只读得到提供方登记过、且对全公司可见的类型,Action 过它自己的角色规则。所以工作流拿不到提供方自己拿不到的东西,成员触发的工作流也不会变成开发者权限。只有发布到正式通道的版本的能力对外可见。

2. 工作流:在清单里写 workflow

一个工作流就是一个应用:清单 sdk 登记 workflow,workflow 里写步骤。下面是报价演示的缩写(完整版见样板应用):

{
  "slug": "quote-workflow",
  "sdk": ["workflow", "data", "semantic", "auth", "log"],
  "models": ["deepseek-flash"],
  "owner": { "department": "营业部", "team": "营业小兴-报价" },
  "workflow": {
    "input": { "rfq_no": { "type": "text", "title": "询价单号", "required": true } },
    "trigger": {
      "manual": { "roles": ["developer", "member"], "preview": "public" },
      "change": { "type": "demo.rfq", "when": "=object.status == '待报价'", "input": { "rfq_no": "=object.rfq_no" } }
    },
    "lanes": ["营业部", "设计中心", "采购部", "制造部", "财务部"],
    "steps": [
      { "id": "rfq", "kind": "use", "title": "询价单", "use": "quote-sales/rfq", "with": { "rfq_no": "=input.rfq_no" } },
      { "id": "bom", "kind": "use", "title": "初始材料清单", "use": "quote-design/bom_of", "with": { "product": "=steps.rfq.row.product" } },
      { "id": "prices", "kind": "use", "title": "原材料行情", "use": "quote-procurement/commodity_prices", "with": { "materials": "=pluck(steps.bom.rows, 'material')" } },
      { "id": "material", "kind": "compute", "title": "材料成本", "lane": "采购部",
        "from": "=steps.bom.rows", "join": [{ "rows": "=steps.prices.rows", "on": "material", "as": "p" }],
        "fields": { "cost": "=round(usage_kg * (1 + scrap_rate) * p.price, 3)" },
        "summary": { "total": "=round(sum(cost), 2)" } },
      { "id": "review", "kind": "model", "title": "AI 报价分析", "model": "deepseek-flash",
        "prompt": "询价:{{ steps.rfq.row }}\n材料成本:{{ steps.material.rows }}", "output": { "summary": "text", "risks": "text[]" } },
      { "id": "draft", "kind": "use", "title": "报价草稿", "use": "quote-sales/demo.propose_quote",
        "with": { "rfq_no": "=input.rfq_no", "product": "=steps.rfq.row.product", "currency": "=steps.rfq.row.currency",
                  "unit_price": "=steps.material.summary.total", "ai_summary": "=steps.review.summary" } }
    ],
    "output": { "quote_no": "=steps.draft.object._pk", "material_cost": "=steps.material.summary.total" },
    "outputLabels": [{ "key": "material_cost", "title": "材料成本" }, { "key": "quote_no", "title": "报价单号" }]
  }
}

步骤

kind 做什么 字段
use 调一个能力 use: "<应用 slug>/<能力名>"、with(参数)
compute 计算:不写 from 求一组值;写了 from 逐行求字段,可 join 别的步骤的行(左关联),filter、sort,最后 summary 汇总 见下
model AI 分析:提示词里用 {{ 表达式 }} 插入前面的结果,按 output 声明的字段返回 model(要登记在清单 models)、system、prompt、output、maxTokens

每一步都可以写 lane(画布泳道,缺省 = 能力提供方登记的部门)、when(条件为假就跳过,下游读到 null)、after(额外的先后依赖)。

依赖是自动的:表达式里引用了 steps.<id> 就依赖它。平台按依赖分层,同一层并行执行;有环、引用不存在的步骤,部署时就拒收。

表达式

以 = 开头的字符串是表达式(像 Excel 公式);其他是字面量。

逐行计算里,行的属性直接用名字(usage_kg),关联上的行用 as 起的名字(p.price),整行叫 row;字段之间可以互相引用,求值顺序按引用关系排,与书写顺序无关。summary 里每个字段名代表整列(sum(cost)),rows 是全部行,count 是行数。

结果

output 把最后要看的值取出来({ 名字: 表达式 }),outputLabels 给出展示顺序和显示名(数组)。画布与 aidc workflow run 都按它展示。

3. 运行

// 开跑:立即返回(执行在服务端继续),用 watch 看每一步
const { run } = await workflow.run({ rfq_no: "RFQ-2609-002" }, { mode: "preview" });
const stop = workflow.watch(run.id, {
  onRun: (r) => render(r.steps),          // 每有一步变化推一次整份运行
  onDone: (r) => console.log(r.output),   // succeeded / failed
});

await workflow.runs({ limit: 20 });        // 最近的运行(摘要)
await workflow.getRun(run.id);             // 每一步的输出
await workflow.wait(run.id);               // 等结束(CLI / 智能体)
方式 说明
正式运行 mode: "run" Action 真的写进语义层(留痕、广播给所有订阅端)
预演 mode: "preview" 读、算、AI 分析都真的跑,Action 只返回将要写入的计划
数据变化自动运行 trigger.change 语义层里这个类型的对象新建 / 修改后(when 为真)自动跑一次正式运行。发布到正式通道起开始生效;每条变化只触发一次;工作流自己写出的变化不回头触发自己;工作流写的数据可以再触发别的工作流(最多 3 层)

谁能跑:

调用方 正式运行 预演
开发者 Key(CLI / 智能体) ✓(可 channel: "test" 跑测试版) ✓
工作流应用里的访客:trigger.manual.roles 里的角色 ✓ ✓
其他本公司成员 — ✓
公开分享链接的访客 — trigger.manual.preview = "public" 时 ✓

4. 画布

官方样板 workflow-canvas 是通用界面:泳道 = 部门,按依赖分层(部门比层数少时竖排,从上往下流),连线上的字是传过去的参数;点任意一步看它用了谁的能力、输入是怎么来的、公式、输出与提供方的应用卡片;运行实时推送,结束后可以回放。任何带 workflow 的应用都可以直接用这份界面,aidc app init <slug> --template workflow 生成的是最小起步版。

5. 部署与校验

aidc app deploy <目录> --dry-run     # 先查:结构、表达式、环、能力在公司目录里、参数名与必填
aidc app deploy <目录> && aidc app publish <slug>
aidc workflow run quote-workflow --param rfq_no=RFQ-2609-002 --preview

部署时平台对照公司的能力目录检查:每个 use 的提供方已发布到正式通道、能力存在、with 里的参数都是能力声明过的、必填的都给了;trigger.change 的类型在语义层里。所以要先发布提供方应用,再部署工作流。

CLI

aidc workflow capabilities [--app slug]
aidc workflow list
aidc workflow get <slug> [--channel test]
aidc workflow run <slug> [--input '{…}'] [--param 名=值 …] [--preview] [--channel test] [--no-wait]
aidc workflow runs <slug> | status <slug> <运行 id> | watch <slug> <运行 id>

API

方法 路径 说明
GET /api/v1/developer/capabilities/{命名空间} 能力目录
GET /api/v1/developer/workflows/{命名空间} 工作流列表
GET /api/v1/developer/workflows/{命名空间}/{slug} 详情(编排计划、步骤、泳道、提供方卡片)
GET / POST /api/v1/developer/workflows/{命名空间}/{slug}/runs 运行列表 / 开跑
GET /api/v1/developer/workflows/{命名空间}/{slug}/runs/{id} 一次运行
GET /api/v1/developer/workflows/{命名空间}/{slug}/runs/{id}/events 实时进度(SSE)

上限

步骤 ≤ 40;能力参数 ≤ 24;逐行计算 ≤ 5000 行;表达式 ≤ 1000 字;一次运行在一次函数调用内跑完(≤ 5 分钟);数据变化触发链最多 3 层。

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