@xdxer/dingtalk-agent 0.1.5-beta.2 → 0.1.5-beta.4

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.
Files changed (72) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.en.md +92 -63
  3. package/README.md +92 -63
  4. package/dist/bin/dingtalk-agent.js +142 -15
  5. package/dist/bin/dingtalk-agent.js.map +1 -1
  6. package/dist/src/agent-audit.js +69 -55
  7. package/dist/src/agent-audit.js.map +1 -1
  8. package/dist/src/agent-enhance.js +49 -30
  9. package/dist/src/agent-enhance.js.map +1 -1
  10. package/dist/src/agent-platform.js +1 -0
  11. package/dist/src/agent-platform.js.map +1 -1
  12. package/dist/src/bootstrap.js +6 -2
  13. package/dist/src/bootstrap.js.map +1 -1
  14. package/dist/src/development-workspace.js +108 -18
  15. package/dist/src/development-workspace.js.map +1 -1
  16. package/dist/src/multica-deploy.js +128 -18
  17. package/dist/src/multica-deploy.js.map +1 -1
  18. package/dist/src/multica-provider.js +157 -2
  19. package/dist/src/multica-provider.js.map +1 -1
  20. package/dist/src/opencode-provider.js +17 -5
  21. package/dist/src/opencode-provider.js.map +1 -1
  22. package/dist/src/schedule-plan.js +105 -0
  23. package/dist/src/schedule-plan.js.map +1 -0
  24. package/dist/src/skills.js +2 -0
  25. package/dist/src/skills.js.map +1 -1
  26. package/dist/src/workspace.js +11 -6
  27. package/dist/src/workspace.js.map +1 -1
  28. package/docs/ARCHITECTURE.md +142 -24
  29. package/docs/INSTALLATION.md +1 -1
  30. package/docs/PRIOR-ART.md +4 -0
  31. package/docs/SELF-TEST.md +1 -1
  32. package/docs/architecture/agent-platform-connection-layer.svg +120 -0
  33. package/docs/architecture/digital-employee-composition.svg +92 -0
  34. package/docs/architecture/dingtalk-agent-architecture.svg +125 -0
  35. package/docs/assets/digital-employee-at-work.svg +77 -0
  36. package/docs/schemas/multica-workspace-run.schema.json +150 -33
  37. package/docs/schemas/project.schema.json +27 -0
  38. package/docs/schemas/workspace-scaffold.schema.json +37 -0
  39. package/examples/agents/README.md +9 -7
  40. package/examples/agents/fde-coach/AGENTS.md +2 -34
  41. package/examples/agents/fde-coach/agent/AGENTS.md +35 -0
  42. package/examples/agents/fde-coach/agent.bindings.json +10 -0
  43. package/examples/agents/release-manager/AGENTS.md +2 -34
  44. package/examples/agents/release-manager/agent/AGENTS.md +35 -0
  45. package/examples/agents/release-manager/agent.bindings.json +10 -0
  46. package/lab/project-workspace/fake-multica-provider.mjs +43 -8
  47. package/lab/project-workspace/opencode-provider-suite.json +1 -1
  48. package/lab/robot-eval/suite.json +1 -1
  49. package/package.json +2 -2
  50. package/skills/core/dingtalk-agent-compose/SKILL.md +25 -18
  51. package/skills/core/dingtalk-agent-compose/assets/AGENTS.template.md +1 -1
  52. package/skills/core/dingtalk-agent-compose/assets/REPOSITORY.template.md +10 -0
  53. package/skills/core/dingtalk-agent-compose/assets/agent.bindings.dingtalk-doc.template.json +2 -2
  54. package/skills/core/dingtalk-agent-compose/assets/agent.bindings.local.template.json +2 -2
  55. package/skills/core/dingtalk-agent-compose/assets/hosts/opencode/opencode.template.json +2 -1
  56. package/skills/core/dingtalk-agent-compose/evals/evals.json +1 -1
  57. package/skills/core/dingtalk-agent-compose/references/agent-definition-contract.md +6 -6
  58. package/skills/core/dingtalk-agent-compose/references/drive-and-schedules.md +124 -0
  59. package/skills/core/dingtalk-agent-compose/references/host-loading-contract.md +10 -12
  60. package/skills/core/dingtalk-agent-compose/references/hosts/claude-code.md +13 -12
  61. package/skills/core/dingtalk-agent-compose/references/hosts/opencode.md +13 -12
  62. package/skills/core/dingtalk-basic-behavior/SKILL.md +11 -7
  63. package/skills/core/dingtalk-basic-behavior/references/event-to-behavior.md +15 -1
  64. package/skills/core/dingtalk-basic-behavior/references/perception-and-gates.md +5 -0
  65. package/skills/core/dingtalk-basic-behavior/references/risk-authority-and-privacy.md +12 -0
  66. package/skills/platforms/deap/PLATFORM.md +30 -1
  67. package/skills/platforms/multica-dingtalk/PLATFORM.md +25 -0
  68. package/skills/platforms/multica-dingtalk/dingtalk-agent-deploy-multica/SKILL.md +3 -2
  69. package/skills/platforms/multica-dingtalk/multica-external/SKILL.md +15 -0
  70. package/docs/assets/agent-delivery-lifecycle.svg +0 -103
  71. /package/examples/agents/fde-coach/{skills → agent/skills}/fde-coach/SKILL.md +0 -0
  72. /package/examples/agents/release-manager/{skills → agent/skills}/release-manager/SKILL.md +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../src/workspace.ts"],"names":[],"mappings":"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","sourcesContent":["// Agent Workspace:一个物理目录对应一个稳定 Context/Field。\n// 人和模型读取 Markdown;机器控制状态仍留在宿主私有 JSON 中。\n\nimport {\n existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, writeFileSync,\n} from 'node:fs'\nimport { basename, dirname, join, relative, resolve } from 'node:path'\nimport { digest } from './events.js'\nimport * as dws from './dws.js'\n\nexport const WORKSPACE_FILE = '.dingtalk-agent/workspace.json'\n\nexport interface WorkspaceSpec {\n $schema: 'dingtalk-agent/workspace@1'\n id: string\n contextId: string\n fieldId: string\n dws: { profile: string; expectedUserId: string }\n skills: string[]\n mounts: Record<'profile' | 'memory' | 'knowledge' | 'skills', string>\n}\n\nexport interface WorkspaceInitOptions {\n contextId?: string\n id?: string\n memory?: string\n knowledge?: string\n}\n\nexport interface MountSnapshot {\n slot: string\n provider: 'local-md' | 'local-dir' | 'dingtalk-doc'\n source: string\n snapshotPath: string\n hash: string\n}\n\nexport function workspacePath(root: string): string {\n return join(root, WORKSPACE_FILE)\n}\n\nexport function ensureWorkspace(\n root: string,\n options: WorkspaceInitOptions = {},\n): WorkspaceSpec {\n const path = workspacePath(root)\n if (existsSync(path)) {\n const current = loadWorkspace(root)\n if (options.contextId && options.contextId !== current.contextId) {\n throw new Error(\n `当前目录已绑定 contextId=${current.contextId};一个物理 Workspace 不能重新绑定为 ${options.contextId}`,\n )\n }\n return current\n }\n\n const contextId = clean(options.contextId || basename(resolve(root)) || 'default')\n const id = clean(options.id || contextId)\n const spec: WorkspaceSpec = {\n $schema: 'dingtalk-agent/workspace@1',\n id,\n contextId,\n fieldId: 'default',\n dws: { profile: '', expectedUserId: '' },\n // 用 Skill name 声明,不把 Workspace 绑死到某个物理安装目录。\n // Resolver 依次查 Workspace override、全局安装和 npm 内置版本。\n skills: ['dingtalk-basic-behavior', ...discoverLocalSkillNames(root)],\n mounts: {\n profile: existsSync(join(root, 'AGENTS.md'))\n ? 'local-md:AGENTS.md' : 'local-md:WORKSPACE.md',\n memory: options.memory || 'local-md:MEMORY.md',\n knowledge: options.knowledge || 'local-md:knowledge/INDEX.md',\n skills: 'local-dir:skills',\n },\n }\n\n mkdirSync(dirname(path), { recursive: true })\n writeFileSync(path, JSON.stringify(spec, null, 2) + '\\n', { flag: 'wx' })\n writeDefaultMarkdown(root, spec)\n for (const dir of ['.dingtalk-agent/cache', '.dingtalk-agent/pending']) {\n mkdirSync(join(root, dir), { recursive: true })\n }\n return spec\n}\n\nexport function loadWorkspace(root: string): WorkspaceSpec {\n const path = workspacePath(root)\n if (!existsSync(path)) {\n throw new Error(\n '缺少 .dingtalk-agent/workspace.json;只有 Prepared Run runtime 才需要 `dingtalk-agent init`。' +\n '普通 Agent Session 请使用全局 Skill,按需运行 `dingtalk-agent bootstrap`。',\n )\n }\n let value: unknown\n try { value = JSON.parse(readFileSync(path, 'utf8')) }\n catch (error) { throw new Error(`Workspace manifest 不是合法 JSON: ${error.message}`) }\n return validateWorkspace(value)\n}\n\nexport function resolveContextId(spec: WorkspaceSpec, supplied = ''): string {\n const contextId = clean(supplied || spec.contextId)\n if (contextId !== spec.contextId) {\n throw new Error(\n `contextId=${contextId} 不属于当前 Workspace(期望 ${spec.contextId});请由上游选择正确工作目录`,\n )\n }\n return contextId\n}\n\n/**\n * Provider 只负责把语义内容冻结成本地 Markdown;锁、Wait、去重和 Receipt 不走这里。\n * dingtalk-doc 只读显式 node,不搜索、不创建、不覆盖。\n */\nexport function snapshotWorkspaceMounts(\n root: string,\n runPath: string,\n spec: WorkspaceSpec,\n): MountSnapshot[] {\n const destination = join(runPath, 'context', 'mounts')\n mkdirSync(destination, { recursive: true })\n const snapshots: MountSnapshot[] = []\n\n for (const [slot, uri] of Object.entries(spec.mounts)) {\n const mount = parseMount(uri)\n if (mount.provider === 'local-dir') {\n // skills 是逻辑槽:实际内容由 Skill resolver 从 Workspace override、\n // 全局目录或 npm 内置版本解析并在 Session 创建时冻结。\n if (slot !== 'skills') safeLocalPath(root, mount.ref)\n snapshots.push({\n slot, provider: mount.provider, source: uri,\n // P0 的目录型 mount 只有 skills;真实内容由 Session 绑定并冻结到这里。\n snapshotPath: slot === 'skills' ? 'context/skills' : '', hash: '',\n })\n continue\n }\n\n const markdown = mount.provider === 'local-md'\n ? readFileSync(safeLocalPath(root, mount.ref), 'utf8')\n : String(dws.readDoc(mount.ref, spec.dws.profile))\n const path = join(destination, `${safeName(slot)}.md`)\n writeFileSync(path, markdown.endsWith('\\n') ? markdown : markdown + '\\n')\n snapshots.push({\n slot,\n provider: mount.provider,\n source: uri,\n snapshotPath: relative(runPath, path).split('\\\\').join('/'),\n hash: digest(markdown),\n })\n }\n\n writeFileSync(\n join(destination, 'manifest.json'),\n JSON.stringify({ $schema: 'dingtalk-agent/mount-snapshot@1', entries: snapshots }, null, 2) + '\\n',\n )\n return snapshots\n}\n\nfunction validateWorkspace(value: unknown): WorkspaceSpec {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('Workspace manifest 必须是 JSON object')\n }\n const input = value as Record<string, any>\n if (input.$schema !== 'dingtalk-agent/workspace@1') {\n throw new Error('Workspace manifest 缺少 dingtalk-agent/workspace@1 schema')\n }\n for (const key of ['id', 'contextId', 'fieldId']) {\n if (!clean(input[key])) throw new Error(`Workspace manifest 缺少 ${key}`)\n }\n if (!Array.isArray(input.skills) || input.skills.some((item: unknown) => typeof item !== 'string')) {\n throw new Error('Workspace skills 必须是 string[]')\n }\n if (!input.dws || typeof input.dws.profile !== 'string' ||\n typeof input.dws.expectedUserId !== 'string') {\n throw new Error('Workspace dws 必须包含 string profile / expectedUserId')\n }\n const requiredSlots = ['profile', 'memory', 'knowledge', 'skills']\n if (!input.mounts || requiredSlots.some((slot) => typeof input.mounts[slot] !== 'string')) {\n throw new Error(`Workspace mounts 必须包含 ${requiredSlots.join(' / ')}`)\n }\n for (const uri of Object.values(input.mounts)) parseMount(String(uri))\n return input as WorkspaceSpec\n}\n\nfunction parseMount(uri: string): {\n provider: 'local-md' | 'local-dir' | 'dingtalk-doc'\n ref: string\n} {\n const separator = uri.indexOf(':')\n const provider = uri.slice(0, separator)\n const ref = separator >= 0 ? uri.slice(separator + 1).trim() : ''\n if (!['local-md', 'local-dir', 'dingtalk-doc'].includes(provider) || !ref) {\n throw new Error(`不支持的 Workspace mount: ${uri}`)\n }\n return { provider: provider as 'local-md' | 'local-dir' | 'dingtalk-doc', ref }\n}\n\nfunction safeLocalPath(root: string, ref: string): string {\n const rootReal = realpathSync(resolve(root))\n const candidate = resolve(rootReal, ref)\n if (!existsSync(candidate)) throw new Error(`Workspace mount 不存在: ${ref}`)\n const actual = realpathSync(candidate)\n const rel = relative(rootReal, actual)\n if (rel === '..' || rel.startsWith(`..${process.platform === 'win32' ? '\\\\' : '/'}`)) {\n throw new Error(`Workspace local mount 必须位于当前目录内: ${ref}`)\n }\n return actual\n}\n\nfunction writeDefaultMarkdown(root: string, spec: WorkspaceSpec): void {\n const files: Array<[string, string]> = [\n ['WORKSPACE.md', `# Agent Workspace\\n\\n- Context ID: ${spec.contextId}\\n- Workspace: ${spec.id}\\n- Field: ${spec.fieldId}\\n\\n这里定义稳定的身份、职责、协作边界和内容挂载。\\n`],\n ['MEMORY.md', '# Long-term Memory\\n\\n只保存经过筛选、带来源的长期记忆。当前事项放在 Session memory。\\n'],\n ['knowledge/INDEX.md', '# Knowledge Index\\n\\n按需列出本 Workspace 可用的知识入口。\\n'],\n ]\n for (const [rel, content] of files) {\n const path = join(root, rel)\n mkdirSync(dirname(path), { recursive: true })\n if (!existsSync(path)) writeFileSync(path, content)\n }\n}\n\nfunction safeName(value: string): string {\n return value.replace(/[^a-zA-Z0-9._-]+/g, '-')\n}\n\nfunction discoverLocalSkillNames(root: string): string[] {\n const directory = join(root, 'skills')\n if (!existsSync(directory) || !lstatSync(directory).isDirectory()) return []\n const names: string[] = []\n for (const entry of readdirSync(directory, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue\n const path = join(directory, entry.name, 'SKILL.md')\n if (!existsSync(path)) continue\n const markdown = readFileSync(path, 'utf8')\n const frontmatter = markdown.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---/)?.[1] || ''\n const name = frontmatter.match(/^name:\\s*['\"]?([^'\"\\r\\n]+)['\"]?\\s*$/m)?.[1]?.trim() || ''\n if (!name) throw new Error(`本地 Role Skill 缺少 frontmatter name: ${path}`)\n if (name !== entry.name) {\n throw new Error(`本地 Role Skill 目录名与 name 不一致: ${entry.name} != ${name}`)\n }\n if (name !== 'dingtalk-basic-behavior') names.push(name)\n }\n return [...new Set(names)].sort()\n}\n\nfunction clean(value: unknown): string {\n return typeof value === 'string' ? value.trim() : ''\n}\n"]}
1
+ {"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../src/workspace.ts"],"names":[],"mappings":"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","sourcesContent":["// Agent Workspace:一个物理目录对应一个稳定 Context/Field。\n// 人和模型读取 Markdown;机器控制状态仍留在宿主私有 JSON 中。\n\nimport {\n existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, writeFileSync,\n} from 'node:fs'\nimport { basename, dirname, join, relative, resolve } from 'node:path'\nimport { digest } from './events.js'\nimport * as dws from './dws.js'\n\nexport const WORKSPACE_FILE = '.dingtalk-agent/workspace.json'\n\nexport interface WorkspaceSpec {\n $schema: 'dingtalk-agent/workspace@1'\n id: string\n contextId: string\n fieldId: string\n dws: { profile: string; expectedUserId: string }\n skills: string[]\n mounts: Record<'profile' | 'memory' | 'knowledge' | 'skills', string>\n}\n\nexport interface WorkspaceInitOptions {\n contextId?: string\n id?: string\n memory?: string\n knowledge?: string\n}\n\nexport interface MountSnapshot {\n slot: string\n provider: 'local-md' | 'local-dir' | 'dingtalk-doc'\n source: string\n snapshotPath: string\n hash: string\n}\n\nexport function workspacePath(root: string): string {\n return join(root, WORKSPACE_FILE)\n}\n\nexport function ensureWorkspace(\n root: string,\n options: WorkspaceInitOptions = {},\n): WorkspaceSpec {\n const path = workspacePath(root)\n if (existsSync(path)) {\n const current = loadWorkspace(root)\n if (options.contextId && options.contextId !== current.contextId) {\n throw new Error(\n `当前目录已绑定 contextId=${current.contextId};一个物理 Workspace 不能重新绑定为 ${options.contextId}`,\n )\n }\n return current\n }\n\n const contextId = clean(options.contextId || basename(resolve(root)) || 'default')\n const id = clean(options.id || contextId)\n const packagedDefinition = existsSync(join(root, 'agent', 'AGENTS.md'))\n const profileRef = packagedDefinition\n ? 'agent/AGENTS.md'\n : existsSync(join(root, 'AGENTS.md')) ? 'AGENTS.md' : 'WORKSPACE.md'\n const skillsRef = existsSync(join(root, 'agent', 'skills'))\n ? 'agent/skills' : 'skills'\n const spec: WorkspaceSpec = {\n $schema: 'dingtalk-agent/workspace@1',\n id,\n contextId,\n fieldId: 'default',\n dws: { profile: '', expectedUserId: '' },\n // 用 Skill name 声明,不把 Workspace 绑死到某个物理安装目录。\n // Resolver 依次查 Workspace override、全局安装和 npm 内置版本。\n skills: ['dingtalk-basic-behavior', ...discoverLocalSkillNames(root, skillsRef)],\n mounts: {\n profile: `local-md:${profileRef}`,\n memory: options.memory || 'local-md:MEMORY.md',\n knowledge: options.knowledge || 'local-md:knowledge/INDEX.md',\n skills: `local-dir:${skillsRef}`,\n },\n }\n\n mkdirSync(dirname(path), { recursive: true })\n writeFileSync(path, JSON.stringify(spec, null, 2) + '\\n', { flag: 'wx' })\n writeDefaultMarkdown(root, spec)\n for (const dir of ['.dingtalk-agent/cache', '.dingtalk-agent/pending']) {\n mkdirSync(join(root, dir), { recursive: true })\n }\n return spec\n}\n\nexport function loadWorkspace(root: string): WorkspaceSpec {\n const path = workspacePath(root)\n if (!existsSync(path)) {\n throw new Error(\n '缺少 .dingtalk-agent/workspace.json;只有 Prepared Run runtime 才需要 `dingtalk-agent init`。' +\n '普通 Agent Session 请使用全局 Skill,按需运行 `dingtalk-agent bootstrap`。',\n )\n }\n let value: unknown\n try { value = JSON.parse(readFileSync(path, 'utf8')) }\n catch (error) { throw new Error(`Workspace manifest 不是合法 JSON: ${error.message}`) }\n return validateWorkspace(value)\n}\n\nexport function resolveContextId(spec: WorkspaceSpec, supplied = ''): string {\n const contextId = clean(supplied || spec.contextId)\n if (contextId !== spec.contextId) {\n throw new Error(\n `contextId=${contextId} 不属于当前 Workspace(期望 ${spec.contextId});请由上游选择正确工作目录`,\n )\n }\n return contextId\n}\n\n/**\n * Provider 只负责把语义内容冻结成本地 Markdown;锁、Wait、去重和 Receipt 不走这里。\n * dingtalk-doc 只读显式 node,不搜索、不创建、不覆盖。\n */\nexport function snapshotWorkspaceMounts(\n root: string,\n runPath: string,\n spec: WorkspaceSpec,\n): MountSnapshot[] {\n const destination = join(runPath, 'context', 'mounts')\n mkdirSync(destination, { recursive: true })\n const snapshots: MountSnapshot[] = []\n\n for (const [slot, uri] of Object.entries(spec.mounts)) {\n const mount = parseMount(uri)\n if (mount.provider === 'local-dir') {\n // skills 是逻辑槽:实际内容由 Skill resolver 从 Workspace override、\n // 全局目录或 npm 内置版本解析并在 Session 创建时冻结。\n if (slot !== 'skills') safeLocalPath(root, mount.ref)\n snapshots.push({\n slot, provider: mount.provider, source: uri,\n // P0 的目录型 mount 只有 skills;真实内容由 Session 绑定并冻结到这里。\n snapshotPath: slot === 'skills' ? 'context/skills' : '', hash: '',\n })\n continue\n }\n\n const markdown = mount.provider === 'local-md'\n ? readFileSync(safeLocalPath(root, mount.ref), 'utf8')\n : String(dws.readDoc(mount.ref, spec.dws.profile))\n const path = join(destination, `${safeName(slot)}.md`)\n writeFileSync(path, markdown.endsWith('\\n') ? markdown : markdown + '\\n')\n snapshots.push({\n slot,\n provider: mount.provider,\n source: uri,\n snapshotPath: relative(runPath, path).split('\\\\').join('/'),\n hash: digest(markdown),\n })\n }\n\n writeFileSync(\n join(destination, 'manifest.json'),\n JSON.stringify({ $schema: 'dingtalk-agent/mount-snapshot@1', entries: snapshots }, null, 2) + '\\n',\n )\n return snapshots\n}\n\nfunction validateWorkspace(value: unknown): WorkspaceSpec {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('Workspace manifest 必须是 JSON object')\n }\n const input = value as Record<string, any>\n if (input.$schema !== 'dingtalk-agent/workspace@1') {\n throw new Error('Workspace manifest 缺少 dingtalk-agent/workspace@1 schema')\n }\n for (const key of ['id', 'contextId', 'fieldId']) {\n if (!clean(input[key])) throw new Error(`Workspace manifest 缺少 ${key}`)\n }\n if (!Array.isArray(input.skills) || input.skills.some((item: unknown) => typeof item !== 'string')) {\n throw new Error('Workspace skills 必须是 string[]')\n }\n if (!input.dws || typeof input.dws.profile !== 'string' ||\n typeof input.dws.expectedUserId !== 'string') {\n throw new Error('Workspace dws 必须包含 string profile / expectedUserId')\n }\n const requiredSlots = ['profile', 'memory', 'knowledge', 'skills']\n if (!input.mounts || requiredSlots.some((slot) => typeof input.mounts[slot] !== 'string')) {\n throw new Error(`Workspace mounts 必须包含 ${requiredSlots.join(' / ')}`)\n }\n for (const uri of Object.values(input.mounts)) parseMount(String(uri))\n return input as WorkspaceSpec\n}\n\nfunction parseMount(uri: string): {\n provider: 'local-md' | 'local-dir' | 'dingtalk-doc'\n ref: string\n} {\n const separator = uri.indexOf(':')\n const provider = uri.slice(0, separator)\n const ref = separator >= 0 ? uri.slice(separator + 1).trim() : ''\n if (!['local-md', 'local-dir', 'dingtalk-doc'].includes(provider) || !ref) {\n throw new Error(`不支持的 Workspace mount: ${uri}`)\n }\n return { provider: provider as 'local-md' | 'local-dir' | 'dingtalk-doc', ref }\n}\n\nfunction safeLocalPath(root: string, ref: string): string {\n const rootReal = realpathSync(resolve(root))\n const candidate = resolve(rootReal, ref)\n if (!existsSync(candidate)) throw new Error(`Workspace mount 不存在: ${ref}`)\n const actual = realpathSync(candidate)\n const rel = relative(rootReal, actual)\n if (rel === '..' || rel.startsWith(`..${process.platform === 'win32' ? '\\\\' : '/'}`)) {\n throw new Error(`Workspace local mount 必须位于当前目录内: ${ref}`)\n }\n return actual\n}\n\nfunction writeDefaultMarkdown(root: string, spec: WorkspaceSpec): void {\n const files: Array<[string, string]> = [\n ['WORKSPACE.md', `# Agent Workspace\\n\\n- Context ID: ${spec.contextId}\\n- Workspace: ${spec.id}\\n- Field: ${spec.fieldId}\\n\\n这里定义稳定的身份、职责、协作边界和内容挂载。\\n`],\n ['MEMORY.md', '# Long-term Memory\\n\\n只保存经过筛选、带来源的长期记忆。当前事项放在 Session memory。\\n'],\n ['knowledge/INDEX.md', '# Knowledge Index\\n\\n按需列出本 Workspace 可用的知识入口。\\n'],\n ]\n for (const [rel, content] of files) {\n const path = join(root, rel)\n mkdirSync(dirname(path), { recursive: true })\n if (!existsSync(path)) writeFileSync(path, content)\n }\n}\n\nfunction safeName(value: string): string {\n return value.replace(/[^a-zA-Z0-9._-]+/g, '-')\n}\n\nfunction discoverLocalSkillNames(root: string, skillsRef: string): string[] {\n const directory = join(root, skillsRef)\n if (!existsSync(directory) || !lstatSync(directory).isDirectory()) return []\n const names: string[] = []\n for (const entry of readdirSync(directory, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue\n const path = join(directory, entry.name, 'SKILL.md')\n if (!existsSync(path)) continue\n const markdown = readFileSync(path, 'utf8')\n const frontmatter = markdown.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---/)?.[1] || ''\n const name = frontmatter.match(/^name:\\s*['\"]?([^'\"\\r\\n]+)['\"]?\\s*$/m)?.[1]?.trim() || ''\n if (!name) throw new Error(`本地 Role Skill 缺少 frontmatter name: ${path}`)\n if (name !== entry.name) {\n throw new Error(`本地 Role Skill 目录名与 name 不一致: ${entry.name} != ${name}`)\n }\n if (name !== 'dingtalk-basic-behavior') names.push(name)\n }\n return [...new Set(names)].sort()\n}\n\nfunction clean(value: unknown): string {\n return typeof value === 'string' ? value.trim() : ''\n}\n"]}
@@ -1,14 +1,18 @@
1
1
  # dingtalk-agent 架构
2
2
 
3
- 本文回答四个问题:**一个数字员工是什么**、**它由什么构成**、**它依赖什么**、**这个仓库分成哪几部分、各解决什么问题**。
3
+ 本文回答四个问题:**一个数字员工是什么**、**它由什么构成**、**每件事谁说了算**、**这个仓库分成哪几部分、各解决什么问题**。
4
4
 
5
5
  本文不写:安装与升级(见 [Installation](INSTALLATION.md))、评测方法与证据分层(见 [Self-test](SELF-TEST.md))、Agent 的行为协议(见 [Basic Behavior Skill](../skills/core/dingtalk-basic-behavior/SKILL.md))、发布历史(见 [CHANGELOG](../CHANGELOG.md))、进行中的工作(见 [roadmap](roadmap/))。
6
6
 
7
+ ![dingtalk-agent 架构总览:五个部件、五个权威,本仓库只拥有一个](architecture/dingtalk-agent-architecture.svg)
8
+
9
+ 上图是全貌,编号对应 §1 的五个部件:实心编号是本仓库拥有的,空心编号由外部签发或提供。下面逐层展开。
10
+
7
11
  ---
8
12
 
9
13
  ## 1. 什么是一个数字员工
10
14
 
11
- ![通用 Agent 行为内核拓扑](architecture/general-agent-kernel-topology.svg)
15
+ ![数字员工的五个部件与各自的权威](architecture/digital-employee-composition.svg)
12
16
 
13
17
  一个聊天机器人只需要把输入变成输出。一个数字员工要额外成立四件事:
14
18
 
@@ -17,49 +21,122 @@
17
21
  - **可核验的完成**:说"做完了"必须对应产物、Receipt 或独立回读,不能以回复正文自证;
18
22
  - **可丢弃的执行体**:沙箱、进程、模型可以随时换掉,事情还能接着做。
19
23
 
20
- 由此得到本项目的核心判断——**可替换的**是触发端、模型、沙箱和岗位能力;**不变的**是定义、上下文、状态、闸门和效果证据。全部设计取舍都服务于把后五项从宿主里独立出来。
24
+ **这四件事没有一件能由 Agent 自己提供——数字员工不等于 Agent。** 它是一个 Agent 装配上组织语境之后的结果:
25
+
26
+ ```text
27
+ 数字员工 = Agent 本体 ← 本仓库
28
+ + 组织身份与场域授权 ← 钉钉数字员工平台
29
+ + 感知通道(事件) ← 钉钉事件中心 / DWS
30
+ + 平台执行能力 ← DWS
31
+ + 运行位置 ← Managed Agent Platform / Agent Host
32
+ ```
33
+
34
+ 运行时上,本仓库只提供第一项;其余四项由外部提供,本仓库不实现也不替代,但必须逐一显式建模,否则边界会悄悄溜走(见 §3)。
35
+
36
+ > ⚠️ **这张等式回答的是「一个跑起来的数字员工由什么组成」,用途是界定依赖——它不是「本项目做什么」的答案。** 把两者混为一谈会严重低估本项目的范围。「本项目做什么」要换一个正交的视角看:**开发域**。
37
+
38
+ **开发域:把一个 Agent 变成钉钉数字员工,要走完六段——这六段本项目全管。**
39
+
40
+ | 段 | 本项目替开发者完成什么 |
41
+ |---|---|
42
+ | **① 本体与员工技能** | 一份可继承、可 hash、可验证的共享行为合同(响应资格、意图分级、授权模型、风险分级、证据阶梯、完成判定、记忆与遗忘),加本体与岗位骨架 |
43
+ | **② 身份获取与事件感知** | 把来路不明的原始事件归一成稳定合同,冻结回复目标与执行身份,按 Field 绑定权限与出口,补齐现场,并保证同一事件只产生一个 Run |
44
+ | **③ 托管平台部署** | 把手工搬运变成 plan → apply → 独立回读 → 加载烟测 → Receipt 的受控发布链,幂等、可回滚、可退役 |
45
+ | **④ 驱动它在钉钉里干活** | 四个动作原语 + Action Gate:副作用前冻结目标身份,副作用后强制平台回读,完成必须有物证 |
46
+ | **⑤ 评测设计** | L0–L4 证据分层方法学、四个 runner、多面证据硬门禁,以及「真实事故 → 可复跑场景」的沉淀路径 |
47
+ | **⑥ 观测与计量** | 目前**最薄的一段**:只有把线上人工观察安全灌回评测素材的受控通道;用量计量尚未实现(见 §8) |
48
+
49
+ 逐段的能力、边界与缺口见 [§8 开发生命周期](#8-开发生命周期从定义到观测)。一句话概括这两个视角的关系:**运行时的底座我们不造;但把 Agent 变成数字员工的这条生产线,从头到尾是我们的。**
50
+
51
+ 三类东西的可变性完全不同,必须分开对待:
52
+
53
+ | 类别 | 内容 | 本仓库的职责 |
54
+ |---|---|---|
55
+ | **外部签发** | 组织身份、场域授权、事件信封 | 冻结进 Session、全程审计,永不扩权 |
56
+ | **可替换** | 触发端、模型、沙箱、运行位置、岗位能力 | 只要求一份可验证的加载与执行合同 |
57
+ | **本仓库不变** | 定义、上下文、状态、闸门、效果证据 | 唯一拥有;全部设计取舍都服务于把它们从执行体里独立出来 |
58
+
59
+ 「外部签发」这一类最容易被漏掉:**身份既不可替换,也不由本仓库提供。**
21
60
 
22
61
  ## 2. 一个 Agent 由什么构成(模型 A)
23
62
 
24
- 三个模型互不重叠,各回答一个问题:**A 交付物由什么组成**、**B 运行时依赖谁**、**C 这个仓库自己分成哪几块**。「Skill 劝,CLI 拦,DWS 做」是贯穿三者的唯一职责口径(见 §4)。
63
+ 三个模型互不重叠,各回答一个问题:**A 交付物由什么组成**、**B 每件事谁说了算**、**C 这个仓库自己分成哪几块**。「Skill 劝,CLI 拦,DWS 做」是贯穿三者的唯一职责口径(见 §4)。
25
64
 
26
65
  | 部件 | 回答什么 | 落在哪 | 谁生成 / 谁校验 |
27
66
  |---|---|---|---|
28
- | **本体 Definition** | 我是谁、服务谁、岗位底线、做事范式、常犯错误 | `AGENTS.md` | `agent enhance` 生成骨架;`agent audit` 校验语义占位符是否已填 |
29
- | **公共行为** | 何时响应、如何追问、何时沉默、如何收口 | `dingtalk-basic-behavior` Skill | 内核内置;`agent audit --verify-load` 证明它真被加载 |
30
- | **岗位能力** | 某个岗位的方法、SOP、禁区、验收标准 | `skills/<role>/SKILL.md` | 开发者编写;`--require-skill` 校验存在与加载 |
67
+ | **本体 Definition** | 我是谁、服务谁、岗位底线、做事范式、常犯错误 | `agent/AGENTS.md` | `agent enhance` 生成骨架;`agent audit` 校验语义占位符是否已填 |
68
+ | **公共行为** | 何时响应、如何追问、何时沉默、如何收口 | `agent/skills/dingtalk-basic-behavior` | 内核内置;`agent audit --verify-load` 证明它真被加载 |
69
+ | **岗位能力** | 某个岗位的方法、SOP、禁区、验收标准 | `agent/skills/<role>/SKILL.md` | 开发者编写;`--require-skill` 校验存在与加载 |
31
70
  | **存储路由** | 长期内容与私有控制状态各自去哪 | `agent.bindings.json`(可选) | `bootstrap` 归一成 `agent-definition@1`;缺省时按宿主 context > 环境变量 > Workspace manifest > 目录约定依次解析 |
32
71
 
33
72
  这四项不是设计出来的分类,而是从 `agent-definition@1` 直接读出来的字段(`src/agent-definition.ts`)。一个 Agent 的最小目录形态:
34
73
 
35
74
  ```text
36
75
  my-agent/
37
- ├── AGENTS.md 本体:角色宪法 + Basic 继承锚点
76
+ ├── AGENTS.md 仓库 Coding Agent 开发约束,不发布
77
+ ├── agent/ managed platform 的唯一同步边界
78
+ │ ├── AGENTS.md 本体:角色宪法 + Basic 继承锚点
79
+ │ └── skills/ Basic 与 Role Skills 的唯一发布源
38
80
  ├── agent.bindings.json 存储路由与 DWS authority(可选,见下)
39
- ├── skills/<role>/SKILL.md 岗位能力的版本化来源
40
- ├── .agents/skills/ Host 可发现的 Skill 物化位置
41
81
  └── .dingtalk-agent/ 私有状态、证据与 Receipt(gitignored)
42
82
  ```
43
83
 
84
+ Host 原生发现目录不是发布源。OpenCode 的 `.agents/skills/`、Claude Code 的 `.claude/skills/` 等只在 dta 创建的隔离工作区临时物化并回收,不能与 `agent/skills/` 一起提交。已有代码仓库可在 `dingtalk-agent.json` 显式声明其它 `agent.definition` 与 `agent.skillsRoot`,不因升级 CLI 被强制迁移。
85
+
44
86
  "文件存在"不是继承证据。`agent audit --verify-load` 把真实加载结果绑定到 Definition/Skill hash、Host 与模型版本、隔离探针和原始 run/export;任何一项漂移,旧证据即失效。
45
87
 
46
- ## 3. 一个 Agent 依赖什么(模型 B)
88
+ ## 3. 每件事谁说了算(模型 B)
89
+
90
+ ![dingtalk-agent 在托管平台与钉钉之间的连接层位置](architecture/agent-platform-connection-layer.svg)
47
91
 
48
- 这四样本仓库都**不拥有**,但都必须显式建模,否则边界会悄悄溜走:
92
+ §1 的五个部件各有一个「谁说了算」。下表按权威归属重排,把本仓库拥有的那一项放在最后:其余四行本仓库只有约束——**写下来是为了让边界可检查,不是因为我们要做它们**:
49
93
 
50
- | 依赖 | 提供什么 | 本仓库的边界 |
94
+ | 这件事谁说了算 | 权威 | 本仓库的边界 |
51
95
  |---|---|---|
52
- | **Agent Host**(也叫 Harness) | 模型、工具循环、Skill 发现、Session 生命周期 | 不自己做 Host,只要求一份可验证的加载合同。Claude Code、Codex、OpenCode 都可以;OpenCode 是当前最完整的参考实现,不是运行前提 |
53
- | **DWS** | 钉钉全部产品能力 | 不复制 DWS 命令面,只在需要冻结事务边界时包一层。`src/dws.ts` 是全仓库唯一 spawn `dws` 的地方;实战缺陷见 [DWS Field Notes](DWS-FIELD-NOTES.md) |
54
- | **Managed Agent Platform** | Workspace、Runtime、Agent、Skill 挂载、身份绑定、执行轨迹 | 通过 registry + adapter 接入。Multica 已支持,DEAP Coming soon;不把尚未开放的平台宣称为已部署 |
55
- | **事件源** | 可信事件信封:谁、在哪、说了什么 | **本仓库不拥有触发器**(见下) |
96
+ | **组织身份、场域与权限** | 钉钉数字员工平台 | 不发证、不改写、不扩权;只把签发结果冻结进 Session 并全程审计 |
97
+ | **事件信封**(谁、在哪、说了什么) | 钉钉事件中心 / DWS | **不拥有触发器**(见下);只要求信封可信、可幂等 |
98
+ | **平台能力执行** | DWS | 不复制 DWS 命令面,只在需要冻结事务边界时包一层。`src/dws.ts` 是全仓库唯一 spawn `dws` 的地方;实战缺陷见 [DWS Field Notes](DWS-FIELD-NOTES.md) |
99
+ | **运行位置** | Managed Agent Platform / Agent Host | 不自己做 Host、不自建 Runtime;通过 registry + adapter 连接,只要求一份可验证的加载合同 |
100
+ | **本体、行为、状态与效果证据** | **本仓库 + Git** | 唯一拥有的一行 |
101
+
102
+ **运行位置既是可替换项,也是本项目的连接面。** 接入一个平台等于「**一个平台 Skill 包 + 注册表一条记录**」,方法学不进内核也不进 CLI(目录约定见 [skills/README](../skills/README.md))。当前 **Multica 已支持,DEAP 敬请期待**;「可扩展」指注册表与 adapter 合同可扩展,不表示尚未开放的平台已经可用——未开放平台的所有平台命令一律 fail-closed。各平台的最佳实践如何被观察和吸收,见 [Prior Art](PRIOR-ART.md)。
103
+
104
+ **DEAP 可能同时落在第一行和第四行。** 它在本项目里的主要角色是钉钉侧的身份与感知平面(第一行):签发身份、划定场域、送来事件、统一展示结果。它是否同时内建自己的 Agent 运行平台(第四行)尚待确认,注册表为此保留了 `deap` 条目。两个角色互不排斥:第一行的能力将被**消费**,第四行的能力和其它平台一样走 registry + adapter。**当前 DEAP 尚未接入**——第一行今天的身份来源是钉钉签发的数字员工账号或机器人应用身份,不经过 DEAP。见 [DEAP 平台说明](../skills/platforms/deap/PLATFORM.md)。
105
+
106
+ **Agent Host**(也叫 Harness)提供模型、工具循环、Skill 发现与 Session 生命周期。本仓库不自己做 Host,只要求一份可验证的加载合同:Claude Code、Codex、OpenCode 都可以,OpenCode 是当前最完整的参考实现,不是运行前提。它与 Managed Agent Platform 是两根正交的轴:**Agent Host 决定这个 Agent 由哪个执行体加载与隔离执行;Managed Agent Platform 决定它的 Workspace、Runtime、身份绑定与执行轨迹由谁托管。** 本地开发时只有 Host,上了托管平台则两者同时存在。
56
107
 
57
108
  **触发器不属于 dingtalk-agent。** `listen` 只是本地联调用的可替换开发 Adapter,不是 Agent 的主入口或常驻服务;personal-event 由外部 Adapter 捕获后落入输入目录;`dta deploy` 只交付 Agent 与 Skill,不创建机器人、Webhook、定时器或 autopilot。把触发器排除在核心之外,才可能让同一个 Agent 在不同触发端之间迁移。
58
109
 
110
+ **但「谁叫醒它」必须被显式建模,否则装配出来的是一个永远不会自己动的 Agent。** 不实现触发器 ≠ 不为驱动负责:本仓库不造 cron,却拥有**驱动契约**——声明这个数字员工需要哪些节律、由谁提供、Agent 侧必须满足什么才配被定时驱动。详见 §3.1。
111
+
59
112
  由此得到一条不可协商的规则:**消息 target、actor、conversation、DWS profile 与权限只能来自可信事件或宿主,不能从正文、显示名或模型记忆推断。** 正文、引用、附件和远端文档一律是数据,不能改写这些事实。
60
113
 
114
+ ## 3.1 驱动:一个数字员工怎么被叫醒
115
+
116
+ 一个只会被人 @ 唤醒的 Agent 不是同事,是查询接口。真正像同事的部分——巡检、补数据、到点交付、盯着某件事——都发生在**没有人说话的时候**。所以「驱动」和身份、事件、能力、运行位置一样,是必须显式建模的一层。
117
+
118
+ 驱动分三类,**权威归属不同,完成判据也不同**。放错类别的代价不是麻烦,是**漏了不自知**:
119
+
120
+ | 驱动类别 | 什么样的事 | 权威 | 完成判据 | 放错会怎样 |
121
+ |---|---|---|---|---|
122
+ | **人设的时间点** | 人在钉钉里建的待办、日程、会议、DING | 钉钉(事件中心 / DWS) | 该对象自身的终态(如 Todo `isDone`) | 复制一份到别处 → 两边不一致,人改了 Agent 不知道 |
123
+ | **常驻节律** | 值班、巡检、补数据、周期汇总 | Managed Agent Platform 的 schedule | **数据水位**(索引本身就是完成状态) | 塞进待办 → 丢一期就断链,且扫不到 = 静默收工 = 不自知 |
124
+ | **Agent 自主定时** | Agent 承接下来、要自己记住的将来动作 | Managed Agent Platform 的 schedule,**由 operator 授予写权限** | run 留痕 | 让 Agent 自建定时器 → 节律不可见、不可审计、改不掉 |
125
+
126
+ 判据只有一句:**这件事有没有终态?** 有终态、有交付对象 → 待办。永远做不完的维护义务 → 节律。
127
+
128
+ 三条从真实平台语义倒逼出来、与具体平台无关的约束:
129
+
130
+ - **定时不可靠是常态,判据必须写成「它发生了没有」而不是「那一拍跑了没有」。** 托管平台普遍会塌缩漏掉的 fire、跳过迟到过久的 fire(Multica 的阈值是 5 分钟)。凡是把「某时刻必须发生的事」绑定到「某一拍」的设计,一次 runtime 抖动就永久丢一期,而且事后查不出来。
131
+ - **外发类节律的留痕在动作之后,所以它没有锁。** 两个节律落在同一分钟并发唤醒,就会把同一条消息发两遍给第三方。多节律拆分必须错开触发时刻。
132
+ - **Agent 不自建定时器、不自改节律。** 节律是可审计的部署产物;在线 Run 只能把新节律整理成候选交给 operator,不能自己配上再宣称配好了——这与 §1「在线 Run 不能热改身份、权限或已启用 Skill」是同一条边界的延伸。
133
+
134
+ **本仓库在这一层拥有什么**:不拥有 cron,拥有三件事——装配时**声明**需要哪些节律与是否允许 Agent 自主排程(`dingtalk-agent-compose`);部署到具体平台时**校验**该平台是否真的提供这些能力、不提供就 fail closed(平台 Skill 包 + `agent-platform` 注册表);以及 Agent 侧被定时驱动时必须满足的**行为合同**(`dingtalk-basic-behavior`)。**平台之间能力不同是常态**——同一个 Agent 的节律声明可以不变,能不能被满足由目标平台回答。
135
+
61
136
  ## 4. 谁拦住什么:Skill 劝,CLI 拦,DWS 做
62
137
 
138
+ ![通用 Agent 行为内核拓扑](architecture/general-agent-kernel-topology.svg)
139
+
63
140
  - **Skill 劝**:判断该不该做、为何做、做到哪一步。这是语义判断,会被上下文影响,因此不能承担安全边界。
64
141
  - **CLI 拦**:固定身份、目标、预算、幂等、状态迁移与回读。不依赖模型自觉。
65
142
  - **DWS 做**:执行具体钉钉产品能力。
@@ -162,6 +239,8 @@ dingtalk-doc:<node-or-url> DWS 拉取在线文档的只读快照
162
239
 
163
240
  重心分布本身是个结论:交付链与评测各占约四分之一,合计超过一半。这个项目的难点从来不是"让模型说话",而是**证明它真的装好了、真的做对了、真的上线了**。
164
241
 
242
+ 对照 §3 的五个权威可以看出这六部分落在分工线的哪一侧:第 1、2、5 部分实现「本体、行为、状态与效果证据」那一行,是本仓库拥有的;**第 3 部分是通往「运行位置」那一行的连接面**——每接一个平台就多一个平台 Skill 包与一条注册表记录,行为内核不变;第 4 部分负责证明前三者在任意一个平台上都同样成立。第 6 部分服务开发者的机器本身,不在分工线上。
243
+
165
244
  两处接缝值得诚实标注,不糊弄过去:
166
245
 
167
246
  - `init.ts` 按模块归第 6 部分,但 CLI `init` 是第 1 部分的可选前置——机器安装与 Workspace 初始化是两件事。
@@ -169,14 +248,51 @@ dingtalk-doc:<node-or-url> DWS 拉取在线文档的只读快照
169
248
 
170
249
  各部分的模块依赖由 TypeScript import 关系直接表达,不在此维护一张会漂移的手绘边图。
171
250
 
172
- ## 8. 从定义到上线
251
+ ## 8. 开发生命周期:从定义到观测
173
252
 
174
- | 阶段 | 关键产物 | 门禁 |
175
- |---|---|---|
176
- | **创建** | `AGENTS.md`、Basic、Role Skills、bindings | 占位符未补全时保持 `partial` |
177
- | **测试** | 隔离 Workspace、load probe、行为评测、多面证据 | Definition/Skills 没有真实加载就不能 ready |
178
- | **发布** | 平台预检、部署 Receipt、远端 readback | 指定 Eval 未通过或身份链不完整就不能 promote |
179
- | **运行** | 数字员工账号或机器人入口、task trace | 无证据不声称写入、送达或完成 |
253
+ 这一节是「本项目做什么」的权威清单。**每一段都同时写明做什么与不做什么**——边界说不清,价值也就说不清。
254
+
255
+ ### 本体与员工技能
256
+
257
+ **做**:把「一个钉钉数字员工开口之前必须想清楚的事」沉淀成可版本化、可 hash、可机器验证继承的共享行为合同——响应资格、九类意图分级、外部动作的七字段授权、按五因素(可逆性/影响对象/数据归属/批量规模/权限范围)而非动作名的风险分级、证据阶梯与完成闸门、六类记忆与五种遗忘范围。另给本体四段骨架、岗位 Skill 五段骨架和两个已填好语义的完整样例。继承有三类机器证据:全树 hash 一致、Host 配置恰好一条强制加载、隔离副本里的随机 canary 精确回显。
258
+
259
+ **不做**:不提供统一的大 System Prompt,也没有 prompt 版本管理 / A-B / 变量注入这类设施;不写岗位方法、产品字段与 API 参数;不判断填进去的岗位内容对不对(那是 ⑤)。
260
+
261
+ ### ② 身份获取与事件感知
262
+
263
+ **做**:把形状各异的原始事件(`data` 是 JSON 字符串、`payload.body` 嵌套、命名风格混用)归一成稳定的事件合同;缺 conversation/message/sender 直接拒收而不是让 Agent 猜收件人;把回复目标与执行身份冻结成正文改不动的权威快照;按 Field 一次性绑定权限、行为包、DWS 身份与消息出口(一个 Field 只允许一个出口 owner,配错启动即失败);生成任何内容之前判定响应资格;用三个受约束的 Enricher(引用还原 / 同人连发合并 / 身份可读化)补齐现场,每项带来源、时间、截断与置信标记;按 eventId 抢 durable lease 保证同一事件只产生一个 Run,崩溃窗口先落 durable inbox 再物化,重放与漂移一律拒绝复用。
264
+
265
+ **不做**:不签发身份、不划定场域(钉钉侧的权限);**不拥有事件订阅与触发器**——Webhook、机器人回调、定时器、autopilot 都不属于本项目,`listen` 只是本地联调 Adapter。
266
+
267
+ ### ③ 托管平台部署
268
+
269
+ **做**:把手工搬运变成受控发布链——稳定 `planId` 冻结本体与整棵 Skill 树的 hash、原子动作清单与读写预算;apply 前重新回读身份/workspace/runtime 链,与冻结计划不一致就在任何写入之前失败;写后独立回读远端对象与 assignment,再发一个带随机 marker 的加载烟测,验证每个 Skill 真被 Host 原生加载;同源重放是零远端写的 noop;失败尽力回滚,超时进 reconciling 要求只读收敛而不是盲重试;`promote` 只接受与策略指定 suite/case/surface 精确匹配的证据 hash;`retire` 只归档那一个 Agent,保留 Skill、Issue 与产物。
270
+
271
+ **不做**:不创建任何事件入口(机器人、Webhook、定时器、autopilot);不创建远端 workspace/runtime,不做平台账号供给;不持有或代替用户登录平台凭据;不允许直接晋级到 prod。
272
+
273
+ ### ④ 驱动它在钉钉里干活
274
+
275
+ **做**:把外发收窄成四个互斥原语(`ack`/`reply`/`ask`/`silence`),模型造不出第五种副作用;ActionRequest 里不允许出现收件人、会话与身份,写错目标在结构上不可能;副作用**前**拦掉越权、超预算、目标漂移、状态非法等情况,副作用**后**强制平台回读把「命令返回成功」与「消息真的在钉钉里」分开记录;结果不确定时进入 reconcile 而**禁止盲重发**;跨 Run、跨沙箱靠宿主的 Wait 与 Session 续做,任务进度用 revision CAS 防覆盖;「完成」必须引用宿主签发、可重新核验的证据。
276
+
277
+ **不做**:不运行模型、不自带调度器、没有工作流引擎;进 Action Gate 的 typed 副作用**只有回复与表情两种**,其余钉钉动作继续直接走 DWS(判据是 §4 的六条),不受 Run 预算与 generation 约束。
278
+
279
+ > ⚠️ **一处「设计完成度 > 交付完成度」的断点**:完成证据的**核验**侧已完整实现并被合同锁定,但**签发**侧(`issueCompletionEvidence`)目前只有库 API,没有接到公开 CLI——`dta task` 只有 `show` 与 `checkpoint`。只用已发布 CLI 的开发者**无法把一件事推进到 `completed`**,需要宿主以库形式集成。
280
+
281
+ ### ⑤ 评测设计
282
+
283
+ **做**:给出「选最低够用的环境层级」的判断表与 L0–L4 分层;规定一次结论必须同时采集哪几个证据面,且回复正文永远不能自证完成;把硬门禁的判定顺序固定下来,防止安全失败被质量分平均掉;提供四个默认零副作用的 runner(真实外发需四道 gate 同时打开);给出「真实事故 → 可复跑场景」的沉淀路径与「这条该修进 CLI 还是修进 Skill」的判别原则;仓库自身的 62 个合同即范例,**每条都成对写明证明什么、不证明什么**。
284
+
285
+ **不做**:不做自然度与主观质量的自动判定,不允许用模型主观高分覆盖已实现的安全失败;不自动清理测试产物(写入授权不等于删除授权);不支持 prod 晋级。
286
+
287
+ ### ⑥ 观测与计量
288
+
289
+ **做**:`dta observe` 提供一条受控通道——把线上发现的一条**人工撰写**的脱敏观察,精确绑定到「线上跑的到底是哪一版」(必须与已 promoted Receipt 的 `observedHash` 逐字节相同),落成 gitignored 的 `proposed` 候选。它保证线上反馈**永远不会自动变成 Agent 的新行为**,且 CLI 会直接拒收手机号、邮箱、token 等敏感串。
290
+
291
+ **⚠️ 这是当前最薄的一段,必须说清楚**:`dta observe` **不采集任何线上数据**,它不是线上观测。执行轨迹的读取能力属于托管平台(随平台包分发一个薄 HTTP wrapper,换平台即失效)。**用量计量——交互量、任务量、线上 token、成本、按人/按群的使用分布——本项目一项都没有实现。** 最接近的是托管平台按 issue 聚合的 token 直通调用,以及本地评测执行的单次 token/花费(无聚合)。反馈采集也不是自动的,靠人手写 JSON;候选从 `proposed` 进入 Eval suite 的评审流程尚未实现。
292
+
293
+ **不做**:`observe` 产物不进 Git(团队间无法共享);不把线上数据写回 Prompt/Skill/suite;在线 Run 不得自动扩大身份、权限或启用 Skill。
294
+
295
+ ---
180
296
 
181
297
  Agent Project 与 Development Workspace 的基数关系:
182
298
 
@@ -221,6 +337,8 @@ trusted W3 inspection + local Definition/Skill tree
221
337
  ## 10. 当前明确不做
222
338
 
223
339
  - 不把 `listen` 或任何触发器做成 Agent 主进程;
340
+ - 不自己做 Managed Agent Platform,也不签发组织身份或场域授权;
341
+ - 不把尚未开放的平台宣称为已支持、已部署或已 Live 验证;
224
342
  - 不自动 init 任意代码仓库;
225
343
  - 不把整个 DWS 复制成另一套 CLI;
226
344
  - 不把钉钉文档当锁或事务数据库;
@@ -194,7 +194,7 @@ dta prepare --event-file event.json --json
194
194
 
195
195
  ## 开发者 Golden Path
196
196
 
197
- 安装完成后,一个岗位 Agent 只需要三组输入:本地 `AGENTS.md`、本地 `skills/<role>/SKILL.md`,以及从 compose Skill 模板创建的 `agent.bindings.json`。本地模板把 memory/knowledge 指向 Markdown;远端模板只把这两个语义槽路由到专用钉钉文档,产物与控制状态仍留在 Agent 根目录。
197
+ 安装完成后,一个新岗位 Agent 只需要三组输入:`agent/AGENTS.md`、`agent/skills/<name>/` 单一发布源,以及从 compose Skill 模板创建的 `agent.bindings.json`。根 `AGENTS.md` 只约束仓库开发。Host exposure dta 在隔离工作区临时物化,不进入 Git;已有仓库可在 manifest 显式声明其它路径。
198
198
 
199
199
  ```bash
200
200
  # 在 Agent 根目录
package/docs/PRIOR-ART.md CHANGED
@@ -1,7 +1,11 @@
1
1
  # 开源蓝本的差异、共同点与迁移决策
2
2
 
3
+ **这不是一次性调研,而是一份持续维护的观察账本。** 本项目的定位是把 Agent 装配成钉钉数字员工并连接各类 Agent 运行平台(见 [Architecture §3](ARCHITECTURE.md#3-每件事谁说了算模型-b)),因此**持续观察各 Managed Agent Platform 与开源 Agent 工具链的最佳实践、把可迁移的部分变成本项目的开源能力**,本身就是工作的一部分。每次接入新平台或发现新蓝本,结论回填到本文。
4
+
3
5
  调研最初基于 2026-07-14 各仓库源码,并在 2026-07-16 增补 `google/agents-cli`。结论不是 fork 某一个项目,而是 clean-room 组合:agents-cli 作为开发生命周期和 Coding-Agent-first CLI 的主要蓝本;其它项目分别提供社交行为、记忆、运行内核、人格或 Skill 包装。没有一个项目可以原样解决钉钉真实事件、DWS 权限和员工行为。
4
6
 
7
+ 观察什么、吸收什么,有一条固定判据:**只吸收可验证的结构与合同**(生命周期分相、manifest、eval 闭环、行为规则),不吸收无法验证的隐藏提示词,也不因为某个平台流行就把它宣称为已接入——支持状态一律以 `dta agent-platform list` 的注册表为准。
8
+
5
9
  ## 开发生命周期的主要蓝本:google/agents-cli
6
10
 
7
11
  [`google/agents-cli`](https://github.com/google/agents-cli) 是 dta 后续 Project、Workspace、Eval、Deploy 和 Provider 设计的首要参考。重点迁移的不是 Google Cloud 产品命令,而是这些结构:
package/docs/SELF-TEST.md CHANGED
@@ -33,7 +33,7 @@
33
33
 
34
34
  ## 怎么加一个场景
35
35
 
36
- 合同评测有 62 个场景、约 7800 行 runner。加一个新场景是四步:
36
+ 合同评测有 64 个场景、约 8100 行 runner。加一个新场景是四步:
37
37
 
38
38
  1. **在 `evals/evals.json` 追加一条**:`id`(顺延)、`prompt`(这个场景在测什么)、`expected_output`、`files`、`expectations`(逐条断言的自然语言描述),以及 **`tier`**。
39
39
  2. **在 `evals/run-contract-evals.mjs` 写同名实现函数** `eval<Name>()`,返回 `{ output, checks: [...] }`。runner 会硬断言 `checks.length === expectations.length`——两边对不上直接失败,这是防止"加了断言忘了写说明"的闸门。
@@ -0,0 +1,120 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 840" width="1440" height="840" role="img" aria-labelledby="title desc">
2
+ <title id="title">dingtalk-agent 作为连接层在运行平台与钉钉之间的位置</title>
3
+ <desc id="desc">运行位置层列出 Agent 可以执行的 Managed Agent Platform,Multica 已支持,DEAP 敬请期待,更多平台需先在注册表登记并提供平台 Skill 包;中间是 dingtalk-agent,提供接入与装配、行为壳子、受控交付、评测与观测四类能力,并拥有 Agent 本体、公共行为、状态与效果证据;下方左侧是钉钉数字员工平台,签发身份、划定场域并送来可信事件,当前尚未接入所以画成虚线;下方右侧是 DWS,所有真实钉钉操作最终由它执行并回读 Receipt;最底部是钉钉组织。</desc>
4
+ <style>
5
+ text { font-family:'Helvetica Neue',Helvetica,Arial,'PingFang SC','Microsoft YaHei',sans-serif; }
6
+ .title { fill:#111827;font-size:28px;font-weight:700; }
7
+ .subtitle { fill:#6b7280;font-size:14px; }
8
+ .lane { fill:#475569;font-size:12px;font-weight:700;letter-spacing:.08em; }
9
+ .node-title { fill:#111827;font-size:16px;font-weight:700; }
10
+ .node-sub { fill:#4b5563;font-size:12px; }
11
+ .small { fill:#64748b;font-size:11px; }
12
+ .label { fill:#475569;font-size:11px;font-weight:600; }
13
+ .footer { fill:#ffffff;font-size:11px;font-weight:600; }
14
+ </style>
15
+ <defs>
16
+ <marker id="arrow-blue" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto"><polygon points="0 0,10 3.5,0 7" fill="#2563eb"/></marker>
17
+ <marker id="arrow-purple" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto"><polygon points="0 0,10 3.5,0 7" fill="#7c3aed"/></marker>
18
+ <marker id="arrow-teal" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto"><polygon points="0 0,10 3.5,0 7" fill="#0d9488"/></marker>
19
+ <filter id="shadow" x="-20%" y="-20%" width="140%" height="140%"><feDropShadow dx="0" dy="2" stdDeviation="3" flood-color="#0f172a" flood-opacity=".10"/></filter>
20
+ </defs>
21
+
22
+ <rect width="1440" height="840" fill="#ffffff"/>
23
+
24
+ <text x="40" y="48" class="title">把 Agent 接进钉钉,并连接更广阔的运行平台</text>
25
+ <text x="40" y="75" class="subtitle">本仓库是连接层:不发身份、不建 Runtime、不复制 DWS 命令面——只把 Agent 装配成合格的钉钉数字员工。</text>
26
+
27
+ <!-- ── 泳道 1:运行位置 ───────────────────────────────── -->
28
+ <rect x="30" y="100" width="1380" height="152" rx="12" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1.2" stroke-dasharray="7 5"/>
29
+ <text x="48" y="124" class="lane">RUNTIME LOCATION · 运行位置:Agent 在哪里执行——可替换,且是本仓库的连接面</text>
30
+
31
+ <rect x="55" y="144" width="300" height="80" rx="9" fill="#f0fdf4" stroke="#86efac" stroke-width="1.6"/>
32
+ <text x="205" y="176" text-anchor="middle" class="node-title">Multica</text>
33
+ <text x="205" y="199" text-anchor="middle" class="node-sub">已支持</text>
34
+
35
+ <rect x="385" y="144" width="300" height="80" rx="9" fill="#f9fafb" stroke="#d1d5db" stroke-width="1.6" stroke-dasharray="6 4"/>
36
+ <text x="535" y="176" text-anchor="middle" class="node-title">DEAP</text>
37
+ <text x="535" y="199" text-anchor="middle" class="node-sub">敬请期待 · 是否内建运行平台待确认</text>
38
+
39
+ <rect x="715" y="144" width="300" height="80" rx="9" fill="#f9fafb" stroke="#d1d5db" stroke-width="1.6" stroke-dasharray="6 4"/>
40
+ <text x="865" y="176" text-anchor="middle" class="node-title">更多平台</text>
41
+ <text x="865" y="199" text-anchor="middle" class="node-sub">注册表 + 平台 Skill 包</text>
42
+
43
+ <text x="1045" y="176" class="node-sub">接入一个平台 =</text>
44
+ <text x="1045" y="199" class="node-sub">一个平台 Skill 包 + 注册表一条记录</text>
45
+
46
+ <!-- 装配箭头 -->
47
+ <path d="M720 252 L720 296" fill="none" stroke="#2563eb" stroke-width="2" marker-end="url(#arrow-blue)"/>
48
+ <rect x="734" y="262" width="204" height="21" rx="5" fill="#ffffff" opacity=".96"/>
49
+ <text x="836" y="277" text-anchor="middle" class="label">装配 · 加载 Definition 与 Skills</text>
50
+
51
+ <!-- ── 泳道 2:dingtalk-agent(高亮)───────────────────── -->
52
+ <rect x="30" y="306" width="1380" height="242" rx="14" fill="#f8fafc" stroke="#0f766e" stroke-width="2"/>
53
+ <text x="48" y="332" fill="#0f766e" font-size="13" font-weight="700" letter-spacing=".08em">DINGTALK-AGENT · 本仓库:行为内核与连接层</text>
54
+ <text x="48" y="354" class="small">五个部件里唯一由本仓库拥有的一项——Agent 本体、公共行为、状态与效果证据</text>
55
+
56
+ <rect x="55" y="370" width="315" height="152" rx="10" fill="#eff6ff" stroke="#60a5fa" stroke-width="2" filter="url(#shadow)"/>
57
+ <text x="75" y="400" class="node-title">接入与装配</text>
58
+ <text x="75" y="424" class="node-sub">把 Agent 变成可 hash、</text>
59
+ <text x="75" y="444" class="node-sub">可继承、可审计的本体</text>
60
+ <rect x="75" y="466" width="275" height="28" rx="7" fill="#ffffff" stroke="#93c5fd"/>
61
+ <text x="212" y="485" text-anchor="middle" class="small" fill="#1d4ed8">agent enhance · agent audit</text>
62
+
63
+ <rect x="390" y="370" width="315" height="152" rx="10" fill="#eff6ff" stroke="#60a5fa" stroke-width="2" filter="url(#shadow)"/>
64
+ <text x="410" y="400" class="node-title">行为壳子</text>
65
+ <text x="410" y="424" class="node-sub">何时响应 · 何时追问</text>
66
+ <text x="410" y="444" class="node-sub">何时沉默 · 如何收口</text>
67
+ <rect x="410" y="466" width="275" height="28" rx="7" fill="#ffffff" stroke="#93c5fd"/>
68
+ <text x="547" y="485" text-anchor="middle" class="small" fill="#1d4ed8">Basic Behavior + 标准模板</text>
69
+
70
+ <rect x="725" y="370" width="315" height="152" rx="10" fill="#eff6ff" stroke="#60a5fa" stroke-width="2" filter="url(#shadow)"/>
71
+ <text x="745" y="400" class="node-title">受控交付</text>
72
+ <text x="745" y="424" class="node-sub">零写入计划 · 显式确认</text>
73
+ <text x="745" y="444" class="node-sub">每步独立回读</text>
74
+ <rect x="745" y="466" width="275" height="28" rx="7" fill="#ffffff" stroke="#93c5fd"/>
75
+ <text x="882" y="485" text-anchor="middle" class="small" fill="#1d4ed8">deploy · promote · Receipt</text>
76
+
77
+ <rect x="1060" y="370" width="315" height="152" rx="10" fill="#eff6ff" stroke="#60a5fa" stroke-width="2" filter="url(#shadow)"/>
78
+ <text x="1080" y="400" class="node-title">评测与观测</text>
79
+ <text x="1080" y="424" class="node-sub">上线前证明它真会做事</text>
80
+ <text x="1080" y="444" class="node-sub">失败沉淀成可复跑场景</text>
81
+ <rect x="1080" y="466" width="275" height="28" rx="7" fill="#ffffff" stroke="#93c5fd"/>
82
+ <text x="1217" y="485" text-anchor="middle" class="small" fill="#1d4ed8">lab · workspace eval · observe</text>
83
+
84
+ <!-- 身份与事件向上(虚线=尚未接入);动作经 DWS 向下(实线=已在用) -->
85
+ <path d="M365 600 L365 556" fill="none" stroke="#7c3aed" stroke-width="1.8" stroke-dasharray="6 4" marker-end="url(#arrow-purple)"/>
86
+ <rect x="373" y="566" width="186" height="21" rx="5" fill="#ffffff" opacity=".96"/>
87
+ <text x="466" y="581" text-anchor="middle" class="label">签发的身份 · 可信事件(待接入)</text>
88
+
89
+ <path d="M1075 556 L1075 600" fill="none" stroke="#0d9488" stroke-width="2" marker-end="url(#arrow-teal)"/>
90
+ <rect x="1084" y="566" width="166" height="21" rx="5" fill="#ffffff" opacity=".96"/>
91
+ <text x="1167" y="581" text-anchor="middle" class="label">动作 · 执行 · Receipt 回读</text>
92
+
93
+ <!-- ── 下层左:钉钉数字员工平台(虚线=尚未接入)─────── -->
94
+ <rect x="30" y="600" width="670" height="160" rx="12" fill="#faf5ff" stroke="#c084fc" stroke-width="1.8" stroke-dasharray="7 5"/>
95
+ <text x="48" y="626" fill="#7c3aed" font-size="12" font-weight="700" letter-spacing=".08em">IDENTITY &amp; PERCEPTION · 钉钉数字员工平台</text>
96
+
97
+ <rect x="55" y="644" width="300" height="76" rx="9" fill="#ffffff" stroke="#d8b4fe" stroke-width="1.6"/>
98
+ <text x="205" y="674" text-anchor="middle" class="node-title">身份权限管控</text>
99
+ <text x="205" y="697" text-anchor="middle" class="node-sub">创建 · UID · 场域边界 · 生命周期</text>
100
+
101
+ <rect x="375" y="644" width="300" height="76" rx="9" fill="#ffffff" stroke="#d8b4fe" stroke-width="1.6"/>
102
+ <text x="525" y="674" text-anchor="middle" class="node-title">感知与人机交互</text>
103
+ <text x="525" y="697" text-anchor="middle" class="node-sub">事件送达 · 统一展示</text>
104
+
105
+ <text x="55" y="744" class="small">DEAP 敬请期待,平台命令一律 fail-closed;当前身份不经过 DEAP。事件信封的权威是钉钉事件中心与 DWS。</text>
106
+
107
+ <!-- ── 下层右:DWS(实线=已在用)────────────────────── -->
108
+ <rect x="740" y="600" width="670" height="160" rx="12" fill="#f0fdfa" stroke="#0f766e" stroke-width="1.8"/>
109
+ <text x="758" y="626" fill="#0f766e" font-size="12" font-weight="700" letter-spacing=".08em">PLATFORM EXECUTION · DWS</text>
110
+
111
+ <rect x="765" y="644" width="620" height="76" rx="9" fill="#ffffff" stroke="#5eead4" stroke-width="1.6"/>
112
+ <text x="1075" y="674" text-anchor="middle" class="node-title">消息 · 文档 · 表格 · 日程 · 审批 · 通讯录</text>
113
+ <text x="1075" y="697" text-anchor="middle" class="node-sub">所有真实钉钉操作最终都由 DWS 执行</text>
114
+
115
+ <text x="765" y="744" class="small">src/dws.ts 是全仓库唯一 spawn dws 的地方;本仓库不复制它的命令面。</text>
116
+
117
+ <!-- 钉钉组织 -->
118
+ <rect x="30" y="790" width="1380" height="26" rx="6" fill="#0f172a"/>
119
+ <text x="720" y="807" text-anchor="middle" class="footer">钉钉组织 · 真实的人、群、日程、审批与文档 —— 身份与事件由钉钉签发,本仓库只冻结、审计和引用,不发证、不改写、不扩权</text>
120
+ </svg>
@@ -0,0 +1,92 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 550" width="1440" height="550" role="img" aria-labelledby="title desc">
2
+ <title id="title">dingtalk-agent 数字员工的五个部件与各自的权威</title>
3
+ <desc id="desc">一个数字员工由五个部件构成:Agent 本体由本仓库拥有;组织身份与场域授权由钉钉数字员工平台签发;感知通道由钉钉事件中心与 DWS 提供;平台执行能力由 DWS 提供;运行位置由 Managed Agent Platform 或 Agent Host 提供。本仓库只拥有第一项,其余四项不实现也不替代,但必须逐一显式建模。</desc>
4
+ <style>
5
+ text { font-family:'Helvetica Neue',Helvetica,Arial,'PingFang SC','Microsoft YaHei',sans-serif; }
6
+ .title { fill:#111827;font-size:28px;font-weight:700; }
7
+ .subtitle { fill:#6b7280;font-size:14px; }
8
+ .lane { fill:#475569;font-size:12px;font-weight:700;letter-spacing:.08em; }
9
+ .node-title { fill:#111827;font-size:16px;font-weight:700; }
10
+ .node-sub { fill:#4b5563;font-size:12px; }
11
+ .small { fill:#64748b;font-size:11px; }
12
+ .own { fill:#1d4ed8;font-size:13px;font-weight:700; }
13
+ .ext { fill:#475569;font-size:13px;font-weight:600; }
14
+ .formula { fill:#334155;font-size:15px; }
15
+ </style>
16
+ <defs>
17
+ <filter id="shadow" x="-20%" y="-20%" width="140%" height="140%"><feDropShadow dx="0" dy="2" stdDeviation="3" flood-color="#0f172a" flood-opacity=".10"/></filter>
18
+ </defs>
19
+
20
+ <rect width="1440" height="550" fill="#ffffff"/>
21
+
22
+ <text x="40" y="48" class="title">数字员工不等于 Agent</text>
23
+ <text x="40" y="75" class="subtitle">它是一个 Agent 装配上组织语境之后的结果——五个部件,五个权威,本仓库只拥有第一项。</text>
24
+
25
+ <rect x="30" y="100" width="1380" height="250" rx="12" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1.2" stroke-dasharray="7 5"/>
26
+ <text x="48" y="124" class="lane">DIGITAL EMPLOYEE · 一个数字员工由五个部件构成</text>
27
+
28
+ <!-- 1. Agent 本体 —— 本仓库唯一拥有 -->
29
+ <rect x="55" y="145" width="234" height="180" rx="10" fill="#eff6ff" stroke="#60a5fa" stroke-width="2" filter="url(#shadow)"/>
30
+ <text x="75" y="175" class="node-title">Agent 本体</text>
31
+ <text x="75" y="198" class="node-sub">Definition · Skills</text>
32
+ <text x="75" y="218" class="node-sub">行为 · 状态 · 效果证据</text>
33
+ <text x="75" y="252" class="small">谁说了算</text>
34
+ <rect x="75" y="262" width="194" height="30" rx="7" fill="#ffffff" stroke="#93c5fd"/>
35
+ <text x="172" y="282" text-anchor="middle" class="node-sub" fill="#1d4ed8">本仓库 + Git</text>
36
+
37
+ <text x="309" y="245" text-anchor="middle" fill="#94a3b8" font-size="24">+</text>
38
+
39
+ <!-- 2. 组织身份与场域授权 -->
40
+ <rect x="329" y="145" width="234" height="180" rx="9" fill="#faf5ff" stroke="#c084fc" stroke-width="1.6"/>
41
+ <text x="349" y="175" class="node-title">组织身份与场域</text>
42
+ <text x="349" y="198" class="node-sub">发证 · 权限 · 边界</text>
43
+ <text x="349" y="218" class="node-sub">入转调离 · 生命周期</text>
44
+ <text x="349" y="252" class="small">谁说了算</text>
45
+ <rect x="349" y="262" width="194" height="30" rx="7" fill="#ffffff" stroke="#d8b4fe"/>
46
+ <text x="446" y="282" text-anchor="middle" class="node-sub" fill="#7c3aed">钉钉数字员工平台</text>
47
+
48
+ <text x="583" y="245" text-anchor="middle" fill="#94a3b8" font-size="24">+</text>
49
+
50
+ <!-- 3. 感知通道 -->
51
+ <rect x="603" y="145" width="234" height="180" rx="9" fill="#fff7ed" stroke="#fdba74" stroke-width="1.6"/>
52
+ <text x="623" y="175" class="node-title">感知通道</text>
53
+ <text x="623" y="198" class="node-sub">可信事件信封</text>
54
+ <text x="623" y="218" class="node-sub">谁 · 在哪 · 说了什么</text>
55
+ <text x="623" y="252" class="small">谁说了算</text>
56
+ <rect x="623" y="262" width="194" height="30" rx="7" fill="#ffffff" stroke="#fdba74"/>
57
+ <text x="720" y="282" text-anchor="middle" class="node-sub" fill="#c2410c">钉钉事件中心 / DWS</text>
58
+
59
+ <text x="857" y="245" text-anchor="middle" fill="#94a3b8" font-size="24">+</text>
60
+
61
+ <!-- 4. 平台执行能力 -->
62
+ <rect x="877" y="145" width="234" height="180" rx="9" fill="#f0fdfa" stroke="#5eead4" stroke-width="1.6"/>
63
+ <text x="897" y="175" class="node-title">平台执行能力</text>
64
+ <text x="897" y="198" class="node-sub">消息 · 文档 · 表格</text>
65
+ <text x="897" y="218" class="node-sub">日程 · 审批 · 通讯录</text>
66
+ <text x="897" y="252" class="small">谁说了算</text>
67
+ <rect x="897" y="262" width="194" height="30" rx="7" fill="#ffffff" stroke="#5eead4"/>
68
+ <text x="994" y="282" text-anchor="middle" class="node-sub" fill="#0f766e">DWS</text>
69
+
70
+ <text x="1131" y="245" text-anchor="middle" fill="#94a3b8" font-size="24">+</text>
71
+
72
+ <!-- 5. 运行位置 -->
73
+ <rect x="1151" y="145" width="234" height="180" rx="9" fill="#f9fafb" stroke="#d1d5db" stroke-width="1.6"/>
74
+ <text x="1171" y="175" class="node-title">运行位置</text>
75
+ <text x="1171" y="198" class="node-sub">模型 · 工具循环</text>
76
+ <text x="1171" y="218" class="node-sub">沙箱 · Session 生命周期</text>
77
+ <text x="1171" y="252" class="small">谁说了算</text>
78
+ <rect x="1171" y="262" width="194" height="30" rx="7" fill="#ffffff" stroke="#d1d5db"/>
79
+ <text x="1268" y="282" text-anchor="middle" class="node-sub">Managed Platform / Host</text>
80
+
81
+ <!-- 归属带 -->
82
+ <rect x="55" y="368" width="234" height="4" rx="2" fill="#2563eb"/>
83
+ <rect x="329" y="368" width="1056" height="4" rx="2" fill="#cbd5e1"/>
84
+ <text x="55" y="394" class="own">本仓库拥有</text>
85
+ <text x="329" y="394" class="ext">由外部签发或提供——本仓库不实现、不替代,但逐一显式建模,否则边界会悄悄溜走</text>
86
+
87
+ <!-- 公式条 -->
88
+ <rect x="30" y="418" width="1380" height="94" rx="10" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1"/>
89
+ <text x="50" y="444" fill="#111827" font-size="13" font-weight="700">可叠加公式</text>
90
+ <text x="50" y="472" class="formula">Agent 本体 + 组织身份与场域授权 + 感知通道 + 平台执行能力 + 运行位置 = 一个可工作的钉钉数字员工</text>
91
+ <text x="50" y="496" class="small">外部签发的身份、场域与事件信封只能被冻结、审计和引用,永远不能从正文、显示名或模型记忆推断。</text>
92
+ </svg>