关于 experience-cms-content-generate
面向 Salesforce CMS 内容创作者的技能,用自然语言提示词创建、编辑和发布现有内容类型的记录。它由服务器生成并校验内容正文,并按意图处理更新、发布和删除请求。
主要功能
- 01基于现有内容类型创建记录
- 02通过提示词生成并校验正文
- 03编辑已有内容记录
- 04发布记录或批量发布
- 05将删除请求引导至指定处理方式
适用场景
- 01从创作指令生成 CMS 内容记录
- 02修改已有记录的内容
- 03发布单条或多条内容
- 04处理用户提出的内容删除请求
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ forcedotcom/ sf-skills --skill experience-cms-content-generate安装后在 Claude Code 中输入/experience-cms-content-generate确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
assets/display-formats.mdquestions.mdassets/payloads/create-content-bulk.jsoncreate-content-single.jsonpublish-content.jsonupdate-content.jsonexamples/create-content-call.mdreferences/bulk-batching.mdcontent-type-classification.mdcontent-write-tool.mddelegation-protocol.mdedit-publish-workflow.mderror-recovery.mdidentifier-resolution.mdintent-routing.mdprinciples.mdux-rules.mdworkspace-resolution.md详细介绍
创建 CMS 内容
用于创建 Salesforce CMS 内容记录的通用技能 — 负责协调类型发现、工作区解析,并针对现有 ContentTypeBundle 调用 create_cms_content。
内容生成始终在服务端进行。 create_cms_content / update_cms_content_variant 会将目标 / 编辑指令作为 prompt;服务端根据架构生成并验证正文,然后返回已持久化的记录。Agent 绝不会遍历架构、组装 contentBody、预先验证或重新生成被拒绝的字段(原则 3)。
范围
在 Salesforce CMS 中创建托管内容记录 — 基于现有 ContentTypeBundle 创建的实例。
在用户希望执行以下操作时使用: 根据自由文本提示,基于现有 CMS 类型创建任意类型的内容记录(单条或批量);编辑 / 优化会话中的项目;更新 / 编辑或发布通过 managedContentVariantId / managedContentId 直接指定的记录 — 即使该记录不是在本次会话中创建的(步骤 0 → UPDATE / PUBLISH 入口);发布全部或部分记录;删除 / 移除记录 — 此技能负责处理删除请求,并引导至硬性停止点(步骤 0-D);绝不透露内部原因。
在用户希望执行以下操作时不要使用: 定义新的内容类型 / 架构(使用 experience-cms-content-type-generate);取消发布、克隆或为记录创建版本;管理工作区 / 文件夹 / 渠道;附加图像 / 媒体;应用品牌样式。
“创建图像 / 媒体内容”不属于预检阶段的排除范围(只有字面意义上的二进制文件附加 / 上传才属于上述排除的“附加媒体”)。创建图像 / 视频内容记录(例如从 URL 创建)应进入正常流程 — 解析类型 + 工作区,调用 create_cms_content,绝不应预先拒绝或建议使用 REST / UI 变通方案。sfdc_cms__media 由服务端决定:让工具返回错误,然后根据原则 15 硬性停止(references/error-recovery.md)。
开始之前
按顺序执行步骤 — 不要跳过或调换顺序。
每次成功运行都必须以调用 create_cms_content 结束(至少 1 次),且每次调用都必须通过 prompt 携带目标。
尽量减少交互 — 调用前唯一需要提问的是步骤 3(工作区)。绝不询问目标优化、模式或正文详情。步骤 1 静默执行。 提示中包含 FQN → 步骤 2 快速路径;否则,步骤 2a 委派执行,中间不得调用 ask_user_tool。**批量操作例外:**步骤 4 会呈现主题提示供用户批准。
逐字提问约定 — 适用于每一次 ask_user_tool 调用,无一例外。 完整规则 → references/ux-rules.md。每个问题都必须通过 ask_user_tool 提出(绝不能使用纯文本);在进行任何调用之前,打开 assets/questions.md,并逐字符复制 question 字符串和 answers 数组,只填写 <placeholders> — 绝不能改写 / 缩短 question,绝不能添加 / 删除 / 调整 answers 的顺序,绝不能将列表内容放入答案中。如果没有适用的模板?停止并重新阅读 assets/questions.md — 绝不能临时编写问题。
工作流概览
- [ ] Step 1: Understand intent (silent — domain, count, FQN if present)
- [ ] Step 2: Resolve content type — fast-path (Buckets 1/2/3) or delegate → contentTypeFqn
- [ ] Step 3: Resolve workspace — UIBundle options or manual ID
- [ ] Step 4: Build payload — single or bulk (topic approval if bulk)
- [ ] Step 5: Dispatch create_cms_content (parallel for bulk)
- [ ] Step 6: Display content body + summary
- [ ] Step 7: Post-action loop — Edit / Publish / End
- [ ] Step 8: Edit — update_cms_content_variant
- [ ] Step 9: Publish — publish_content
- [ ] Step 10: Post-publish — Create more / Render (if UIBundle) / End
步骤 0:路由意图(始终最先执行)
在步骤 1 之前,将意图准确分类为一种并进行路由。 更新/发布/删除是一级入口,而不只是创建流程的后续步骤。若用户以其中一个动词开头 → 不要自行发挥(凭直觉选择工具、运行 SOQL、猜测变体 ID)。读取开头动词并进行路由:
| 用户意图(开头动词) | 路由至 |
|---|---|
create、generate、write、draft、author、post、add、compose;“create N <things>” | CREATE — 继续执行步骤 1 |
| update、edit、change、modify、revise 现有记录 | UPDATE 入口 — 步骤 0-U |
| publish 现有记录 | PUBLISH 入口 — 步骤 0-P |
| delete、remove、destroy 记录 | DELETE — 步骤 0-D(立即停止) |
| 意图不明确(无法判断是创建、更新还是发布) | 使用 ask_user_tool 消除歧义(Create new / Update existing / Publish existing / Cancel),并根据回答进行路由 |
禁止偏离规则(适用于所有路由)。 如果此桥接上的路由所需 content-write 工具(create_cms_content/update_cms_content_variant/publish_content)不可用,立即停止,打印面向用户的可执行消息,并结束本轮。绝不可改用 SOQL、sf data、CLI、同类工具或 contentBody 渠道;工具不可用和不支持的操作都是终止情况,绝不可触发回退。准确消息 + 各路由占位符 + 可说/不可说内容 → references/intent-routing.md § 禁止偏离规则。
步骤 0-U(UPDATE)和步骤 0-P(PUBLISH)— 直接入口路径
完整操作详情 → references/intent-routing.md。 这是会话内步骤 8(编辑)/步骤 9(发布)的直接入口对应路径 — 记录可直接指定,也可能来自之前的会话或其他用户(编辑/发布不限于当前会话)。关键约束:
- 严格执行标识符门槛 — 任何工具调用之前。 目标
managedContentVariantId只能来自 (a) 会话登记表,或 (b) 用户输入的标识符(MC…/20Y…/9Ps)。只有名称、没有 ID、且不在登记表中 → 停止并询问,通过ask_user_tool提问“Which record should I work with?”,问题必须逐字照抄,选项为["Cancel"]。不得自行查找记录 — 不得使用search_content、发现/列表工具、SOQL 或猜测 ID。 - 按前缀解析 + 操作前验证 →
references/identifier-resolution.md(9Ps→get_content_variant;MC…/20Y…→get_content)。读取失败 → 停止;绝不可盲目编辑/发布。 - 0-U → 步骤 8c(必须先完整显示正文,再提示用户提供编辑指示),通过步骤 7 对话框结束。0-P → 步骤 9b,通过发布确认结束,并结束本轮(不执行步骤 10 — 没有会话上下文)。两者均不执行步骤 1–5。
步骤 0-D:DELETE(立即停止)
删除功能不可用(没有删除能力 — 这是内部信息,不得对用户透露)。准确打印以下消息,不得有任何其他内容:
Deleting content isn't supported here. To delete this content, open it in Salesforce CMS and use the Delete option there.
前后都不得说任何话 — 不得有开场白、推理、规则复述、工具/服务器名称或元叙述;用户只能看到纯文本消息。结束本轮。不得提供 unpublish_content、SOQL 或 CLI 作为替代方案 — 只有 CMS UI 可以进行此操作。
步骤 1:理解意图
静默步骤——此处绝不可提问。 在 Agent 内部提取信息,然后直接进入步骤 2。不要先说“让我确认一下……”,不要调用 ask_user_tool,也不要提供内容类型菜单——即使提示很模糊(generate new content for Q4 launch),步骤 2 所需的信息也已足够。正准备在步骤 1 提问(澄清、提供内容类型菜单、询问“你心里想的是哪种类型?”或“要多少个?”)?这就是问题所在——转到步骤 2。解析消息,提取:
- 内容领域(文章、博客、新闻、常见问题……)——按原样推断;未指定领域也没关系。
- 数量——明确指定数量 → 使用该数量;“多个”“若干”“几个”“一些” → 由 Agent 选择 4–5 个;未提及数量 → 单个。
- 内容类型引用——逐字捕获任何看起来像内容类型名称的词项(准确的 FQN、仅差一个下划线的近似名称、开发者名称、不带命名空间的名称、自然语言名称)。此处不要分类——由步骤 2 指定所属类别。
不要删减或改写消息——原始消息是步骤 4 主题提示词的创作方向,也是步骤 2a 按原样传给同级 Agent 的 intent。
多类型门槛——步骤 1 唯一可以提出的问题。 如果提示涉及 ≥2 种不同的内容类型(每种都对应自己的 ContentTypeBundle,例如 grooming packages 和 service area coverage),你必须先让用户选择一种,再进入步骤 2(每次运行仅处理一种类型;两种类型会破坏委派约定)。按原文发送步骤 1 的多类型提示(答案 = 用户所用措辞中的不同领域 + Cancel),后续只将所选领域作为 intent。这是“绝不提问”规则的唯一例外——仅在涉及 ≥2 种不同类型时触发,不适用于目标、模式或数量。同一种类型下的多个主题(5 blog posts)不会触发此门槛(批量处理)。规则和示例 → references/content-type-classification.md § Multi-type gate。
步骤 2:解析内容类型
将步骤 1 捕获的内容类型引用归类为以下四个类别之一——完整的检测规则、示例和路由方式见 references/content-type-classification.md。摘要:
- 类别 1——准确的 FQN。 符合
^[a-zA-Z_][a-zA-Z0-9_]*__[A-Za-z][A-Za-z0-9_]*$(c__BlogPost)。捕获contentTypeFqn,进入步骤 3。静默处理。 - 类别 2——可自动更正的近似名称。 已知命名空间与名称之间只有一个下划线(
c_news→c__news)。自动更正,在聊天中告知用户(不调用ask_user_tool),进入步骤 3。 - 类别 3——低置信度、类似 FQN 的名称。 不带命名空间的名称(
BlogPost→建议使用c__BlogPost)或未知命名空间的单下划线名称。发送步骤 2 的 FQN 更正提示,并根据回答进行路由。 - 无效 FQN 门槛。 词项本意是 FQN(包含
__),但格式错误,且不属于类别 2 的近似名称(c__、__Foo、c__Blog Post、c__123)→ 不要将其作为自由文本委派;发送 FQN 更正提示(Let me provide a different FQN/Cancel),并用新字符串重新开始步骤 2。 - 类别 4——自然语言或未提供词项(
blog post)。委派——进入步骤 2a。
快速通道不变量(类别 1/2/3): 捕获 FQN 后,不要在组织中验证它、委派、扫描 contentTypes/、发送 metadata-grounding、检索或读取 schema.json。无效的 FQN 会在步骤 5 确定性地报错 INVALID_TYPE。在委派路径上,同级 Agent 负责扫描、grounding、选择问题、新建并部署、构建 FQN,以及检索并协调。
2a–2d. 委托给同级技能(仅 Bucket 4)
完整协议 → references/delegation-protocol.md。 简而言之:2a 先解析工作区(Step 3 → contentSpaceOrFolderId),打印提示 Resolving the content type for your request…,通过 mcp__skill_bridge__load_skill("experience-cms-content-type-generate") 调用(不要使用内置的 Skill — 会返回 Unknown skill),传入 { intent: "<user message verbatim>", suppressCreateContentPrompt: true, <scope> }(<scope> = spaceId 0Zu 或 folderId 9Pu,必须且只能有一个,绝不能传 baseType);委托前不提问。2b — 同级技能运行期间,本技能处于暂停状态(在得到终态结果前,不得调用 Step 4+;交错调用会破坏其状态机)。接收 { status, fqn, message }(忽略任何 schema),严格按 status 路由:
status | 本技能的操作 |
|---|---|
success(存在 fqn) | 原样打印同级技能的 message(包含类型和部署行);若为空,则打印 Using content type \`.`。然后执行 Step 2c。 |
not_deployed(存在 fqn) | 停止。 原样打印 message。不要继续执行 Step 3 — create_cms_content 对仅本地的包会失败并返回 INVALID_TYPE。 |
cancelled | 静默停止。 打印 Session ended. 并退出。不要再次调用同级技能。 |
error | 停止。 原样打印 message(包含原因和恢复提示)。不要重试或绕过。 |
load failed(桥接器返回 Unknown skill/错误 — 同级技能从未运行) | 按 references/delegation-protocol.md § 2b 停止(终态,不是回退方案 — 不得进行本地扫描、grounding 或工作区调用)。先通过 search_skills→load_skill 重试一次。 |
2c(仅在 success 时执行)— 验证 fqn 是否符合 FQN 正则表达式;缺失/格式错误 → 显示重新运行提示 + ask_user_tool(Retry with an explicit FQN/Cancel);然后捕获 contentTypeFqn,执行 Step 3。2d — 绝不调用 metadata-grounding、sf project retrieve,不得重新展示/重新选择,也不得根据文件夹名称构建 FQN(这些都由同级技能负责);出现五种漂移信号时 → 按 load failed 行硬性停止;绝不能将 not_deployed 降级为 success。对于手动指定的空间,2a 调用就是第 2 层确认 — 无效/未找到时 → 硬性停止,并通过无效 ID 模板重新询问。
步骤 3:解析工作区 — 问题 1
步骤 3 的执行时机取决于步骤 2 如何解析类型: 快速路径(桶 1/2/3)→ 在此处、步骤 2 之后执行。委派路径(桶 4)→ 提前执行,作为步骤 2a 的第一个操作,在分派同级项之前执行,这样 contentSpaceOrFolderId 就能限定同级项的发现范围;同级项返回后不要重新执行或再次询问。两种情况的解析步骤相同。
静默扫描本地项目中的 UIBundle 目录,然后通过单个 ask_user_tool 问题列出所有选项。**完整的发现、路由和验证流程 → references/workspace-resolution.md。**简而言之:
- **发现(静默):**扫描每个
sfdx-project.json包路径下的uiBundles/(后备方式:递归扫描),读取每个<name>.uibundle-meta.xml中的<masterLabel>→{ developerName, masterLabel }。如果数量为零 → 使用“没有本地 UIBundle”变体。绝不虚构工作区、运行 SOQL 或读取ui-bundle.json。 - **询问(单个问题):**通过
ask_user_tool分派assets/questions.md中的“步骤 3 — 工作区解析”模板(绝不使用纯文本);逐字复制question+answers,不得改写、重命名或删减任何内容。**无 UIBundle 变体为固定文本 —question:"Which content space or folder should I create the content in? Provide the ID (Content Space IDs start with0Zu; Folder IDs start with9Pu).",answers:["Cancel"]。**找到 UIBundle、手动输入 ID 和无效 ID 变体 → 见assets/questions.md。 - 选择 UIBundle →
get_or_create_cms_workspace_and_web_app_channel(developerName, masterLabel);返回的spaceId=contentSpaceOrFolderId;记录workspaceMethod=uibundle+channelId;将channelId持久化到uiBundles/<developerName>/public/content-metadata.json(合并)。工具失败 → 重试提示。 - 手动输入 ID → 记录
workspaceMethod=manual(没有channelId→ 步骤 10 渲染隐藏);手动输入 ID 提示中包含“返回”。验证(前缀 + 长度是必要条件,但不充分):L10Zu→spaceId/9Pu→folderId,15/18 位字母数字字符。L2 在首次调用涉及该空间的工具时验证(委派路径:get_content_types_for_workspace;快速路径:create_cms_content)——无效/未找到 → 停止,原样显示错误,并通过无效 ID 模板重新询问。不得显示组织选择器。
步骤 4:构建创建内容载荷
严格入口条件 — contentTypeFqn 必须来自步骤 2(桶 1/2/3 快速路径捕获的值,或 status: success 同级项结果)。未运行步骤 2(且在桶 4 中进行了委派)?停止,返回步骤 2。绝不虚构、猜测或默认内容类型——**未执行步骤 2 就选择 sfdc_cms__news 或任何基础/标准类型,属于回归问题。**没有 FQN → 桶 4 → 必须先委派。步骤 2 之前通过 ToolSearch 提前调用创建工具,同样属于此类问题。
目标以 prompt 传入;服务端生成并验证正文。Agent 只负责整理载荷并生成标题。输入:contentType = 步骤 2 的 contentTypeFqn;contentSpaceOrFolderId = 步骤 3 的值;prompt = [USER GOAL](单条内容使用原始消息;批量内容使用经步骤 4.B.2 批准的主题提示词)。标题由 Agent 生成——简洁、切题、面向客户,并体现 [USER GOAL]。
- 单条(quantity = 1):
assets/payloads/create-content-single.json。必填:contentType、contentSpaceOrFolderId、title、prompt(原样传入)。仅当用户指定时才填写可选项(urlName、contentKey、externalId、apiName)。绝不包含contentBody——它与prompt互斥。 - **批量(quantity > 1):**生成 N 个不同的主题提示词,供用户批准(分两部分:Markdown 列表 +
ask_user_tool),然后构建 N 个相互独立的单元素载荷(共享contentType/contentSpaceOrFolderId;每项分别填写title+prompt)。**绝不合并成一个inputs数组——每项调用一次。**流程 →references/bulk-batching.md。
完整架构 → references/content-write-tool.md;载荷演练 → examples/create-content-call.md。
第 5 步:执行创建调用
使用第 4 步的 payload 调用 create_cms_content;服务端会生成并验证内容,然后返回记录。复杂类型可能需要更长时间。
批量内容
5a. 调用前确认(统一批准) — 对所有项目进行一次确认(避免每次调用都弹出提示)。在聊天中显示 Ready to create all **<N>** content items in your org. Proceed?,然后发送第 5a 步的批准提示。Yes, create all → 5b;Cancel → 结束会话。
5b. 并行发送 N 个单项调用,遵循 references/bulk-batching.md:恰好调用 N 次 create_cms_content,每次使用一个包含 1 个元素的 inputs 数组,并在同一轮中并行发送全部调用。部分失败 → 登记成功项,并显示失败项(主题 + 错误),发送重试提示(重试会将失败项作为新的并行调用重新发送)。全部失败 → 先应用 references/error-recovery.md 中的“批量全部失败重试保护”规则(仅限批量全部失败分支)。
第 6 步:显示内容正文和摘要
成功时,按 assets/display-formats.md 显示摘要表 + 内容正文表(使用真实 Markdown,包含每个字段;创建和编辑均相同)。绝不可折叠为一行 title · status · id — 摘要表必须包含 Content Key + Managed Content ID(仅省略响应中不存在的字段)。失败时,使用 references/error-recovery.md;逐字显示错误,并通过 ask_user_tool 询问:Retry / Refine goal and retry / Cancel — 但 type-class-unsupported 除外(sfdc_cms__media / image / video),此情况必须停止(原则 15):仅逐字显示以下固定文本(不得添加前言或改写),然后结束本轮:Content generation isn't supported for content type \` (type class: ``). This skill can't author that type class. To create or edit this content, use the Salesforce CMS UI directly.` 验证由服务端负责。
第 7 步:操作后续循环
显示内容正文(创建或编辑)后,发送 assets/questions.md 中的第 7 步提示(按数量选择单项或批量版本)。按以下方式处理:
Edit content→ 第 8 步Publish content/Publish all→ 携带所有变体 ID 进入第 9 步Publish subset→ 使用assets/questions.md中的发布子集模板,按编号询问要发布的项目,然后携带所选变体 ID 进入第 9 步End session→ 输出一行:Session ended. Content saved as draft.并退出。
步骤 8、9、10:编辑 / 发布 / 发布后
完整操作详情 → references/edit-publish-workflow.md。 这三个步骤都仅使用 MCP——不使用 SOQL 或 CLI(通过 content-readonly 读取,通过 content-write 写入)。关键摘要:
- 步骤 8——编辑(
update_cms_content_variant)。8a 确定范围(单项,或针对批量编辑使用步骤 8a 提示词)→ 8b 编辑指令提示词(原文照用,适用于所有选中项)→ 8c 载荷(variantId使用该项最新响应中的 ID,或步骤 0-U 的 ID;prompt原文照用;仅在重命名时重新发送title)→ 8d 调用(批量 = 并行调用 N 次)→ 返回步骤 6,显示完整更新后的正文及每个字段(不是差异表;若响应中缺少内容,则通过get_content_variant重新获取),然后进入步骤 7。失败时 →Retry / Refine edit instruction and retry / Cancel;批量全部失败时 → 使用错误恢复防护措施。 - 步骤 9——发布(通过
variantIds调用publish_content)。9a 确定范围(全部 / 子集 / 默认为全部)→ 9b 调用(使用会话中的 ID,或步骤 0-P 中已验证的 ID——直接入口在确认后结束本轮,不进入步骤 10)→ 9c 成功后,将每个已发布项注册表中的publishStatus从 draft 改为published(必须——步骤 10 会据此筛选),逐字输出assets/display-formats.md中的发布确认信息 (Content published successfully.+ Title/Managed Content ID/Variant ID)——不得改写为Content is live或使用部署 ID 相关表述,然后进入步骤 10。部分或全部失败时 → 使用错误恢复防护措施 + 重试提示词。 - **步骤 10——发布后。**调用步骤 10 提示词;可选项取决于
workspaceMethod(uibundle包含渲染选项,manual隐藏该选项)。会话内发布时,两种方法都必须调用此步骤——跳过此步骤直接输出Session ended.属于回归问题。Create more content→ 从步骤 1 开始重新执行完整流程(静默处理——不询问“接下来要做什么?”,等待用户的下一条消息)→ 步骤 2 → 步骤 3;不要复用本次运行的工作区。Render…→ 将channelId、contentKeys(仅限publishStatus=published)、contentTypeFqn、uiBundleDeveloperName、uiBundleMasterLabel交给experience-cms-content-render;若已发布项数为 0 → 输出“没有已发布项”提示行 + 重新调用该提示词。End session→Session ended.
错误处理
references/error-recovery.md — 完整的错误信号 → 响应映射:create_cms_content / update_cms_content_variant / publish_content 服务端失败、批量部分失败、同级项终止状态、超出范围的请求。
跨技能集成
- 发现 / 定义 ContentTypeBundle(仅步骤 2 的委派路径,不适用于快速路径)→
experience-cms-content-type-generate(步骤 2a–2d 中的载荷 +status路由)。 - 将已发布内容渲染为 UIBundle(步骤 10)→
experience-cms-content-render(交接参数 + 步骤 10 中的workspaceMethod=uibundle门槛)。
关键原则
全部 15 条原则的完整内容 → references/principles.md(权威索引;以上各步骤正文也都逐条落实):(1)按顺序执行工作流,(2)调用即执行工作,(3)仅限服务端生成,(4)用户目标原文照用,(5)委派时由同级技能负责类型,(6)工作区依据用户 / UIBundle 决定——绝不推断或使用 SOQL,(7)取消即终止,(8)显示内容保持一致,(9)会话注册表 + 稳定的变体 ID,(10)操作后循环,(11)批量操作 = 每项并行调用一次,(12)发布范围默认为全部,(13)先路由意图,再校验标识符,(14)出现偏离立即停止,(15)不支持的类型-类别必须停止。标识符 → references/identifier-resolution.md。