@xdxer/dingtalk-agent 0.1.5-beta.3 → 0.1.5-beta.5
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/CHANGELOG.md +41 -0
- package/README.en.md +92 -65
- package/README.md +92 -65
- package/dist/bin/dingtalk-agent.js +142 -16
- package/dist/bin/dingtalk-agent.js.map +1 -1
- package/dist/src/agent-platform.js +1 -0
- package/dist/src/agent-platform.js.map +1 -1
- package/dist/src/development-workspace.js +66 -3
- package/dist/src/development-workspace.js.map +1 -1
- package/dist/src/doctor.js +1 -1
- package/dist/src/doctor.js.map +1 -1
- package/dist/src/multica-deploy.js +101 -9
- package/dist/src/multica-deploy.js.map +1 -1
- package/dist/src/multica-provider.js +157 -2
- package/dist/src/multica-provider.js.map +1 -1
- package/dist/src/schedule-plan.js +105 -0
- package/dist/src/schedule-plan.js.map +1 -0
- package/dist/src/skill-manager.js +5 -0
- package/dist/src/skill-manager.js.map +1 -1
- package/docs/ARCHITECTURE.md +133 -18
- package/docs/PRIOR-ART.md +4 -0
- package/docs/SELF-TEST.md +1 -1
- package/docs/architecture/agent-platform-connection-layer.svg +120 -0
- package/docs/architecture/digital-employee-composition.svg +92 -0
- package/docs/architecture/dingtalk-agent-architecture.svg +125 -0
- package/docs/assets/digital-employee-at-work.svg +77 -0
- package/docs/schemas/multica-workspace-run.schema.json +150 -33
- package/docs/schemas/project.schema.json +22 -0
- package/docs/schemas/workspace-scaffold.schema.json +37 -0
- package/examples/agents/README.md +1 -1
- package/lab/project-workspace/fake-multica-provider.mjs +18 -2
- package/lab/project-workspace/opencode-provider-suite.json +1 -1
- package/lab/robot-eval/suite.json +1 -1
- package/package.json +3 -2
- package/skills/core/dingtalk-agent-compose/SKILL.md +22 -3
- package/skills/core/dingtalk-agent-compose/assets/AGENTS.template.md +1 -1
- package/skills/core/dingtalk-agent-compose/references/drive-and-schedules.md +124 -0
- package/skills/core/dingtalk-basic-behavior/SKILL.md +5 -4
- package/skills/core/dingtalk-basic-behavior/references/event-to-behavior.md +15 -1
- package/skills/core/dingtalk-basic-behavior/references/perception-and-gates.md +3 -0
- package/skills/core/dingtalk-basic-behavior/references/risk-authority-and-privacy.md +12 -0
- package/skills/core/dingtalk-people-group-memory/COMPLETENESS.md +36 -0
- package/skills/core/dingtalk-people-group-memory/SKILL.md +69 -0
- package/skills/core/dingtalk-people-group-memory/references/adapters.md +273 -0
- package/skills/core/dingtalk-people-group-memory/references/assembly-guidance.md +40 -0
- package/skills/core/dingtalk-people-group-memory/references/binding.md +110 -0
- package/skills/core/dingtalk-people-group-memory/references/cold-start.md +70 -0
- package/skills/core/dingtalk-people-group-memory/references/config-binding.md +89 -0
- package/skills/core/dingtalk-people-group-memory/references/consent-and-visibility.md +83 -0
- package/skills/core/dingtalk-people-group-memory/references/consolidation.md +162 -0
- package/skills/core/dingtalk-people-group-memory/references/event-ingest.md +103 -0
- package/skills/core/dingtalk-people-group-memory/references/guided-setup.md +70 -0
- package/skills/core/dingtalk-people-group-memory/references/model.md +148 -0
- package/skills/core/dingtalk-people-group-memory/references/storage-port.md +107 -0
- package/skills/platforms/deap/PLATFORM.md +30 -1
- package/skills/platforms/multica-dingtalk/PLATFORM.md +25 -0
- package/skills/platforms/multica-dingtalk/dingtalk-agent-deploy-multica/SKILL.md +3 -2
- package/skills/platforms/multica-dingtalk/multica-external/SKILL.md +15 -0
- package/docs/assets/agent-delivery-lifecycle.svg +0 -103
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# 存储端口契约
|
|
2
|
+
|
|
3
|
+
本篇定义 Fact 怎么落地。**模型层(`model.md`)与事件层(`event-ingest.md`)只对本端口编程,不认识钉钉。** 介质特有的坑全部收在 `adapters.md`。
|
|
4
|
+
|
|
5
|
+
**解耦检验**:把某适配器的能力位调成最宽松档后,通用算法里的完整性校验、写后回读、判重读、翻页判存在四条分支应**自动全灭,Skill 正文一字不改**。
|
|
6
|
+
|
|
7
|
+
## 零、先用端口形状消解,剩下的才用能力位描述
|
|
8
|
+
|
|
9
|
+
三条病理不进能力位,靠端口形状让它**说不出来**:
|
|
10
|
+
|
|
11
|
+
- **没有 delete / update 操作** → `raw` 只增不删由形状强制,遗忘只能 append tombstone。
|
|
12
|
+
- **水位是 meta 键空间的一等对象,不是任何页里的一行** → 「水位必须放短页」这件事无从发生。
|
|
13
|
+
- **模型层词汇里没有页、分区、seg、月份** → 切的是 Fact,不是页;物理分区如何滚动是适配器私事。
|
|
14
|
+
|
|
15
|
+
**适配器私有地址空间**:适配器可在自己的地址空间保存分区表、哨兵、物理 ID。模型层不可读不可写;端口签名里**不得出现任何介质地址类型**(nodeId / URL / 路径),它们只出现在 `resolve` 返回的不透明句柄与绑定档案里。
|
|
16
|
+
|
|
17
|
+
🔴 **用户可见链接的锚点必须是 `(subjectKey, section, evidenceId)` 三元**,永不含物理分区名——否则换介质即死链。
|
|
18
|
+
|
|
19
|
+
## 一、操作集(10 个)
|
|
20
|
+
|
|
21
|
+
| 操作 | 语义 / 前置 | 返回与失败模式 |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| `resolve(agentIdentity)` | Boot 期一次解析两个 root 与能力位;同 Session 缓存 | `{roots[], capabilities}`;`NOT_CONFIGURED`(确证未建,可引导)/`UNAVAILABLE`(读失败,**禁止折成 NOT_CONFIGURED**)/`DRIFT(level, observed, expected)`(只报双边真实值,不自愈)。两 root 各自独立 |
|
|
24
|
+
| `probeWrite(root)` | **显式、昂贵、绑定期一次** | `writable` / `read-only` / `write-unverified`。结果写进绑定档案,运行期不重复探测 |
|
|
25
|
+
| `ensureEntity(root, subjectKey, displayHint)` | 唯一的建档动作。**禁止在 ingest/消息触发路径调用** | `exists` / `created` / `ambiguous`(同键多实例=残片)→ `ambiguous` 一律 HALT,不自愈、不猜正本 |
|
|
26
|
+
| `listEntities(root, cursor)` | 判「不存在」的唯一权威来源 | `{keys[], cursor, complete}`;`complete=false` 的结果**只能用于发现,不能用于否定** |
|
|
27
|
+
| `appendFacts(subject, section, facts[])` | 只增追加;facts 自带 `evidenceId` | `receipt{accepted[], skipped[]}`;`PARTIAL` / `UNVERIFIED` / `TOO_LARGE` / `READ_ONLY` |
|
|
28
|
+
| `readFacts(subject, section, range)` | 跨物理分区连续读 | `{facts[], cursor, complete}`;`complete=false` **等同读失败**,不是空 |
|
|
29
|
+
| `putView(subject, section, content, {expectVersion?})` | 整体重写;端口按 section 的 `layer` **拒绝对 `raw` 调用** | `receipt{version}`;`STALE` / `TOO_LARGE`(降级为摘要视图,溢出内容降为 Fact) |
|
|
30
|
+
| `readView(subject, section)` | 召回主路径 | `{content, version, complete}`;`NOT_FOUND` 是**合法初态**,必须与 `UNAVAILABLE` 严格可区分 |
|
|
31
|
+
| `metaGet / metaPut(scope, key, value, {expectVersion?})` | A0 键空间:水位、writeState、绑定档案、停用账本、tombstone 索引、欠账指针 | `{value, version}` / `NOT_FOUND` / `CONFLICT`。🔴 **水位键固定为 `watermark:(subjectKey, channel)`,与 section 正交** |
|
|
32
|
+
| `confirm(receipt)` | 通用算法**无条件调用**;`write.confirm=implicit` 时 O(1) 返回、零往返 | `confirmed` / `unconfirmed` / `failed`。未 confirmed 不得声称已记 |
|
|
33
|
+
|
|
34
|
+
🔴 **水位键必须是 `(subject, channel)`,绝不能是 `(subject, section)`。** 一个 section 可能同时吃多个渠道的事件(`activity` 同时吃待办与文档),两渠道追平进度天然不同;用 section 当键会让追平待办后推进的水位把文档的未消化区间一起判成已消化,**那批事件永远不会被再消化**——正好踩中「水位虚高不可逆」。
|
|
35
|
+
|
|
36
|
+
## 二、能力位(8 位 + 容量参数)
|
|
37
|
+
|
|
38
|
+
**准入规则(硬性)**:新增一位必须能**同时改变 ≥2 个适配器的行为**,否则它是适配器内部细节,不许上浮。**位数上限 8。**
|
|
39
|
+
|
|
40
|
+
| 位 | 取值 | 通用算法据此改变什么 |
|
|
41
|
+
|---|---|---|
|
|
42
|
+
| `read.completeness` | `exact` / `verified-partial` | `verified-partial` 时 `complete=false` 按读失败处理:记欠账、跳过本轮。**完整性如何自证全在适配器内部,模型层不知道「截断」这个词**。🔴 **静默截断介质(doc read 不报错)上,唯一可靠的自证是 count 对账**:写侧在 meta 记 `count:(subject,section,partition)`,读回条数 ≠ 记录条数即 `complete=false`。哨兵尾行会被静默截断吃掉,不可靠。详见 `consolidation.md` §0 |
|
|
43
|
+
| `limits.maxFactBytes` / `maxViewBytes` | 整数 / ∞ | 超限时**切 Fact**(同 `evidenceId` 拆多条)或把 View 降级为摘要 |
|
|
44
|
+
| `write.confirm` | `implicit` / `required` | `required` 时每次写后真回读 |
|
|
45
|
+
| `write.cas` | `none` / `revision` | `none`:append → confirm → metaPut 三步,任一失败整批作废、水位不动。`revision`:两步原子提交,`CONFLICT` 靠 `evidenceId` 幂等重放 |
|
|
46
|
+
| `dedupe.enforcement` | `server` / `client` | `client` 时重放前必须 `readFacts` 尾窗判重,且**要求 `complete=true` 才敢重放**;否则不写、记欠账、水位不动 |
|
|
47
|
+
| `identity.collision` | `reject` / `silent-rename` | `silent-rename` 时 `ensureEntity` 内部回读核对,检出残片返回 `ambiguous` |
|
|
48
|
+
| `lookup.negative` | `immediate` / `list-only` | `list-only` 时任何搜索的 0 结果**不构成否定证据**;否定结论只能来自 `listEntities(complete=true)` |
|
|
49
|
+
| `access.scope` | `container` / `leaf` | `leaf` 时只接受叶子锚点 seed;容器枚举缺席一律映射为 `UNAVAILABLE`,**禁止**推出 `NOT_CONFIGURED` |
|
|
50
|
+
| `access.probe` | `declarative` / `empirical` | `empirical` 时 `resolve` 不承诺写权,须显式 `probeWrite` 一次并缓存 |
|
|
51
|
+
|
|
52
|
+
## 三、病理逐条映射
|
|
53
|
+
|
|
54
|
+
| 病理 | 归宿 | 通用算法的行为 |
|
|
55
|
+
|---|---|---|
|
|
56
|
+
| 原始层按月分页 | `read.completeness` + `limits.*` | 只调 `appendFacts/readFacts(range)`。「按月」降为适配器把一个 section 映射到多个物理对象的**内部分区策略**;本地文件上就是一个文件 |
|
|
57
|
+
| 水位必须放短页 | **端口形状消解** | `metaGet/Put` 独立寻址,落在哪是适配器的事 |
|
|
58
|
+
| 判存在只认列父目录翻完页 | `lookup.negative=list-only` | 先读模型层自持的索引 View 快判(有界成本);索引未命中且真要建时才付 `listEntities` 全量代价;`complete=false` → 记欠账、本拍跳过,**绝不新建** |
|
|
59
|
+
| 建后必回读核对残片 | `identity.collision=silent-rename` + `write.confirm` | 回读关进 `ensureEntity`,模型层只看三态;`ambiguous` → HALT 报人 |
|
|
60
|
+
| 先追加后推水位、任一失败整批作废 | `write.cas` + `write.confirm` | 这是 `cas=none` 分支的标准应对,不是某介质专属规则 |
|
|
61
|
+
| 写权用经验判定 | `access.probe=empirical` | 不查权限表、不解析显示名,只消费三态;`read-only` → 只召回不沉淀且禁说「我记住了」 |
|
|
62
|
+
| 容器级探测漏落点 | `access.scope=leaf` | `resolve` 只走 seed 一跳;容器级失败 = `UNAVAILABLE` 而非未配置 |
|
|
63
|
+
|
|
64
|
+
## 四、适配器取值表
|
|
65
|
+
|
|
66
|
+
🔴 **一个部署会同时用多个适配器**:narrative 类 section 走 `dingtalk-doc`,registry 类 section 走 `aitable`(见 `model.md` §三 kind、`adapters.md`)。端口的解耦价值正在这里——同一套模型层操作,registry 换介质就把一半病理关掉。
|
|
67
|
+
|
|
68
|
+
| 位 | `dingtalk-doc`(narrative·生产) | `aitable`(registry·生产,🔬实测) | `local-md`(开发/评测) |
|
|
69
|
+
|---|---|---|---|
|
|
70
|
+
| `read.completeness` | `verified-partial` | **`exact`** | `exact` |
|
|
71
|
+
| `maxFactBytes / maxViewBytes` | 4KB / 24KB | 单元格上限(故不放长正文) | ∞ / ∞ |
|
|
72
|
+
| `write.confirm` | `required` | `required` | `implicit` |
|
|
73
|
+
| `write.cas` | **`none`(raw 与 view 都是)** | `revision`(按 recordId 改行) | `revision`(临时文件 rename) |
|
|
74
|
+
| `dedupe.enforcement` | `client` | `server`(按 key 查重) | `client`(读 exact,故可靠) |
|
|
75
|
+
| `identity.collision` | `silent-rename` | `reject`(recordId 唯一) | `reject` |
|
|
76
|
+
| `lookup.negative` | `list-only` | **`immediate`**(`--filters` 查不到就是没有) | `immediate` |
|
|
77
|
+
| `access.scope` | `leaf` | `leaf`(baseId 直达) | `container` |
|
|
78
|
+
| `access.probe` | `empirical` | `declarative` | `declarative` |
|
|
79
|
+
|
|
80
|
+
> 🔬 **`aitable=exact/immediate` 是实测结论**(2026-07-23 核对 `dws aitable record query --help`):`--all`+`--cursor` 真分页无 341 行墙、`--filters` 按字段查、`record update --records` 按 recordId 精准改。**这就是"registry 类不该塞进文档"的凭据**:把 `00-群索引`/水位台账/tombstone 从 doc 挪到 aitable,`read.completeness=exact` 让 count 对账分支自动全灭、`lookup.negative=immediate` 让翻页判存在分支自动全灭。
|
|
81
|
+
|
|
82
|
+
> 🔬 **`dingtalk-doc` 的 `write.cas=none` 是实测结论**:`dws doc update` 只有 `--mode overwrite|append`,**没有任何 revision / expectVersion / CAS 参数**(2026-07-23 核对 `--help`)。所以编译层的整体重写同样没有并发保护,只能靠「写后回读 + 冲突时以最后一次为准」,并接受两个并发写者会互相覆盖。不要以为编译层比原始层安全。
|
|
83
|
+
|
|
84
|
+
`local-md` 落地形态:`<root>/people/<personKey>/` 为目录(**主键即目录名**,显示名进 front-matter),raw section = 一个只增 `.md`,view = 临时文件 rename,meta = `_meta/*.json`。
|
|
85
|
+
|
|
86
|
+
🔴 **`local-md --chaos` 是契约的组成部分,不是建议**:强制 `complete=false`、随机静默改名、随机 `UNVERIFIED`、注入索引延迟与判重读截断。CI 必须让 chaos 档与真实档跑同一组用例——否则这套抽象只是把 bug 挪到了适配器边界之外,第一次执行仍然发生在生产。
|
|
87
|
+
|
|
88
|
+
## 五、不能下放给适配器的模型层不变式
|
|
89
|
+
|
|
90
|
+
1. `raw` 只增不删、纠错用 `supersedes`;`derived` 可重建。**View 里不得存在唯一信息。**
|
|
91
|
+
2. `evidenceId` 全局唯一即去重键,必须是**源系统主键**(不得用内容哈希或时间戳)。端口只做机械去重,选错它无从发现。
|
|
92
|
+
3. `audience` 写入时定、读取时只收窄。**收窄必须 fail-closed**:读该实体事实时 `complete=false`,则本轮不引用它的任何事实,宁可答「不清楚」。
|
|
93
|
+
4. 交叉归属三铁律;唯一上浮方向 = 会话公开 → 人的 `public-facts`。
|
|
94
|
+
5. 水位键 `(subject, channel)` 单调不回退;**先写事实、后推水位**的因果顺序**即使有 CAS 也不得反转**(CAS 只允许合并两步,不允许先推)。
|
|
95
|
+
6. 「读失败 ≠ 不存在」的翻译权在模型层。**任何适配器不得把 `UNAVAILABLE` / `complete=false` 补成空集。**
|
|
96
|
+
7. section 的 `layer` 归属由模型层定义并交给端口;会话隐私档位白名单默认拒绝。
|
|
97
|
+
8. 知情同意:未启用态零写调用、未 `confirmed` 不说「我记住了」、首次落盘回读念一遍并给链接。
|
|
98
|
+
9. **有界降级**:同一 root 连续 N 次 `unconfirmed` ⇒ 作废 `probeWrite` 缓存、降级 `read-only`、显式报人。否则表现为「一直在记但什么都没记」。
|
|
99
|
+
|
|
100
|
+
## 六、这个抽象做不到什么(诚实清单)
|
|
101
|
+
|
|
102
|
+
- **并发建重复无法根除。** 无 CAS 介质上,端口只能把撞车压到绑定期一次并在事后 `ambiguous` → HALT。「建档只在绑定期由单写者触发」是**流程约束,不是端口能力**——这是抽象的公开缺口。
|
|
103
|
+
- **`client` 去重 + `verified-partial` 读存在真实双写窗口。** 判重读本身可能不全;缓解是「`complete=false` 即不重放」,代价是欠账增长而非双写。这两位的组合应在 `resolve` 阶段被显式标记为高风险档。
|
|
104
|
+
- **能力位大多是为 `dingtalk-doc` 的病理而设。** `aitable` 与 `local-md` 上这些位几乎全取宽松档、对应的通用算法分支全灭。这本是"抽象没做干净"的嫌疑——但反过来看,registry 走 aitable 后一半病理消失,恰恰证明**问题不在模型、在"把结构化数据塞进叙事介质"**。准入规则(≥2 适配器行为差异、上限 8 位)仍须执行,否则第 N 个介质接入时会退化成「每个适配器一个 if」。
|
|
105
|
+
- **判存在的读放大只被压小、没被消除。** 索引 View 可能陈旧,真要新建时仍需付全量翻页代价,且它落在「新人首次建档」这条常见路径上。
|
|
106
|
+
- **授权门不在本端口。** 它是消息**源侧**的门,归 ingest 源端口的 `AUTH_REQUIRED` 一态;放进存储端口即是端口变宽的开始。
|
|
107
|
+
- **端口窄度需要持续维护。** 任何一次「我只要再加一个 listFiles / getUrl」,都会把它推回通用文件系统。
|
|
@@ -1,3 +1,32 @@
|
|
|
1
1
|
# DEAP 平台说明
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**状态:敬请期待。** DEAP 的技能包与交付链尚未开放,`dta agent-platform use deap` 与全部平台命令一律 fail-closed。本文说明它在架构里的位置,不代表它已可用。
|
|
4
|
+
|
|
5
|
+
## 它可能同时扮演两个角色
|
|
6
|
+
|
|
7
|
+
注册表里 `deap` 与 `multica-dingtalk` 并列,但它在架构中可能比一个托管平台多一层(见 [Architecture §3](../../../docs/ARCHITECTURE.md#3-每件事谁说了算模型-b)):
|
|
8
|
+
|
|
9
|
+
| | Multica 这类托管平台 | DEAP |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| 组织身份与感知 | 不提供 | **主要角色**:签发身份、划定场域、送来事件、统一展示 |
|
|
12
|
+
| 运行位置 | **主要角色**:Workspace、Runtime、Agent 生命周期 | **待确认**:是否同时内建一层自己的运行平台 |
|
|
13
|
+
| 本仓库如何对待 | 通过注册表与平台 Skill 包**连接** | 身份与感知**开放后将消费**;运行位置若开放,同样按平台方式接入 |
|
|
14
|
+
|
|
15
|
+
对本项目而言,DEAP 目前最关键的是两层:
|
|
16
|
+
|
|
17
|
+
1. **身份权限管控** —— 数字员工的创建、UID、场域边界、入转调离与全生命周期。这一层决定一个 Agent 能以谁的名义、在什么范围内行动。本仓库不发证、不改写、不扩权,只把签发结果冻结进 Session 并全程审计。
|
|
18
|
+
2. **感知与人机交互** —— 事件订阅与结果展示。本仓库不拥有触发器,只要求送达的事件信封可信、可幂等。
|
|
19
|
+
|
|
20
|
+
第三层——它是否也提供运行位置——**尚待确认,注册表为此保留了 `deap` 条目**。如果它开放了平台能力,将和其它平台一样通过注册表与平台 Skill 包接入,不会因为它同时是身份与感知平面就获得旁路。两个角色互不排斥,本仓库分别对待,不合并成一格。
|
|
21
|
+
|
|
22
|
+
## 驱动能力:未知,且不能假定
|
|
23
|
+
|
|
24
|
+
装配侧可以声明一个数字员工需要哪些常驻节律(见 core 技能 `dingtalk-agent-compose` 的 `references/drive-and-schedules.md`),但**DEAP 是否提供 schedule 能力、是否允许 Agent 自主排程,目前都未确认**。
|
|
25
|
+
|
|
26
|
+
**平台之间驱动能力不同是常态**:不得把 Multica 的 autopilot 语义(5 段 cron、`run_only`、迟到 5 分钟跳过)转述成 DEAP 的行为,也不得因为 Agent 在 Multica 上跑通了节律就认为迁到 DEAP 后节律仍然成立。平台未开放期间,任何节律相关命令与 DEAP 上的其它平台命令一样 fail-closed;需要的节律记为**缺口**,不静默降级成“那就不定时了”。
|
|
27
|
+
|
|
28
|
+
如果 DEAP 只扮演身份与感知平面(不提供运行位置),那么它对驱动的贡献是**人设时间点的事件**(待办、日程到点)这一类,而常驻节律仍由实际承载运行位置的那个平台提供——两者不能互相替代。
|
|
29
|
+
|
|
30
|
+
## 开放时要做什么
|
|
31
|
+
|
|
32
|
+
平台开放时,在本文说明各技能用途,并把 `src/agent-platform.ts` 注册表里 `deap` 的状态改为 `supported`、补齐 `skills` 与 `commands`。在那之前,任何声称 DEAP 已可部署的说法都与 CLI 的实际行为冲突。
|
|
@@ -13,6 +13,31 @@ Multica 是钉钉 FDE fork 的托管 Agent 平台:把一个 dingtalk-agent 数
|
|
|
13
13
|
|
|
14
14
|
供给 workspace/runtime/agent → `dta deploy` 原样发布人类可读 Definition,并将 Basic + Role Skills 作为一级能力精确挂载 → 独立 Issue load smoke → 绑定钉钉机器人(见下)→ `chat-send --wait` 或 DWS 对话验收 → `task-trace` 观测轨迹。部署哈希和 Skill 清单只存在于 plan/Receipt,不进入 Agent System Prompt。
|
|
15
15
|
|
|
16
|
+
## 驱动能力:这个平台能提供什么节律
|
|
17
|
+
|
|
18
|
+
装配侧的节律声明(见 core 技能 `dingtalk-agent-compose` 的 `references/drive-and-schedules.md`)到这里被兑现。Multica 的实现是 **autopilot**:
|
|
19
|
+
|
|
20
|
+
| 装配侧概念 | Multica 实现 | 命令 |
|
|
21
|
+
|---|---|---|
|
|
22
|
+
| 常驻节律 | autopilot + `kind: schedule` trigger | `autopilot-create --cron "<5 段>" --timezone <IANA>` |
|
|
23
|
+
| 不产出工单的纯唤醒 | `--mode run_only` | 同上 |
|
|
24
|
+
| 每拍留一条工单 | `--mode create_issue`(标题模板支持 `{{date}}`) | 同上 |
|
|
25
|
+
| 手动补一拍 | — | `autopilot-trigger --autopilot <uuid>` |
|
|
26
|
+
| 停用/恢复 | `status: paused / active` | `autopilot-set-status` |
|
|
27
|
+
| 回读与审计 | — | `autopilot-list`、`autopilot-get`、`autopilot-runs` |
|
|
28
|
+
|
|
29
|
+
**Agent 自主排程**:平台 API 支持,但 dta 不默认授予——Agent 侧的合同是「不自建定时器、不自改节律」。要开放必须由 operator 显式决定,并保证节律仍可在 `autopilot-list` 中被看见和改掉。
|
|
30
|
+
|
|
31
|
+
平台语义里有三条会直接影响正确性,装配时必须按它们设计判据:
|
|
32
|
+
|
|
33
|
+
- **cron 是标准 5 段**(无秒、无 `@daily`);时区是 IANA,API 默认 UTC,`multica_ext.py` 默认 `Asia/Shanghai`——**显式传 `--timezone`,不要依赖默认**。
|
|
34
|
+
- **run 幂等按 `(trigger, 计划时刻)`;漏掉的 fire 会塌缩成最近一次,迟到超过 5 分钟直接跳过。** 所以定点 cron 只用来开窗,不能用来保证「某时刻必须发生」——完成判据必须逾期后持续为真。
|
|
35
|
+
- **多条节律不要落在同一分钟。** 外发类的留痕写在动作之后、没有锁,并发唤醒会把同一条消息发两遍给第三方。
|
|
36
|
+
|
|
37
|
+
`autopilot-create` 的 stdout **带一行非 JSON 前缀**(`scheduled: <cron> ..., next run ...`)。直接 `json.load(stdout)` 会抛异常,让人误判「没建成」而**重复创建**——重复的节律就是重复的外发。建完一律用 `autopilot-list` / `autopilot-get` 独立回读条数、cron、时区、提示词、启用状态和 `next_run_at`,不要相信创建响应。
|
|
38
|
+
|
|
39
|
+
`multica_ext.py` **没有** `autopilot-delete`;误建的先 `autopilot-set-status --status paused` 止血,再按需 `DELETE /api/autopilots/{id}`(需带 `X-Workspace-Id` 头,否则 400)。
|
|
40
|
+
|
|
16
41
|
## 使用前的就绪要求
|
|
17
42
|
|
|
18
43
|
- multica CLI 已安装:`curl -fsSL https://raw.githubusercontent.com/multica-ai/multica/main/scripts/install.sh | bash`
|
|
@@ -3,7 +3,7 @@ name: dingtalk-agent-deploy-multica
|
|
|
3
3
|
description: 当开发者要把 dingtalk-agent Agent Project 部署、更新、检查、恢复或 retire 到 Multica Workspace,或把通过指定 Eval gate 的本地版本晋级、把脱敏反馈转成待评审 Eval candidate 时使用。只编排 dta 的稳定 deploy/promote/observe CLI,不直接调用 Multica 写命令,不创建 Trigger,不热改 Agent 本体或 Skill,也不替用户登录或持有凭据。
|
|
4
4
|
compatibility: Requires dingtalk-agent and an authenticated Multica CLI profile for live apply/status readback.
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.3.
|
|
6
|
+
version: "0.3.3"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# 部署 dingtalk-agent 到 Multica
|
|
@@ -54,7 +54,8 @@ create / update / noop / rollback / retire 动作
|
|
|
54
54
|
- 不直接执行 `multica agent|skill ...` 写命令绕过 `dta deploy`。
|
|
55
55
|
- 不把 `--yes` 当成登录、改 scope、新增权限或确认新 plan。
|
|
56
56
|
- 不因模型回复正确而跳过 task status、tool trace 和远端内容 hash。
|
|
57
|
-
- 不创建机器人、Webhook、Autopilot、定时器或其他事件 Trigger
|
|
57
|
+
- 不创建机器人、Webhook、Autopilot、定时器或其他事件 Trigger。**deploy 也不会修改或删除已有的**——节律是独立于交付的生产对象,重新部署不重置它、不停用它,也不会因为 Skill 改了就自动改作用域提示词。改节律走 ops 技能 `multica-external` 的 `autopilot-*`,由 operator 决定。
|
|
58
|
+
- 不因为部署成功就宣称这个数字员工"已经在自己干活了"。`deploy` 只保证本体与 Skill 到位;**没有 schedule 的 Agent 只会被 @ 唤醒**。交付一个需要常驻节律的员工时,必须单独确认 `autopilot-list` 里真有对应节律且 `status=active`,否则如实报告这是缺口。
|
|
58
59
|
- 不把 token、Secret、邮箱、Server URL、Agent instructions 或 Skill 正文写入提交的 Receipt/日志。
|
|
59
60
|
- 不把线上消息、生产原始数据或 Observation 直接写回 AGENTS.md、Prompt、Skill 或 Eval suite。
|
|
60
61
|
- 不把 `proposed` candidate 当成已评审、已发布或已证明有效。
|
|
@@ -134,6 +134,21 @@ but a poll-only client fully reconstructs any past run from `task-trace`.
|
|
|
134
134
|
|
|
135
135
|
### 5 — Schedule: cron automations (autopilot)
|
|
136
136
|
|
|
137
|
+
**Reconcile from the declared source of truth, don't hand-author.** An Agent
|
|
138
|
+
Project declares its rhythms in `dingtalk-agent.json#schedules` (version-controlled;
|
|
139
|
+
see the compose skill's `drive-and-schedules.md`). `dta schedule plan --workspace
|
|
140
|
+
<name> --json` maps them to this provider's autopilot ops. Your job is to reconcile
|
|
141
|
+
that desired state against live:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
dta schedule plan --workspace <name> --json # desired state, provider-mapped
|
|
145
|
+
python3 $PY autopilot-list # live; match declared↔live by title
|
|
146
|
+
# create only missing, update drifted, delete extra — autopilot-create is NOT
|
|
147
|
+
# idempotent, so ALWAYS list first; blind-creating duplicates → duplicate外发.
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Manual/ad-hoc autopilots use the same commands directly:
|
|
151
|
+
|
|
137
152
|
```bash
|
|
138
153
|
python3 $PY autopilot-create --title "每日巡检" --agent <uuid> \
|
|
139
154
|
--description "<the prompt for each run>" --cron "0 9 * * 1-5" --timezone Asia/Shanghai
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="520" viewBox="0 0 1200 520" role="img" aria-labelledby="title desc">
|
|
2
|
-
<title id="title">dingtalk-agent 从定义到交付的生命周期</title>
|
|
3
|
-
<desc id="desc">AGENTS.md、Basic Behavior 和 Role Skills 组成 Agent Project,经本地或云上 Harness 测试,通过 Gate 和 Receipt 后发布到 Managed Agent Platform,最终以数字员工账号或机器人身份交付。</desc>
|
|
4
|
-
<defs>
|
|
5
|
-
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
|
|
6
|
-
<stop offset="0" stop-color="#0a1020"/>
|
|
7
|
-
<stop offset="1" stop-color="#111a31"/>
|
|
8
|
-
</linearGradient>
|
|
9
|
-
<linearGradient id="accent" x1="0" y1="0" x2="1" y2="0">
|
|
10
|
-
<stop offset="0" stop-color="#39c6f4"/>
|
|
11
|
-
<stop offset="1" stop-color="#7777ff"/>
|
|
12
|
-
</linearGradient>
|
|
13
|
-
<filter id="shadow" x="-20%" y="-30%" width="140%" height="160%">
|
|
14
|
-
<feDropShadow dx="0" dy="8" stdDeviation="12" flood-color="#020617" flood-opacity=".34"/>
|
|
15
|
-
</filter>
|
|
16
|
-
<style>
|
|
17
|
-
.eyebrow { font: 600 13px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; letter-spacing: 1.6px; fill: #7dd3fc; }
|
|
18
|
-
.title { font: 700 22px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #f8fafc; }
|
|
19
|
-
.body { font: 500 15px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #cbd5e1; }
|
|
20
|
-
.small { font: 500 13px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #94a3b8; }
|
|
21
|
-
.chip { font: 600 12px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #dbeafe; }
|
|
22
|
-
.number { font: 700 14px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #08111f; }
|
|
23
|
-
</style>
|
|
24
|
-
</defs>
|
|
25
|
-
|
|
26
|
-
<rect width="1200" height="520" rx="28" fill="url(#bg)"/>
|
|
27
|
-
<path d="M52 90H1148" stroke="#23304a"/>
|
|
28
|
-
<text x="52" y="55" class="eyebrow">ONE AGENT PROJECT · ONE VERIFIABLE CONTRACT</text>
|
|
29
|
-
<text x="52" y="82" class="title">同一份定义,完成创建、测试、发布和交付</text>
|
|
30
|
-
|
|
31
|
-
<!-- Step 1 -->
|
|
32
|
-
<g filter="url(#shadow)">
|
|
33
|
-
<rect x="52" y="132" width="272" height="232" rx="22" fill="#111c33" stroke="#2b3b59"/>
|
|
34
|
-
<circle cx="86" cy="168" r="16" fill="#67e8f9"/>
|
|
35
|
-
<text x="86" y="173" text-anchor="middle" class="number">1</text>
|
|
36
|
-
<text x="112" y="175" class="title">定义 Agent</text>
|
|
37
|
-
<rect x="76" y="208" width="224" height="38" rx="9" fill="#172643"/>
|
|
38
|
-
<text x="92" y="232" class="body">AGENTS.md</text>
|
|
39
|
-
<rect x="76" y="256" width="224" height="38" rx="9" fill="#172643"/>
|
|
40
|
-
<text x="92" y="280" class="body">Basic Behavior</text>
|
|
41
|
-
<rect x="76" y="304" width="224" height="38" rx="9" fill="#172643"/>
|
|
42
|
-
<text x="92" y="328" class="body">Role Skills</text>
|
|
43
|
-
</g>
|
|
44
|
-
|
|
45
|
-
<!-- Arrow 1 -->
|
|
46
|
-
<path d="M340 248H386" stroke="url(#accent)" stroke-width="3" stroke-linecap="round"/>
|
|
47
|
-
<path d="m378 240 10 8-10 8" fill="none" stroke="#7777ff" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
|
|
48
|
-
|
|
49
|
-
<!-- Step 2 -->
|
|
50
|
-
<g filter="url(#shadow)">
|
|
51
|
-
<rect x="404" y="132" width="292" height="232" rx="22" fill="#111c33" stroke="#2b3b59"/>
|
|
52
|
-
<circle cx="438" cy="168" r="16" fill="#67e8f9"/>
|
|
53
|
-
<text x="438" y="173" text-anchor="middle" class="number">2</text>
|
|
54
|
-
<text x="464" y="175" class="title">Harness 测试</text>
|
|
55
|
-
<text x="428" y="219" class="body">加载 · 隔离 · 执行 · 回读</text>
|
|
56
|
-
<rect x="428" y="246" width="112" height="30" rx="15" fill="#17314b" stroke="#275779"/>
|
|
57
|
-
<text x="484" y="266" text-anchor="middle" class="chip">本地 Runtime</text>
|
|
58
|
-
<rect x="552" y="246" width="120" height="30" rx="15" fill="#2a254f" stroke="#4f46a5"/>
|
|
59
|
-
<text x="612" y="266" text-anchor="middle" class="chip">云上 Runtime</text>
|
|
60
|
-
<path d="M428 304H672" stroke="#263956"/>
|
|
61
|
-
<circle cx="440" cy="329" r="7" fill="#4ade80"/>
|
|
62
|
-
<text x="456" y="334" class="small">Gate 通过,Receipt 可核验</text>
|
|
63
|
-
</g>
|
|
64
|
-
|
|
65
|
-
<!-- Arrow 2 -->
|
|
66
|
-
<path d="M712 248H758" stroke="url(#accent)" stroke-width="3" stroke-linecap="round"/>
|
|
67
|
-
<path d="m750 240 10 8-10 8" fill="none" stroke="#7777ff" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
|
|
68
|
-
|
|
69
|
-
<!-- Step 3 -->
|
|
70
|
-
<g filter="url(#shadow)">
|
|
71
|
-
<rect x="776" y="132" width="228" height="232" rx="22" fill="#111c33" stroke="#2b3b59"/>
|
|
72
|
-
<circle cx="810" cy="168" r="16" fill="#67e8f9"/>
|
|
73
|
-
<text x="810" y="173" text-anchor="middle" class="number">3</text>
|
|
74
|
-
<text x="836" y="175" class="title">发布到平台</text>
|
|
75
|
-
<text x="800" y="219" class="body">Managed Agent Platform</text>
|
|
76
|
-
<rect x="800" y="246" width="180" height="38" rx="9" fill="#172643"/>
|
|
77
|
-
<text x="890" y="270" text-anchor="middle" class="body">Multica · 已支持</text>
|
|
78
|
-
<rect x="800" y="294" width="180" height="38" rx="9" fill="#172643"/>
|
|
79
|
-
<text x="890" y="318" text-anchor="middle" class="body">更多 Adapter</text>
|
|
80
|
-
</g>
|
|
81
|
-
|
|
82
|
-
<!-- Delivery branches -->
|
|
83
|
-
<path d="M1004 220H1030Q1048 220 1048 202V182Q1048 164 1066 164H1080" fill="none" stroke="#586985" stroke-width="2"/>
|
|
84
|
-
<path d="M1004 276H1030Q1048 276 1048 294V314Q1048 332 1066 332H1080" fill="none" stroke="#586985" stroke-width="2"/>
|
|
85
|
-
<g filter="url(#shadow)">
|
|
86
|
-
<rect x="1080" y="126" width="82" height="112" rx="18" fill="#14213b" stroke="#38678b"/>
|
|
87
|
-
<circle cx="1121" cy="159" r="13" fill="#7dd3fc"/>
|
|
88
|
-
<path d="M1099 200c2-19 10-28 22-28s20 9 22 28" fill="#7dd3fc" opacity=".9"/>
|
|
89
|
-
<text x="1121" y="223" text-anchor="middle" class="small">数字员工</text>
|
|
90
|
-
</g>
|
|
91
|
-
<g filter="url(#shadow)">
|
|
92
|
-
<rect x="1080" y="276" width="82" height="112" rx="18" fill="#14213b" stroke="#554fb0"/>
|
|
93
|
-
<rect x="1100" y="309" width="42" height="34" rx="10" fill="#a5b4fc"/>
|
|
94
|
-
<circle cx="1112" cy="325" r="4" fill="#14213b"/>
|
|
95
|
-
<circle cx="1130" cy="325" r="4" fill="#14213b"/>
|
|
96
|
-
<path d="M1121 298v11M1115 298h12" stroke="#a5b4fc" stroke-width="4" stroke-linecap="round"/>
|
|
97
|
-
<text x="1121" y="373" text-anchor="middle" class="small">机器人</text>
|
|
98
|
-
</g>
|
|
99
|
-
|
|
100
|
-
<text x="52" y="432" class="body">继承不靠自述:Definition / Skill hash、运行轨迹、平台回读与 Receipt 共同证明。</text>
|
|
101
|
-
<rect x="52" y="458" width="1096" height="1" fill="#23304a"/>
|
|
102
|
-
<text x="52" y="491" class="small">身份、目标、权限、预算和副作用始终由可信宿主与 Gate 固定。</text>
|
|
103
|
-
</svg>
|