@tencentcloudadp/cli 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +118 -2
- package/bin/adp.js +4 -0
- package/config-schema.json +319 -0
- package/dist/cli.js +28513 -0
- package/dist/cli.js.map +1 -0
- package/package.json +70 -4
- package/skills/adp/SKILL.md +116 -0
- package/skills/adp/configuration/SKILL.md +51 -0
- package/skills/adp/create/SKILL.md +189 -0
- package/skills/adp/evals/evals.json +60 -0
- package/skills/adp/gotchas/SKILL.md +92 -0
- package/skills/adp/references/app-keys.md +41 -0
- package/skills/adp/references/app-modes.md +36 -0
- package/skills/adp/references/auth.md +45 -0
- package/skills/adp/references/canvas/branch.json +159 -0
- package/skills/adp/references/canvas/deep-research.json +267 -0
- package/skills/adp/references/canvas/dynamic-option.json +410 -0
- package/skills/adp/references/canvas/extract.json +109 -0
- package/skills/adp/references/canvas/intent.json +340 -0
- package/skills/adp/references/canvas/llm.json +161 -0
- package/skills/adp/references/canvas/main.json +155 -0
- package/skills/adp/references/canvas/option.json +97 -0
- package/skills/adp/references/canvas/single.json +155 -0
- package/skills/adp/references/canvas/sub.json +125 -0
- package/skills/adp/references/credentials.md +40 -0
- package/skills/adp/references/inventory.md +39 -0
- package/skills/adp/references/memory.md +54 -0
- package/skills/adp/references/operations.md +56 -0
- package/skills/adp/references/pitfalls.md +125 -0
- package/skills/adp/references/platform-skills.md +31 -0
- package/skills/adp/references/timers.md +42 -0
- package/skills/adp/references/tuning.md +79 -0
- package/skills/adp/references/volumes.md +18 -0
- package/skills/adp/references/workflows.md +241 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# Platform pitfalls
|
|
2
|
+
|
|
3
|
+
Symptom → cause → fix. Each one constrains an API this CLI already calls. Verify the
|
|
4
|
+
platform side with `adp docs search "<action>" --format json` when in doubt.
|
|
5
|
+
|
|
6
|
+
## Single-workflow `WorkflowId` must be written through the bind path
|
|
7
|
+
|
|
8
|
+
- **Symptom**: the workflow is deployed and enabled, but `adp app get` still shows an
|
|
9
|
+
empty entry workflow and `adp deploy` fails with `450934 Single workflow is empty`.
|
|
10
|
+
- **Cause**: writing the id into `adp.jsonc` `mode.single_workflow` sends
|
|
11
|
+
`ModifyApp` `Config.Mode.SingleWorkflowConfig`, but only when that path is in the
|
|
12
|
+
update mask. A mask that omits it silently drops the binding.
|
|
13
|
+
- **Fix**: `adp workflow deploy` binds via `Config.Mode.SingleWorkflowConfig` for
|
|
14
|
+
`app_mode=3`. To bind an existing id by hand, keep `mode.single_workflow` in
|
|
15
|
+
`adp.jsonc` and `adp deploy`; the mask is derived from the config, so the object
|
|
16
|
+
must be present.
|
|
17
|
+
|
|
18
|
+
## Enable before bind
|
|
19
|
+
|
|
20
|
+
- **Symptom**: binding fails with `450935 Specified workflow is invalid`, even though
|
|
21
|
+
the workflow looks publishable.
|
|
22
|
+
- **Cause**: a workflow that has just been saved is not yet enabled. Publish status
|
|
23
|
+
(`UNPUBLISHED` / `PUBLISHED`) is not the enable flag — `IsEnable` is, and it is a
|
|
24
|
+
separate field.
|
|
25
|
+
- **Fix**: `adp workflow enable --app-id <id> --workflow-id <wf>` before any bind.
|
|
26
|
+
`workflow deploy` does this in order (create → save → enable → bind) and waits
|
|
27
|
+
~2s before binding because the platform is eventually consistent here.
|
|
28
|
+
|
|
29
|
+
## `app_mode` cannot always change
|
|
30
|
+
|
|
31
|
+
- **Symptom**: a mode change is rejected with `450442 Application mode cannot be changed`.
|
|
32
|
+
- **Cause**: `1` / `2` / `3` can switch among themselves, but Claw (`4`) is isolated.
|
|
33
|
+
- **Fix**: treat Claw as create-time-only. If a mode change is rejected, create a new
|
|
34
|
+
app rather than forcing it. Mode table: [app-modes.md](app-modes.md).
|
|
35
|
+
|
|
36
|
+
## Claw release needs a Claw-scene model
|
|
37
|
+
|
|
38
|
+
- **Symptom**: `adp deploy` on an `app_mode=4` app fails with
|
|
39
|
+
`4600005 应用配置不完整,请检查后再发布`, although the agent has instructions and a model.
|
|
40
|
+
- **Cause**: Claw only accepts models listed under `DescribeModelList` `ModelScene=18`.
|
|
41
|
+
`adp models` without `--scene` lists every model, so a general model such as
|
|
42
|
+
`qwen3.8-flash` looks valid but is rejected at release.
|
|
43
|
+
- **Fix**: `adp models --scene 18 --space-id <id> --fields modelId --format json`, put one
|
|
44
|
+
into `agent.model.model_id`, then `adp deploy`. `adp init --app-mode 4 --create-remote`
|
|
45
|
+
without `--model-id` already picks the first one; `adp deploy` refuses the
|
|
46
|
+
`placeholder-model` value before calling the API.
|
|
47
|
+
|
|
48
|
+
## `ModifyChannel` only changes a few fields
|
|
49
|
+
|
|
50
|
+
- **Symptom**: `adp channel update --name …` (older CLI) returned ok, but the name did not
|
|
51
|
+
change and the description was wiped.
|
|
52
|
+
- **Cause**: the `ModifyChannel` update mask allows only `spec.description` and
|
|
53
|
+
`spec.wecom_robot.callback.wecom_robot_id` (B-end), or `spec.description` and
|
|
54
|
+
`spec.wecom_robot.websocket.bot_id` / `bot_secret` (C-end). Other paths are ignored.
|
|
55
|
+
ADP also stores a per-type default `ChannelName` (10016 → 「飞书机器人」).
|
|
56
|
+
- **Fix**: the CLI exits 2 for any other path. Recreate the channel to change the name
|
|
57
|
+
or other credentials.
|
|
58
|
+
|
|
59
|
+
## Most channel types check credentials with the provider
|
|
60
|
+
|
|
61
|
+
- **Symptom**: `adp channel create` with placeholder credentials fails with
|
|
62
|
+
`4506004 确认填写认证的回调url地址` (10002, 10009), `4506003 渠道相关参数错误` (LINE),
|
|
63
|
+
or a system / internal error (10004, Telegram, 10000).
|
|
64
|
+
- **Cause**: at create time ADP verifies the credentials or callback URL with WeCom,
|
|
65
|
+
LINE, Telegram, or WeChat. Only 10013 DingTalk, 10014 WeCom robot WebSocket and
|
|
66
|
+
10016 Lark are stored without a check. 10000 and 10015 authorize by QR code; their
|
|
67
|
+
fields are filled in by ADP after the scan.
|
|
68
|
+
- **Fix**: use real credentials. For WeCom callback types, configure the receive-message
|
|
69
|
+
URL, Token and EncodingAESKey in the WeCom admin console first. Read a block's fields
|
|
70
|
+
with `adp docs get 132545 --section <Name>ChannelConfig --format json`.
|
|
71
|
+
- A second channel of the same type is allowed: a second 10016 Lark channel on the same app
|
|
72
|
+
is created normally. `4506003-企微应用已经被绑定` means that credential is already bound to a
|
|
73
|
+
channel. ADP says 企微应用 for every type (a Lark `AppId` gets the same text); the CLI message
|
|
74
|
+
names the provider from the ChannelType instead (`these Lark robot credentials are already
|
|
75
|
+
bound …`) and reports `ChannelAlreadyBound` (conflict, exit 5).
|
|
76
|
+
- The binding is not released right away when the channel is deleted: recreating a channel with
|
|
77
|
+
the same Lark `AppId` right after `channel delete` has been measured to fail with the same
|
|
78
|
+
4506003. Reuse the existing channel (`adp channel list --app-id <app>`), wait before
|
|
79
|
+
recreating, or use another provider app; changing other fields will not help.
|
|
80
|
+
|
|
81
|
+
## Release completion is `status = 3`, nothing else
|
|
82
|
+
|
|
83
|
+
- **Symptom**: a release looks finished but the app still serves the old version.
|
|
84
|
+
- **Cause**: intermediate and terminal statuses are easy to confuse; substring matching
|
|
85
|
+
on a status description reads in-flight states as done.
|
|
86
|
+
- **Fix**: `adp versions --fields releaseId,status --format json`. Status is a numeric
|
|
87
|
+
enum: `1` pending, `2` publishing, **`3` published (the only completion signal)**,
|
|
88
|
+
`4` failed, `5` reviewing, `6` review passed, `7` review failed, `8` callback
|
|
89
|
+
running, `9` paused, `10`–`12` appeal states. Wait for `3`; treat `4` / `7` / `12`
|
|
90
|
+
as failure and inspect before retrying — `adp deploy` is `non_idempotent`.
|
|
91
|
+
|
|
92
|
+
## Reading shared-KB bindings
|
|
93
|
+
|
|
94
|
+
`DescribeApp` can return an empty `SharedKbList` while the binding exists. `adp app get`
|
|
95
|
+
then reads `draft.sharedKbIds` from the app's referenced shared KBs (LKE
|
|
96
|
+
`ListReferShareKnowledge`). `adp kb create --shared-sub-type` is sent as `SharedSubType`,
|
|
97
|
+
but ADP currently ignores it: `kb get` reports 0 whatever you pass.
|
|
98
|
+
|
|
99
|
+
## `shared_kb_ids` is full-overwrite
|
|
100
|
+
|
|
101
|
+
- **Symptom**: after a push that adds one shared KB, every previously bound shared KB
|
|
102
|
+
disappears.
|
|
103
|
+
- **Cause**: `ModifyApp` `SharedKbIdList` replaces the whole set. Any id missing from
|
|
104
|
+
the pushed list is unbound, and a non-numeric id is dropped silently.
|
|
105
|
+
- **Fix**: read the current set with `adp app get --app-id <id> --format json` and push
|
|
106
|
+
the full target list.
|
|
107
|
+
- **Tri-state in `adp.jsonc`**:
|
|
108
|
+
| Config | Effect |
|
|
109
|
+
| --- | --- |
|
|
110
|
+
| key absent | bindings untouched (the path is not in the update mask) |
|
|
111
|
+
| `"shared_kb_ids": ["<id>"]` | replace the whole set with that list |
|
|
112
|
+
| `"shared_kb_ids": []` | unbind everything (explicit empty array) |
|
|
113
|
+
- Ids must be plain numeric strings (for example `"2019409536501314752"`), no `kb_`
|
|
114
|
+
prefix. Confirm the result with `adp app get` after pushing.
|
|
115
|
+
|
|
116
|
+
## List `truncated` used to lie at 100 rows
|
|
117
|
+
|
|
118
|
+
- **Symptom** (historical): `--limit 200` returned 100 rows with `truncated: false`.
|
|
119
|
+
- **Cause**: Cloud `PageSize` max is 100. The CLI used to probe `items.length > limit` and dropped `TotalCount`.
|
|
120
|
+
- **Fix**: lists now auto-follow pages, return `total`, and set `truncated` from `items.length < total`. If truncated, re-run with `--limit` equal to `total`. Do not paginate with hand-signed Cloud API.
|
|
121
|
+
- With `--page`, one page is fetched and its size is capped at 100 (`pageSize` in the result shows the real size). `truncated` is true only when rows remain after this page; the last page and pages past the end report `false`, and `next_actions` points at `--page <n+1>`.
|
|
122
|
+
- 对话里的知识引用:只有直接命中问答对的回复带 `References`,内容都指向那条问答,所以几条引用一模一样是平台返回的;文档生成的回复不带 `References`(`result.references` 为空不代表没检索到文档)。Claw(app_mode 4)应用的知识库工具同样只返回问答引用,命中文档时没有引用(已两次实测确认),不要承诺能给出文档出处。`adp chat` 的引用在成功结果的 `result.references`(`index`、`name`、`type`,问答带 `qaId` / `kbId`,文档带 `docId`);CLI 会收集 SSE 里任意位置的 `Reference` / `References`,平台以后若在别的帧里带上文档引用也能拿到。`adp tail` 读的 `DescribeMsgRecordList` 没有引用字段,看不到引用。`conversation messages` 只能读当前 CAM 可见的会话(访客 1、评测 2、工作流调试 10);`adp chat` 建的是 API 会话(类型 5,要 AppKey),用 `conversation messages` / `get` / `delete` 都读不到也删不掉。要看文档出处,在知识库里用 `kb doc referrers` 反查。
|
|
123
|
+
- 应用长期记忆(`adp.jsonc` 的 `memory`)不保证下一轮一定召回:实测开了记忆、上一轮说过的信息,下一轮 `adp chat` 仍可能答不出。这是平台行为,CLI 没有召回开关;需要确定性时把关键信息放进同一轮消息,或用 `adp memory` 管理记忆库条目。
|
|
124
|
+
- `adp chat --app-id <id>` 直接对任意已发布应用对话(AppKey 的取法和项目默认应用相同,不打印),不需要 `adp.jsonc`;`--agent-id` 只在需要指定 Agent 时传。
|
|
125
|
+
- `adp var get` 默认 `--module-type -1`(任意模块),能找到 `var put` 写入的变量,不管平台把它存在哪个模块;`var update` / `var delete` 不传 `--module-type` 时先读出变量所在模块再写。内置变量(`VisitorBizId` 等,列表里 `moduleType` 为 0)`var get` 读不到(450010,CLI 报 `VarNotFound`),只能在 `var list` 里看。
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# 平台 Skill:发布、引用与共享
|
|
2
|
+
|
|
3
|
+
`adp skill` 管的是平台技能目录里的 Skill,不是本配套 skill。
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
adp skill release --skill-id <id> --space-id <id> --format json # 新建/更新后要发布,应用才能用;可重复执行
|
|
7
|
+
adp skill refs --skill-id <id> --space-id <id> --format json # 谁在用:应用、智能体、用户
|
|
8
|
+
adp skill categories --format json # 分类 key
|
|
9
|
+
adp skill share submit --skill-id <id> --space-id <id> --remark <说明> --yes # 共享到企业技能中心
|
|
10
|
+
adp skill share withdraw --skill-id <id> --space-id <id> --yes # 撤回共享
|
|
11
|
+
adp skill share approval --approval-id <id> --format json
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
- Skill zip 根目录必须有 `SKILL.md`,且带 YAML front matter,至少包含 `name` 和 `description`,否则 `skill create` 报 450020:
|
|
15
|
+
|
|
16
|
+
```markdown
|
|
17
|
+
---
|
|
18
|
+
name: my-skill
|
|
19
|
+
description: 一句话说明这个 Skill 做什么、什么时候用
|
|
20
|
+
---
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
- 创建或更新后平台会做约 2 分钟的安全扫描。扫描期间 `skill release` 报 450028、`skill delete` 报 450063,CLI 都报 `SkillScanning`(`retryable: true`),next_action 就是原命令:等 30 秒左右再执行,最多等几分钟,不要改包重传。扫描中的 Skill 不出现在 `skill list` 里,列表里找不到不代表没建成。
|
|
24
|
+
- `skill list` / `plugin list` 必须有空间:没传 `--space-id` 又不在 `adp.jsonc` 项目里时报 `UsageError`(exit 2),next_action 是 `adp space list`。
|
|
25
|
+
- 不传 `--version-id` 时用当前版本。
|
|
26
|
+
- Skill 标识(`--name`)重名报 450021(CLI 报 `SkillNameTaken`,消息里写的是你创建时用的空间;平台原文不说明范围,内部记录为全企业唯一,跨空间是否可重名未实测)。换一个名字,不要去删别人的同名 Skill。`skill list --query <词>` 按名称/展示名称模糊查找,先查再起名。
|
|
27
|
+
- `skill release` 撞上安全扫描(450028)时 CLI 报 `SkillScanning`(`retryable: true`):等一两分钟再执行同一条命令。
|
|
28
|
+
- `skill get` 查不到时报 `SkillNotFound`(平台码 450002,文案「技能不存在」)。450002 在别的接口表示无权限,CLI 只按「技能不存在」文案映射。刚创建的 Skill 在安全分析(`AnalysisStatus` 1)结束前不出现在 `skill list` 里,可能要好几分钟,所以重试 create 撞 450021 时多半是自己刚建的:用第一次 create 返回的 `skillId`,不要换名再建。
|
|
29
|
+
- 共享和撤回对其他空间可见,先问用户;返回 `pending_approval` 表示等审批,不要替用户催审。
|
|
30
|
+
- 撤回时其他空间还在用会报 `SkillShareInUse`,把引用方列给用户,用户明确同意才加 `--force`。
|
|
31
|
+
- 删除或大改前先跑 `skill refs`,告诉用户会影响哪些应用。
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# 工作台定时任务(`adp timer`)
|
|
2
|
+
|
|
3
|
+
智能工作台里的定时任务:按调度把 prompt 发给模型执行。任务属于空间,并且只对创建者可见。它和应用上的触发器(`adp trigger`)不是一回事:用户说「给应用加定时触发」时用 trigger,说「工作台定时任务」时用 timer。
|
|
4
|
+
|
|
5
|
+
## 创建
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
adp timer create --space-id <sp> --name 日报 --prompt "总结今天的行业新闻" --daily 09:30 --format json
|
|
9
|
+
adp timer create --space-id <sp> --name 周报 --prompt-file prompt.md --weekly 1@09:00 --weekly 5@17:00
|
|
10
|
+
adp timer create --space-id <sp> --name 巡检 --prompt "检查…" --every 2h --start-at 2026-12-01T08:00:00+08:00
|
|
11
|
+
adp timer create --space-id <sp> --name 一次性 --prompt "…" --once 2026-12-01T09:00:00+08:00
|
|
12
|
+
adp timer create --space-id <sp> --name 工作日 --prompt "…" --cron "0 9 * * 1-5"
|
|
13
|
+
adp timer create --space-id <sp> --name 试跑 --prompt "…" --manual
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
- 调度只能选一种。`--weekly` 的格式是 `<1-7>@HH:MM`,1 是周一,可以重复传,最多 7 条。
|
|
17
|
+
- `--every` 只接受 `h`(小时)和 `d`(天),并且必须带 `--start-at`。
|
|
18
|
+
- 时间写成带时区偏移的 RFC 3339 格式。`--timezone` 默认是 `Asia/Shanghai`。
|
|
19
|
+
- `--model` 不传时用平台默认模型,可以先用 `adp models --space-id <sp>` 查可选模型。
|
|
20
|
+
- 返回结果里的 `policy` 是平台生成的中文描述,比如「每周一、五 09:30」。
|
|
21
|
+
|
|
22
|
+
## 管理与运行
|
|
23
|
+
|
|
24
|
+
以下命令都需要 `--space-id`(不传时读 `adp.jsonc`;没有项目文件时必须显式传)。
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
adp timer list --space-id <sp>
|
|
28
|
+
adp timer get --space-id <sp> --timer-id <id> --format json
|
|
29
|
+
adp timer update --space-id <sp> --timer-id <id> --cron "0 9 * * 1-5" # 只改传入的字段;--timezone 必须和一个调度参数一起传
|
|
30
|
+
adp timer pause|resume --space-id <sp> --timer-id <id> # 暂停只停调度
|
|
31
|
+
adp timer run --space-id <sp> --timer-id <id> --wait --format json # 立即执行一次
|
|
32
|
+
adp timer runs --space-id <sp> --timer-id <id> [--unread]
|
|
33
|
+
adp timer mark-read --space-id <sp> --timer-id <id> [--run-id <id> ...]
|
|
34
|
+
adp timer delete --space-id <sp> --timer-id <id> --yes
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
- 应用触发器的运行记录:`adp tail --app-id <id> --trigger-id <id>`(必须带 `--app-id`),单次详情 `adp trigger instance get --instance-id <id>`,返回的 `conversationId` 可以接着用 `adp conversation messages --type 1` 查看。
|
|
38
|
+
- 运行日志里 `statusLabel` 的取值有 `pending`、`running`、`succeeded`(`status` 4,`resultCode` 为 `SUCCESS`)、`failed`(5);没见过的状态码显示成 `status_<n>`,不要自行解读。`triggerLabel` 是 `scheduled` 或 `manual`。
|
|
39
|
+
- `resultSummary` 只保留模型的最终回答,前面的思考过程(`</think>` 之前的内容)已去掉。
|
|
40
|
+
- 运行失败时,`resultSummary` 里有模型或工具的错误信息,`sessionId` 可以在工作台打开对应会话。
|
|
41
|
+
- 报 `TimerTaskNotFound`,说明这个任务不存在、已被删除,或者不是你创建的。
|
|
42
|
+
- 结果推送渠道(企微等)目前只能在控制台配置。
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# 调优准则与用户反馈
|
|
2
|
+
|
|
3
|
+
## 调优准则(`adp guideline`)
|
|
4
|
+
|
|
5
|
+
准则写的是「在什么场景下应该怎么答」,应用回答时会遵循。所有命令都需要 `--app-id`,不传时读取 `adp.jsonc` 里的应用。
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
adp guideline create --content "报价时注明数据日期" --apply-scene "行情报价类问题" --format json
|
|
9
|
+
adp guideline list --status candidate --format json # 待采纳的生成结果
|
|
10
|
+
adp guideline enable --guideline-id <id> --guideline-id <id>
|
|
11
|
+
adp guideline disable|delete --guideline-id <id> ...
|
|
12
|
+
adp guideline changes --format json # 下次发布会带上的准则改动
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
- 手动创建的准则直接是 `enabled`。从评测生成的准则先是 `candidate`,执行 `enable` 就等于采纳。准则不能改回 `candidate`。
|
|
16
|
+
- 准则改动要 `adp deploy` 之后才对终端用户生效。发布前可以用 `changes` 核对一遍。
|
|
17
|
+
- `enable` / `disable` 会返回 `succeeded` 和 `failed`。只要有一部分成功,命令就不算失败,记得检查 `failed` 列表。
|
|
18
|
+
- `delete` 是全有或全无:先逐个查 ID,任何一个不存在就报 `GuidelineNotFound`(退出码 3),一条都不删。
|
|
19
|
+
|
|
20
|
+
### 从评测生成准则
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
adp guideline task create --evaluation-id <id> --model Hunyuan/hy3 --name 九月标注提炼
|
|
24
|
+
adp guideline task get --task-id <id> --format json # 查看生成数量和准则 ID
|
|
25
|
+
adp guideline list --task-id <id> --status candidate
|
|
26
|
+
adp guideline task create --from-task-id <id> # 复用原任务的配置再生成一次
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
生成任务需要一个已经完成人工标注的评测,评测本身目前在控制台创建。
|
|
30
|
+
|
|
31
|
+
### 调试反馈自动提炼
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
adp guideline auto-distill set --enable --model Hunyuan/hy3
|
|
35
|
+
adp guideline auto-distill get --format json
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
开启后,平台会把调试面板里的反馈提炼成候选准则。第一次开启时必须指定 `--model`。
|
|
39
|
+
|
|
40
|
+
## 终端用户反馈(`adp feedback`)
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
adp feedback list --reason 回答错误 --format json
|
|
44
|
+
adp feedback get --feedback-id <id>
|
|
45
|
+
adp feedback create --record-id <回复记录ID> --session-id <会话ID> --question "…" --answer "…" --reason 回答错误 --accept-terms
|
|
46
|
+
adp feedback delete --feedback-id <id> --yes
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
- 平台按应用模式分开存储反馈,CLI 会自动读取应用的模式。
|
|
50
|
+
- `--record-id` 要填被反馈的那条回复的记录 ID,不是提问的记录 ID。
|
|
51
|
+
- 提交反馈等于同意平台服务条款。只有在用户明确同意后,才加 `--accept-terms`。
|
|
52
|
+
- `--question` 和 `--answer` 都必填,缺任何一个平台都会报参数异常。
|
|
53
|
+
- 删除前,CLI 会逐个核对反馈是否属于这个应用,不属于的会拒绝删除。
|
|
54
|
+
|
|
55
|
+
## 同义词(`adp synonym`)
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
adp synonym create --word 可口可乐 --synonym 可乐 --synonym coke --format json
|
|
59
|
+
adp synonym list --unreleased --format json
|
|
60
|
+
adp synonym export --output synonyms.xlsx
|
|
61
|
+
adp synonym import --file synonyms.xlsx
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
- 一个词在应用里只能出现一次(标准词或某个同义词)。冲突时命令报 `SynonymConflict`,消息会指出冲突的词现在是标准词还是哪个标准词的同义词,按 `next_actions` 里的 `synonym list --query` 找到已有条目再改。
|
|
65
|
+
- 导入只接受 `.xlsx`。`export` 出的文件(包括没有数据、只有表头的导出)可以直接当模板改了再导入;不要改表头,标准词和同义词都不能留空,同义词一行一个。已有的词会被跳过,不会覆盖。
|
|
66
|
+
- 导入是异步落库的,命令返回后几秒内 `synonym list` 才能看到。文件有错时报 `SynonymImportFailed`,CLI 会把平台标注过错误行的文件存成 `<原文件名>.errors.xlsx`,打开看每行的原因。
|
|
67
|
+
- 同义词改动同样要 `adp deploy` 后才生效。
|
|
68
|
+
|
|
69
|
+
## 不满意回复(`adp unsatisfied`)
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
adp unsatisfied list --status pending --format json
|
|
73
|
+
adp unsatisfied get --reply-id <id> # 看上下文
|
|
74
|
+
adp unsatisfied handle --reply-id <id> --status ignored
|
|
75
|
+
adp unsatisfied export --output unsatisfied.xlsx
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
- 「加入问答」「加为相似问」目前只能在控制台操作,CLI 只做拒答和忽略。
|
|
79
|
+
- 点踩原因标签用 `adp unsatisfied label` 管理。
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# 云盘(`adp volume`)
|
|
2
|
+
|
|
3
|
+
云盘是空间级的文件存储,应用可以挂载。所有命令都需要 `--space-id`(不传时读 `adp.jsonc`)。
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
adp volume create --name 研发资料 --format json # 名称在空间内唯一
|
|
7
|
+
adp volume upload --volume-id <id> --file ./report.pdf --to docs/
|
|
8
|
+
adp volume ls --volume-id <id> --path docs --format json
|
|
9
|
+
adp volume download --volume-id <id> --path docs/report.pdf --output ./report.pdf
|
|
10
|
+
adp volume mv --volume-id <id> --path docs/report.pdf --name report-v2.pdf # 原地改名
|
|
11
|
+
adp volume rm --volume-id <id> --path docs --recursive --yes
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
- 路径相对云盘根目录,不能含 `..`。`--to` 以 `/` 结尾时保留本地文件名。
|
|
15
|
+
- 上传不会覆盖已有文件(`VolumeEntryExists`)。要替换时先 `rm` 再上传,并先和用户确认。
|
|
16
|
+
- `mv` 用 `--path` 指定原文件、`--name` 给新文件名(只是文件名,不带目录),只能原地改名,不能移动目录或给目录改名。
|
|
17
|
+
- 删除目录必须加 `--recursive`。`volume delete` 会删掉云盘里所有文件;先用 `volume get` 看 `referenceApps`,有应用挂载时和用户确认。
|
|
18
|
+
- `preview-url --reveal` 输出的是短期可访问的链接,只在用户要时给出,不要写进日志。
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
# Workflow canvases and mounting
|
|
2
|
+
|
|
3
|
+
## Fast path
|
|
4
|
+
|
|
5
|
+
1. Copy a template from [canvas/](canvas/), set `WorkflowName` (unique per app) and
|
|
6
|
+
`WorkflowDesc`, and edit node data only.
|
|
7
|
+
2. Write only `Nodes` with their `NextNodeIDs`. Leave out `Edge` and `NodeUI`: the CLI
|
|
8
|
+
derives the connections from `NextNodeIDs` and lays the nodes out.
|
|
9
|
+
3. `adp workflow deploy --app-id <app> --canvas-file wf.json --dry-run --format json`.
|
|
10
|
+
It checks the canvas locally (unknown node types, duplicate names, unconnected nodes,
|
|
11
|
+
dead ends) and lists `canvasFixes`. Fix every reported problem, then run it with `--yes`.
|
|
12
|
+
4. To change a deployed workflow, deploy again **into the same id**:
|
|
13
|
+
`adp workflow deploy --app-id <app> --workflow-id <wf> --canvas-file wf.json --yes`.
|
|
14
|
+
Do not create renamed copies. The result says `bound: false` because the entry binding
|
|
15
|
+
is left as it was, not removed. This saves the draft only: `--env test` sees it at once,
|
|
16
|
+
but `--env prod` and `adp chat` keep the old version until `adp deploy` releases the app.
|
|
17
|
+
5. Draft check in mode 3: `adp workflow run start --app-id <app> --query "<q>" --env test`
|
|
18
|
+
and read `answer`. Publish with `adp deploy`, then `adp chat`.
|
|
19
|
+
|
|
20
|
+
Inside a project directory every `adp workflow …` command defaults `--app-id` to
|
|
21
|
+
`app_id` in `adp.jsonc`.
|
|
22
|
+
|
|
23
|
+
| Template | Shape | Reply |
|
|
24
|
+
|---|---|---|
|
|
25
|
+
| [canvas/single.json](canvas/single.json) | START → CODE_EXECUTOR → ANSWER → END | `WF-OK:<user query>` |
|
|
26
|
+
| [canvas/llm.json](canvas/llm.json) | START → LLM → ANSWER (`Output.Content`) → END | model reply |
|
|
27
|
+
| [canvas/branch.json](canvas/branch.json) | START → LOGIC_EVALUATOR → 2 × ANSWER → END | `BR-YES` / `BR-NO` |
|
|
28
|
+
| [canvas/intent.json](canvas/intent.json) | START → INTENT_RECOGNITION → (计算: CODE_EXECUTOR → ANSWER, failure → ANSWER) / (闲聊: ANSWER) / (其他, fallback: ANSWER) → END | `CALC-OK:<query>` / `CALC-FAILED` / `CHAT` / `OTHER` |
|
|
29
|
+
| [canvas/option.json](canvas/option.json) | START → OPTION_CARD (基础版 / 专业版) → 2 × ANSWER → END | run pauses (`waiting_input`); `run resume --query 专业版` → `PLAN=PRO` |
|
|
30
|
+
| [canvas/dynamic-option.json](canvas/dynamic-option.json) | START → CODE → LOGIC (AND: `GE`, `NOT_CONTAINS`) → dynamic OPTION_CARD → LOGIC (`IN`) → ANSWER → END | query `many` pauses with `options` 北京/上海/广州; resume 北京 → `IN-OK`, 广州 → `NOT-IN`, 火星 → `ELSE`; query `one` → `FEW` |
|
|
31
|
+
| [canvas/extract.json](canvas/extract.json) | START → PARAMETER_EXTRACTOR (`date`) → ANSWER (`Output.date`) → END | `DATE=2026-11-03` for 「评审定在2026年11月3日」 |
|
|
32
|
+
| [canvas/sub.json](canvas/sub.json) | START(input `topic`) → CODE_EXECUTOR → END(output `result`) | none (child) |
|
|
33
|
+
| [canvas/main.json](canvas/main.json) | START → WORKFLOW_REF → ANSWER → END | `MAIN:<child result>` |
|
|
34
|
+
| [canvas/deep-research.json](canvas/deep-research.json) | START → 3 × WORKFLOW_REF (plan → research → summarize) → ANSWER → END | `MAIN:<summarize result>` |
|
|
35
|
+
|
|
36
|
+
## Canvas rules
|
|
37
|
+
|
|
38
|
+
- One `START`, one `END`. END does not reply: the user sees the **`ANSWER`** node
|
|
39
|
+
(`AnswerNodeData.Answer`, `{{var}}` declared in `Inputs`). There is no `REPLY` type.
|
|
40
|
+
- Every node except END lists its successors in `NextNodeIDs`, and every node must be
|
|
41
|
+
reachable from START. Branch nodes put each branch target in its own entry:
|
|
42
|
+
`LogicEvaluatorNodeData.Group[i].NextNodeIDs` (at least 2 groups; the last group without
|
|
43
|
+
`Logical` is else), `OptionCardNodeData.Options[i].NextNodeIDs`,
|
|
44
|
+
`IntentRecognitionNodeData.Intents[i].NextNodeIDs`; the node's own `NextNodeIDs` stays
|
|
45
|
+
empty. The CLI generates the branch edges and handles. See `branch.json`.
|
|
46
|
+
- INTENT_RECOGNITION (see `intent.json`): `IntentRecognitionNodeData.{ModelName,
|
|
47
|
+
ModelParams{Temperature,TopP,MaxTokens}, Prompt, Intents[]}`; each intent has `Name`,
|
|
48
|
+
`Desc`, `Example` (one string; an `Examples` array is dropped on save) and its own
|
|
49
|
+
`NextNodeIDs`. The node's own `NextNodeIDs` is `[]`, and the query reaches `Prompt`
|
|
50
|
+
through an `Inputs` entry (`{{q}}`).
|
|
51
|
+
- The platform treats the **last** entry of `Intents` as the fallback: it is not offered to
|
|
52
|
+
the model, and every query that matches no other intent goes there. The node output then
|
|
53
|
+
reads `{"IntentIndex": <N>, "IntentName": "Other"}` (`IntentIndex` is 1-based, N = number
|
|
54
|
+
of intents), whatever that intent is called. So always end `Intents` with an explicit
|
|
55
|
+
fallback such as `其他`; a real intent placed last (for example 闲聊) would never be
|
|
56
|
+
recognised and would swallow unrelated queries.
|
|
57
|
+
- OPTION_CARD (see `option.json`): `OptionCardNodeData.{Question, Options[], CardFrom}`;
|
|
58
|
+
`Question` is the prompt shown above the buttons, each option is `{Content, NextNodeIDs}`
|
|
59
|
+
(`Content` is the button text; there is no id field), `CardFrom: "INPUT"` for static
|
|
60
|
+
options. The node's own `NextNodeIDs` and `Inputs` stay empty. Downstream nodes read
|
|
61
|
+
`REFERENCE_OUTPUT` `Output.OptionContent` / `Output.OptionIndex`. A run pauses at the
|
|
62
|
+
card (`waiting_input`); answer with one option's `Content`.
|
|
63
|
+
- OPTION_CARD dynamic options (console 「动态拉取变量值」, see `dynamic-option.json`, verified on
|
|
64
|
+
the platform): `CardFrom: "DYNAMIC"`, `Options: []`, and `DynamicOptionsRefInputName` names an
|
|
65
|
+
`ARRAY_STRING` entry of the card's own `Inputs` (usually a `REFERENCE_OUTPUT` to an upstream
|
|
66
|
+
list). The options form **one** branch:
|
|
67
|
+
```json
|
|
68
|
+
"OptionCardNodeData": {
|
|
69
|
+
"Question": "请选择城市:", "Options": [], "CardFrom": "DYNAMIC",
|
|
70
|
+
"DynamicOptionsRefInputName": "cities",
|
|
71
|
+
"DynamicOptionsRefNextNodeIDs": ["route"],
|
|
72
|
+
"DynamicOptionsElseNextNodeIDs": ["fallback"],
|
|
73
|
+
"SystemPrompt": "", "ModelName": "Hunyuan/hy3"
|
|
74
|
+
},
|
|
75
|
+
"Inputs": [{ "Name": "cities", "Type": "ARRAY_STRING",
|
|
76
|
+
"Input": { "InputType": "REFERENCE_OUTPUT", "Reference": { "NodeID": "code1", "JsonPath": "Output.cities" } } }]
|
|
77
|
+
```
|
|
78
|
+
`DynamicOptionsRefNextNodeIDs` is taken for any listed option, `DynamicOptionsElseNextNodeIDs`
|
|
79
|
+
for a free-text answer that matches none; route on `Output.OptionContent` after it (for example
|
|
80
|
+
LOGIC_EVALUATOR `IN`). The CLI derives both edges and checks the input name and type. A
|
|
81
|
+
dynamic card lists **every** option in the waiting run's `options`.
|
|
82
|
+
- Every static OPTION_CARD has a system 「其它」 option as its last choice: a free-text answer that
|
|
83
|
+
matches no option goes there. Like the intent fallback, it is not listed: the waiting run's
|
|
84
|
+
`options` (and `adp chat` `optionCards`) leave the last option out.
|
|
85
|
+
- PARAMETER_EXTRACTOR (see `extract.json`): `SaveWorkflow` stores only
|
|
86
|
+
`Parameters[i].{RefParameterID, Required, SubParams}`; a `Name` / `Type` / `Desc` written
|
|
87
|
+
into the node is dropped and the run fails with `NodeErr.RuntimeError`. Declare each
|
|
88
|
+
parameter inline as `{Name, Type (STRING|INT|FLOAT|BOOL), Desc, Required,
|
|
89
|
+
CorrectExamples[], IncorrectExamples[]}`: `adp workflow deploy` registers it for that node
|
|
90
|
+
(LKE `CreateParameter`, not in the public action list), replaces it with the returned
|
|
91
|
+
`RefParameterID`, and lists the ids in `result.parameters`. An entry that already has a
|
|
92
|
+
`RefParameterID` is kept as is. Examples are strings; empty strings are dropped (the
|
|
93
|
+
platform answers `8000999`). Downstream nodes read `Output.<Name>`.
|
|
94
|
+
Redeploying with `--workflow-id` reuses the ids the node already has: the platform rejects a
|
|
95
|
+
second `CreateParameter` with the same name on the node (`500334 参数名称重复`), so deploy
|
|
96
|
+
reads the stored canvas, looks the names up (LKE `GetParameterList`), rewrites those
|
|
97
|
+
definitions in place (LKE `UpdateParameter`) and only creates new names.
|
|
98
|
+
- `CorrectExamples` / `IncorrectExamples` steer extraction hard: a value written the way an
|
|
99
|
+
incorrect example is (measured: `10月20日` listed as incorrect) makes the node ask again even
|
|
100
|
+
though the user gave the date. List only formats you really want to refuse.
|
|
101
|
+
- PARAMETER_EXTRACTOR input rule: the node reads the user query from the dialog itself, so
|
|
102
|
+
leave `Inputs` empty. A `SYSTEM_VARIABLE` input (for example `SYS.UserQuery`) is rejected by
|
|
103
|
+
the platform (「参数提取节点中不允许引用系统变量」) and by the CLI before anything is sent. To
|
|
104
|
+
feed it preprocessed text, use a `REFERENCE_OUTPUT` input from an upstream node.
|
|
105
|
+
`UserConstraint` is the follow-up dialogue style (language, tone), not the parameter list.
|
|
106
|
+
When a required parameter is missing, the run pauses (`waiting_input`) for the follow-up answer.
|
|
107
|
+
- Failure branch on a node (CODE_EXECUTOR in `intent.json`): `ExceptionHandling` with
|
|
108
|
+
`Switch: "ON"`, `HandleMethod: "EXCEPTION_EXECUTE"`, `NextNodeIDs: [<failure node>]` and
|
|
109
|
+
`AbnormalRetrySwitch: "ABNORMAL_RETRY_OFF"`; the success path stays in the node's
|
|
110
|
+
`NextNodeIDs`. A handled failure does not fail the run: the run ends in `state: 2` and the
|
|
111
|
+
failed node's run carries `failCode` (for example `NodeErr.ExecuteCodeFailed`), so read
|
|
112
|
+
`nodeRuns[].failCode` or the reply to tell the branches apart.
|
|
113
|
+
- `WorkflowDesc` is plain text: the platform drops `<...>`, so the CLI rewrites it as `{...}`.
|
|
114
|
+
- LOGIC_EVALUATOR `CONTAINS` / `EQ` with `MatchType: PRECISE` are case-sensitive (`YES` does
|
|
115
|
+
not contain `yes`); normalise case in a CODE_EXECUTOR first if needed.
|
|
116
|
+
- LOGIC_EVALUATOR `Comparison.Operator` (all verified in runs): `EQ` 等于, `NE` 不等于, `GT` 大于,
|
|
117
|
+
`GE` 大于等于, `LT` 小于, `LE` 小于等于 (`LeftType` `INT` or `FLOAT`; the right value is a number
|
|
118
|
+
string such as `"2"`), `CONTAINS` 包含 / `NOT_CONTAINS` 不包含 (`STRING` or `ARRAY_STRING`),
|
|
119
|
+
`IN` 属于 / `NOT_IN` 不属于 (left value against the right `Values[]` list), `IS_SET` 已填充 /
|
|
120
|
+
`NOT_SET` 未填充 (no right value needed). `NEQ` and `UNSPECIFIED` fail the run
|
|
121
|
+
(`NodeErr.ExistUnsupportedOperator`); the CLI rejects them, and numeric operators on a non-number
|
|
122
|
+
`LeftType`, before anything is sent. `LeftType` uses the output types (`STRING`, `INT`, `FLOAT`,
|
|
123
|
+
`BOOL`, `OBJECT`, `ARRAY_STRING`, …).
|
|
124
|
+
- Several conditions in one group: `{"LogicalOperator": "AND" | "OR", "Compound": [<single
|
|
125
|
+
conditions>]}` with **no** `Comparison` beside `Compound` (a leftover `Comparison: {}` is read as
|
|
126
|
+
`UNSPECIFIED`; the CLI removes it). A single condition is `LogicalOperator: "UNSPECIFIED"`,
|
|
127
|
+
`Compound: []` and the `Comparison`. See `dynamic-option.json`.
|
|
128
|
+
- Node data key is `<Type>NodeData`: `StartNodeData`, `CodeExecutorNodeData`,
|
|
129
|
+
`AnswerNodeData`, `LLMNodeData`, `WorkflowRefNodeData`.
|
|
130
|
+
- `NodeID` matches `^[a-zA-Z_][a-zA-Z0-9_]*$`; `NodeName` is unique in the canvas.
|
|
131
|
+
- Input sources (`Input.InputType`): `USER_INPUT`, `REFERENCE_OUTPUT`
|
|
132
|
+
(`Reference: {NodeID, JsonPath: "Output.<field>"}`), `SYSTEM_VARIABLE`
|
|
133
|
+
(`SystemVariable: {Name: "SYS.UserQuery"}`), `CUSTOM_VARIABLE`, `NODE_INPUT_PARAM`,
|
|
134
|
+
`ENV_VARIABLE`, `APP_VARIABLE`, `WORKFLOW_VARIABLE`. `CONSTANT`/`TEXT` do not exist.
|
|
135
|
+
- CODE_EXECUTOR: `def main(params: dict) -> dict`; returned keys equal
|
|
136
|
+
`Outputs[0].Properties[*].Title`. Types: `STRING`, `INT`, `FLOAT`, `BOOL`, `OBJECT`,
|
|
137
|
+
`ARRAY_*` (no `NUMBER`).
|
|
138
|
+
- LLM nodes (see `llm.json`): `LLMNodeData.{ModelName, ModelParams{Temperature,TopP,MaxTokens},
|
|
139
|
+
SystemPrompt, Prompt}`, no `0` params; the next node reads `Output.Content`. Not every
|
|
140
|
+
`adp models` entry works in workflows: an unusable one fails deploy with
|
|
141
|
+
`获取模型信息为空`. `Hunyuan/hy3` works; otherwise pick from the node type's scene:
|
|
142
|
+
`adp models --scene 20` (LLM), 22 (PARAMETER_EXTRACTOR), 23 (LLM_KNOWLEDGE_QA),
|
|
143
|
+
24 (TAG_EXTRACTOR), 25 (INTENT_RECOGNITION), 26 (OPTION_CARD), 27 (LOGIC_EVALUATOR).
|
|
144
|
+
The deploy error's next_action is that scene's list for the failing node (scene 18 is
|
|
145
|
+
Claw apps, not workflows).
|
|
146
|
+
- Local check (also `--dry-run`, nothing sent): cycles (`cycle a -> b -> a`, with the edge to
|
|
147
|
+
remove), a `Reference.NodeID` that names no node, and an `Output.<field>` that the source
|
|
148
|
+
node does not declare when it declares outputs (PARAMETER_EXTRACTOR inline parameter
|
|
149
|
+
`Name`s, CODE_EXECUTOR `Outputs[0].Properties[*].Title`). Renaming an extractor parameter
|
|
150
|
+
without updating the readers is caught here, with node id and the declared names. Every
|
|
151
|
+
reference in the node is checked, not just `Inputs`: LOGIC_EVALUATOR `Comparison.Left` /
|
|
152
|
+
`Right`, OPTION_CARD dynamic options, LLM / INTENT prompt variables and END outputs.
|
|
153
|
+
- `workflow deploy --dry-run` also checks each LLM / extractor / intent / option card node's
|
|
154
|
+
`ModelName` against `adp models --scene <n>` (read-only): a model the scene does not list fails
|
|
155
|
+
with `WorkflowModelInvalid` and a `models --scene` next action; when the model list cannot be
|
|
156
|
+
read the preview only warns (`WorkflowModelCheckSkipped`).
|
|
157
|
+
- Follow-ups after a failed deploy (`WorkflowCanvasInvalid`, `WorkflowModelInvalid`,
|
|
158
|
+
`WorkflowValidationError`) are your own command with every flag kept (`--no-bind`, `--name`,
|
|
159
|
+
`--workflow-id`, `--env`, …); only `--dry-run` / `--yes` change. After a successful deploy in a
|
|
160
|
+
Standard (1) or workflow (3) app the next actions preview another `--no-bind` deploy and
|
|
161
|
+
`adp deploy --dry-run`. `adp deploy --dry-run` warns when workflows will be published even though
|
|
162
|
+
`previewTotal` is 0.
|
|
163
|
+
- `workflow deploy --workflow-id … --dry-run` reads the stored canvas and
|
|
164
|
+
`GetParameterList` (read-only) and plans `UpdateParameter` for parameters the node already
|
|
165
|
+
registered, `CreateParameter` only for new ones — the same as the real deploy.
|
|
166
|
+
- When the platform rejects a canvas that passed the local check
|
|
167
|
+
(`WorkflowValidationError`), the next_action is the same `workflow deploy` with `--yes`
|
|
168
|
+
instead of `--dry-run` (it writes): edit the node the message names first; re-running
|
|
169
|
+
`--dry-run` proves nothing. That action, and the local re-check after `WorkflowCanvasInvalid`,
|
|
170
|
+
carry `needs_edit: {"file": "<canvas file>"}`: edit that file before running them; running
|
|
171
|
+
them unchanged fails the same way.
|
|
172
|
+
- Workflows brought in with `workflow import --enable` need no `workflow deploy`: the next
|
|
173
|
+
`adp deploy` (app release) publishes them along with the app. In the rare case an enabled
|
|
174
|
+
workflow is still `UNPUBLISHED` after a release, `adp deploy` warns
|
|
175
|
+
(`unpublishedWorkflows`) and its next_action re-saves it with `workflow deploy --workflow-id`.
|
|
176
|
+
|
|
177
|
+
## Nested workflows (WORKFLOW_REF)
|
|
178
|
+
|
|
179
|
+
1. Children: copy `sub.json` per step (change `WorkflowName` and the code), deploy each with
|
|
180
|
+
`--no-bind`, and note the returned `workflowId`.
|
|
181
|
+
- Child START declares parameters in `StartNodeData.Inputs`; child nodes read them
|
|
182
|
+
with `REFERENCE_OUTPUT` on the START node (`JsonPath` = parameter name).
|
|
183
|
+
- Child END exposes `Outputs[0].Properties[*]` with
|
|
184
|
+
`Value: {InputType: "REFERENCE_OUTPUT", Reference: {NodeID, JsonPath: "Output.result"}}`.
|
|
185
|
+
2. Parent: put each child id in `WorkflowRefNodeData.WorkflowID` (in `deep-research.json`,
|
|
186
|
+
replace `<PLAN_WORKFLOW_ID>`, `<RESEARCH_WORKFLOW_ID>`, `<SUMMARIZE_WORKFLOW_ID>`).
|
|
187
|
+
`RefInputs` match the child inputs by `Name` and `Type`; a later step reads the previous
|
|
188
|
+
one with `REFERENCE_OUTPUT` `Output.result`.
|
|
189
|
+
- An `OBJECT` or `ARRAY_*` input also needs `RefInputs[i].SubInputs` listing every child
|
|
190
|
+
field, each with its own `Input.Reference.JsonPath` (for `cfg` read from `Output.cfg`:
|
|
191
|
+
`{Name: "topic", Type: "STRING", Input: {InputType: "REFERENCE_OUTPUT", Reference:
|
|
192
|
+
{NodeID: "code0", JsonPath: "Output.cfg.topic"}}}`). Matching `Name` and `Type` alone
|
|
193
|
+
fails deploy with `<ref NodeID>: 输入参数不匹配`.
|
|
194
|
+
3. Deploy the parent last. In a run, `adp workflow run get --sub-workflow-path <ref NodeID>`
|
|
195
|
+
shows a child run, but its `output` can be `{}`; read a child's result with
|
|
196
|
+
`adp workflow run node --node-run-id <id>` on the WORKFLOW_REF node run.
|
|
197
|
+
|
|
198
|
+
Verified: children returning `PLAN:`, `RESEARCH:`, `SUM:` prefixes reply
|
|
199
|
+
`MAIN:SUM:RESEARCH:PLAN:<query>`.
|
|
200
|
+
|
|
201
|
+
## How each app mode runs a workflow
|
|
202
|
+
|
|
203
|
+
| app_mode | How the workflow is reached | Steps |
|
|
204
|
+
|---|---|---|
|
|
205
|
+
| 3 single workflow | Every message runs the entry workflow | `workflow deploy` (binds entry) → `adp deploy` → `adp chat` |
|
|
206
|
+
| 1 standard | Routed by `WorkflowDesc` among enabled workflows | `workflow deploy` with a specific `WorkflowDesc` → `adp deploy` → `adp chat` with a query matching the description |
|
|
207
|
+
| 4 Claw | The agent calls it as a tool | `workflow deploy --no-bind` → `adp deploy` → `adp agent tool bind --agent-id <id> --plugin-id <wf> --tool-id <wf> --workflow` → add the tool to `agent.tools` in `adp.jsonc` (`tool_source: 1`) → `adp deploy` → `adp chat` |
|
|
208
|
+
| 2 Multi-Agent | Tool of an agent, or the collaboration workflow | same as Claw for tools |
|
|
209
|
+
|
|
210
|
+
- Claw/Multi-Agent: `adp deploy` writes `agent.tools` from `adp.jsonc` as a whole list. A
|
|
211
|
+
tool bound only with `agent tool bind` is removed by the next deploy unless it is also
|
|
212
|
+
in `agent.tools`. Check with `adp agent resources --env prod`.
|
|
213
|
+
- A workflow used as an agent tool must not pause for input (no OPTION_CARD,
|
|
214
|
+
TEXT_COLLECTION, FILE_COLLECTION, PARAMETER_EXTRACTOR).
|
|
215
|
+
- `adp chat` only talks to the **released** app; before `adp deploy` it fails with
|
|
216
|
+
`AppNotReleased` (platform `460048 应用未发布`, exit 5) and next action `adp deploy`.
|
|
217
|
+
- `workflow run start` / `get` return `answer` (the ANSWER node text) when the run-level
|
|
218
|
+
`output` is empty. Only queued, running or waiting runs can be stopped.
|
|
219
|
+
- A run that reaches a node waiting for the user (OPTION_CARD, TEXT_COLLECTION,
|
|
220
|
+
PARAMETER_EXTRACTOR follow-up, …) reports `state: 5`, `stateLabel: "waiting_input"`
|
|
221
|
+
(state 5 is not in the public enum). `run start` stops waiting at once and returns
|
|
222
|
+
`status: "waiting_input"` and `question` (the node's latest message, e.g. the
|
|
223
|
+
PARAMETER_EXTRACTOR follow-up 「请提供要查询的日期」, read from ADP `DescribeWorkflowRun`
|
|
224
|
+
`WorkflowRunOutput.LatestMessage`). When that message is an option card
|
|
225
|
+
(`OptionCardList`), `options` lists the choices and the first next action is
|
|
226
|
+
`adp workflow run resume … --query <first option>` (change `--query` to pick another).
|
|
227
|
+
Otherwise (a free-text question such as a PARAMETER_EXTRACTOR follow-up) `options` is `[]`
|
|
228
|
+
and the first next action is `adp workflow run resume --app-id … --run-id … --format json`
|
|
229
|
+
with `needs_input: {"flag": "query", "question": "…"}`: append `--query '<the user's answer>'`
|
|
230
|
+
before running it. A `needs_input` command lacks exactly that one flag (here the required
|
|
231
|
+
`--query`) by design; append it, never a placeholder. The second next action is `adp workflow run get …` (it repeats
|
|
232
|
+
`question`). `adp chat` does the same when the app's reply asks the user something (a
|
|
233
|
+
PARAMETER_EXTRACTOR follow-up such as 「请问要查询哪个城市?」): the next action is
|
|
234
|
+
`adp chat --conversation-id … --format json` with `needs_input: {"flag": "message", "question": "…"}`,
|
|
235
|
+
not a canned `--message "继续"` (the extractor would take 继续 as the value). Run results (start / resume / get) always carry `question` and `options` (`null` when the run is not waiting), so `--fields question,options` works on finished runs too. A terminal `adp chat` reply (no option card, no question) gets no next action: a generic follow-up would only re-enter the workflow. A renamed or removed extractor parameter leaves its old registration on the platform (no public delete API); only the in-place `workflow deploy --workflow-id` that drops it from the canvas lists it under `staleParameters` (the CLI finds registered parameters through the stored canvas's `RefParameterID`s, so once a deploy has saved a canvas without it, later deploys no longer see or list it). Note the `parameterId`s from that deploy if you need them. After an OPTION_CARD, `SYS.UserQuery` in later nodes is the clicked button's text, not the user's original message: to keep the original text, read it from a node that ran before the card (an LLM or PARAMETER_EXTRACTOR output) instead of `SYS.UserQuery`. The `planned` ModifyApp line says when the deploy rebinds the mode 3 entry workflow. `run resume` then waits like `start` for the next terminal
|
|
236
|
+
or waiting state (`--no-wait` returns `status: "resumed"` at once). After a resume the run
|
|
237
|
+
can drop out of state 5 and back within one poll on the same node run (a follow-up asked
|
|
238
|
+
again), so resume counts a state 5 seen 6 s after the resume as the new pause. Answer an
|
|
239
|
+
option card with one option's text exactly as listed in `options`. `run resume` has no
|
|
240
|
+
run-environment flag: the run id already fixes test/prod (`--env` on resume is only the
|
|
241
|
+
global `adp.env.<name>.jsonc` overlay).
|