experience-search-coordinate
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSearch Coordinator
搜索协调器
Routes search requests to the correct sub-workflow — structured CMS content or media — and runs both when a request mixes the two.
A pointer below is a required action, not FYI — open that file before continuing past that point; this skill has drifted before from steps followed off memory.
→ Read将搜索请求路由到正确的子工作流——结构化CMS内容或媒体——当请求混合两种类型时,会同时运行两者。
下方的标记是必填操作,而非仅供参考——在继续之前请打开该文件;此前曾出现过凭记忆执行步骤导致Skill偏离要求的情况。
→ ReadScope
适用范围
This skill is for SEARCHING FOR existing content or media, not creating new content or images.
Use this skill when the user wants to:
- Search for articles, blog posts, news, FAQs, events, products, or custom content
- Search for images, logos, icons, photos, graphics, banners, hero images, audio clips, videos, or documents
- Reuse existing assets instead of creating new ones, or any combination of the above in one request
DO NOT use this skill when the user wants to:
- Generate new content (use )
experience-cms-content-generate - Generate new images (use image generation tools)
- Define content type schemas (use )
experience-cms-content-type-generate - Apply brand guidelines (use )
experience-cms-brand-apply - Create, edit, or publish content records
此Skill仅用于搜索现有内容或媒体,不用于创建新内容或图片。
当用户需要以下操作时使用此Skill:
- 搜索文章、博客文章、新闻、常见问题、活动、产品或自定义内容
- 搜索图片、标志、图标、照片、图形、横幅、首屏图、音频片段、视频或文档
- 复用现有资产而非创建新资产,或在一个请求中组合上述任意操作
当用户需要以下操作时请勿使用此Skill:
- 生成新内容(使用)
experience-cms-content-generate - 生成新图片(使用图片生成工具)
- 定义内容类型架构(使用)
experience-cms-content-type-generate - 应用品牌规范(使用)
experience-cms-brand-apply - 创建、编辑或发布内容记录
Step 1: Determine Channel Scope
步骤1:确定渠道范围
Mandatory on every request that reaches it — never skip straight to Step 2. No phrasing of the request ("just find me an article," a plain keyword search, etc.) skips this step's local-file scan. If you're about to call in Step 2 without having scanned for this turn, STOP and come back here first.
search_metadatauiBundles/*/public/content-metadata.json- Explicit given — use it directly, skip discovery entirely, proceed to the scope rule below.
channelId - Named uiBundle/app, no — resolve that uiBundle's
channelId; if it doesn't resolve, fall through to point 3 as if nothing was named.channelId - Otherwise, discover from the local project — scan every file (never gate this on server-side deployment status) and collect the
uiBundles/*/public/content-metadata.jsons found. Zero → public channels only. Exactly one → public plus that channel. More than one → ask the user which one viachannelId.ask_followup_question
→ Read § "Step 1 points 1-3" for the full discovery mechanics before acting on points 1-3 above. Proceed to Step 2 once scope is determined.
references/scope-resolution.mdScope rule (applies whether the was user-provided or discovered): scope is always public channels (, no field) plus that one (a separate call with set to it, no field) — never resolve a separate ID to represent "public," and never send and in the same call. This scope decides how many search calls Steps 3 and 4 make: no in scope → one search call (public channels only). A in scope → two search calls (public channels, then that specific ), with results merged before presenting.
channelIdcontentAccessScope: "Public"channelIdschannelIdchannelIdscontentAccessScopecontentAccessScopechannelIdschannelIdchannelIdchannelId**每个到达此步骤的请求都必须执行此操作——切勿直接跳至步骤2。**无论请求如何表述(例如“帮我找一篇文章”、纯关键词搜索等),都不能跳过此步骤的本地文件扫描。如果您打算在步骤2中调用但尚未扫描文件,请立即停止并返回此步骤。
search_metadatauiBundles/*/public/content-metadata.json- 明确提供——直接使用该ID,跳过所有发现流程,继续执行下方的范围规则。
channelId - 指定了uiBundle/应用,但未提供——解析该uiBundle的
channelId;如果无法解析,则按第3点处理,如同未指定任何内容。channelId - 其他情况,从本地项目中发现——扫描所有文件(切勿根据服务器端部署状态限制此操作),并收集找到的
uiBundles/*/public/content-metadata.json。若无结果→仅使用公共渠道。若只有一个结果→使用公共渠道加上该渠道。若有多个结果→通过channelId询问用户选择哪一个。ask_followup_question
→ 在执行上述1-3点之前,请阅读中“步骤1的1-3点”部分,了解完整的发现机制。确定范围后,继续执行步骤2。
references/scope-resolution.md**范围规则(无论是用户提供还是发现的):范围始终包含公共渠道(,无字段)加上一个(单独调用,设置为该ID,无字段)——切勿解析单独的ID来代表“公共”,也切勿在同一调用中同时发送和。**此范围决定了步骤3和4需要执行多少次搜索调用:范围中无→一次搜索调用(仅公共渠道)。范围中有→两次搜索调用(公共渠道,然后是特定的),结果合并后再呈现。
channelIdcontentAccessScope: "Public"channelIdschannelIdchannelIdscontentAccessScopecontentAccessScopechannelIdschannelIdchannelIdchannelIdStep 2: Determine Content Type and Route
步骤2:确定内容类型并路由
Precondition: Step 1 must have already run in this turn (its channel-scope result is what point 5 below carries into Step 3/4). Step 1 runs unconditionally — even for a plain keyword search with no obvious channel angle, not only when the request names a channel or app.
-
Identify one or more distinct search intents in the request (e.g. "find a press release about our launch and a hero image for the page" is two intents). Run the rest of this step once per intent.If intents span both routes, sequence the routes — never interleave or merge them: run the Media Route (Step 4) to full completion for every media intent first, then the Content Route (Step 3) for every content intent. See Step 5.
-
Callon the
search_metadataMCP server using the intent itself as the query. Nometadata-groundingarray support —filtersis the only narrowing parameter, passed top-level:metadataTypejavascriptsearch_metadata({ query: "<the user's intent>", metadataType: "ContentTypeBundle", limit: 100 })
Each candidate already includes a full composite identifier (e.g. ) — use it as returned; never reconstruct it.
00DVW00000CfBQP2A3::0T1VW000008sow60AA::ContentTypeBundleCheck the outcome before doing anything else:
- is unavailable (the call errors/times out) — you MUST call
metadata-grounding(the workspace content-type fallback) before any Step 3/4 search tool; do not attemptget_content_types_for_workspace, there's nothing to look up, and do not skip straight to a search tool on an assumed FQN.query_metadata - Zero candidates returned — ask the user one clarifying question to narrow the intent (, same question/options as the "intent itself is ambiguous" case at the end of this step), then retry
ask_followup_questiononce with the clarified query:search_metadata- Still zero candidates after that one retry — apply the workspace content-type fallback. Do not ask a second clarifying question.
- One or more candidates on the retry — continue to point 3.
- One or more candidates on the first call — continue to point 3.
Fallback chain when doesn't produce a usable candidate list → Read before running it: "Workspace content-type fallback" first, then "Wording fallback" as a last resort.
search_metadatareferences/content-type-discovery.md-
Callwith each candidate's identifier from point 2 (cap at top 5, batched into one
query_metadataarray):metadataIdentifiersjavascriptquery_metadata({ metadataIdentifiers: ["00DVW00000CfBQP2A3::0T1VW000008sow60AA::ContentTypeBundle"] })Read each entry's—typeDetails[].properties,mixins, andtypeClasseslive there, not in theapiNameresponse.search_metadata -
Filter for supported types first, THEN decide the route among survivors — do not conflate the two:
- Discard any candidate whose lacks
properties.mixins— only delivery-API-enabled types are searchable.sfdc_cms:deliveryApiEnabled - Of the remainder, discard any whose lacks
properties.typeClasses. This is the single "supported for search" gate, not a content/media split —sfdc_cms__structuredappears on both structured-content types and media types, so it only separates searchable types from unsearchable ones (e.g.sfdc_cms__structuredcarriessfdc_cms__emailbut notsfdc_cms__content, and must be discarded).sfdc_cms__structured - Zero survive — tell the user which types were found but aren't supported, then stop (don't guess a route). Some, but not all, survive — tell the user which got filtered out (plain statement, not a question), then continue with survivors. All survive — no message needed. → Read § "Filter-result messages" for exact wording.
references/content-type-discovery.md - Route on the top-ranked survivor's (order returned by
properties.typeClasses): containssearch_metadata→ Media Route (Step 4); otherwise → Content Route (Step 3).sfdc_cms__media - Collect the FQN(s) — the top-ranked survivor's . Add other surviving candidates' FQNs too if clearly relevant to the same intent and sharing the same classification, passing all as one comma-separated
properties.apiNamevalue rather than searching per type.contentTypeFqn
- Discard any candidate whose
-
Carry the scope from Step 1 (public channels only, or public channels plus a) into whichever route is invoked — see the
channelIdfield in each route below.channelIds
If intent itself is ambiguous (e.g. "find me some content" with no hint of type or subject) → Read § "Intent itself is ambiguous" for the exact question/options before calling . Do not guess.
references/content-type-discovery.mdsearch_metadata前置条件:步骤1必须已在当前请求中执行(其渠道范围结果将带入步骤3/4的第5点)。步骤1必须无条件执行——即使是无明显渠道指向的纯关键词搜索,而不仅仅是当请求指定渠道或应用时。
-
识别请求中的一个或多个不同搜索意图(例如“找一篇关于我们发布会的新闻稿,以及页面用的首屏图”包含两个意图)。对每个意图执行此步骤的其余部分。**如果意图跨越两个路由,请按顺序执行路由——切勿交错或合并:**先针对所有媒体意图完整执行媒体路由(步骤4),再针对所有内容意图执行内容路由(步骤3)。详见步骤5。
-
调用:在
search_metadataMCP服务器上,将意图本身作为查询参数调用该工具。不支持metadata-grounding数组——仅可通过顶级参数filters来缩小范围:metadataTypejavascriptsearch_metadata({ query: "<the user's intent>", metadataType: "ContentTypeBundle", limit: 100 })
每个候选结果已包含完整的复合标识符(例如)——直接使用返回值;切勿自行重构。
00DVW00000CfBQP2A3::0T1VW000008sow60AA::ContentTypeBundle在执行其他操作前先检查结果:
- 不可用(调用出错/超时)——必须在调用步骤3/4的搜索工具前调用
metadata-grounding(工作区内容类型备选方案);不要尝试get_content_types_for_workspace,因为没有可查询的内容,也不要假设FQN直接跳转到搜索工具。query_metadata - 未返回候选结果——向用户提出一个澄清问题以缩小意图范围(使用,与本步骤末尾“意图本身不明确”场景使用相同的问题/选项),然后使用澄清后的查询重试一次
ask_followup_question:search_metadata- 重试后仍无结果——应用工作区内容类型备选方案。请勿提出第二个澄清问题。
- 重试后返回一个或多个候选结果——继续执行第3点。
- 首次调用返回一个或多个候选结果——继续执行第3点。
当无法生成可用候选列表时的备选流程→ 在执行前请阅读:优先使用“工作区内容类型备选方案”,最后使用“措辞备选方案”。
search_metadatareferences/content-type-discovery.md-
调用:传入第2点中每个候选结果的标识符(最多取前5个,批量放入
query_metadata数组):metadataIdentifiersjavascriptquery_metadata({ metadataIdentifiers: ["00DVW00000CfBQP2A3::0T1VW000008sow60AA::ContentTypeBundle"] })读取每个条目的——typeDetails[].properties、mixins和typeClasses存储在此处,而非apiName的响应中。search_metadata -
先筛选支持的类型,再从剩余类型中决定路由——切勿混淆这两个步骤:
- 剔除中缺少
properties.mixins的候选结果——仅启用交付API的类型可被搜索。sfdc_cms:deliveryApiEnabled - 在剩余结果中,剔除中缺少
properties.typeClasses的候选结果。这是唯一的“支持搜索”筛选条件,而非内容/媒体的拆分条件——sfdc_cms__structured同时出现在结构化内容类型和媒体类型中,因此它仅区分可搜索类型与不可搜索类型(例如sfdc_cms__structured包含sfdc_cms__email但不包含sfdc_cms__content,必须被剔除)。sfdc_cms__structured - 无剩余结果——告知用户找到的类型均不支持,然后停止操作(不要猜测路由)。部分剩余——告知用户哪些类型被筛选掉(直接陈述,而非提问),然后继续处理剩余结果。全部剩余——无需发送消息。→ 请阅读中的“筛选结果消息”部分,获取准确措辞。
references/content-type-discovery.md - 根据排名最高的剩余结果的决定路由(按
properties.typeClasses返回的顺序):包含search_metadata→媒体路由(步骤4);否则→内容路由(步骤3)。sfdc_cms__media - 收集FQN——排名最高的剩余结果的。如果其他剩余候选结果与同一意图明显相关且属于同一分类,也添加其FQN,将所有FQN作为逗号分隔的
properties.apiName值传入,而非按类型分别搜索。contentTypeFqn
- 剔除
-
将步骤1的范围(仅公共渠道,或公共渠道加一个)带入调用的路由——详见下方每个路由中的
channelId字段。channelIds
如果意图本身不明确(例如“帮我找一些内容”,未提及类型或主题)→ 在调用前,请阅读中的“意图本身不明确”部分,获取准确的问题/选项。切勿猜测。
search_metadatareferences/content-type-discovery.mdStep 3: Content Route
步骤3:内容路由
Follow this sequence for each intent Step 2 routed here. The content type FQN(s) are already known from Step 2.
-
Build the search query:
- Extract keywords — concrete nouns and named subjects that would appear in the content's title or body. Use domain-specific synonyms, max 10 terms, joined with . E.g. "blog posts about sustainable business practices" →
OR.sustainable OR sustainability OR business OR environmental - Extract taxonomies — descriptive qualities, categories, or topical tags only (adjectives, categories, attributes — not concrete nouns). Stringify as , or
{"OR": ["term1", "term2"]}if none apply. E.g. "sustainable business practices and environmental responsibility" →"{}"; "FAQs about password resets" →{"OR": ["Business", "Corporate", "Environment", "Responsibility"]}(no descriptive/categorical terms)."{}" - Load for the request payload structure. Set
assets/search-payload-template.jsonto the comma-separated FQN list collected in Step 2.contentTypeFqnandcontentAccessScopeare mutually exclusive — never send both in the same call — so they're set per-call in point 3 below, not here.channelIds
- Extract keywords — concrete nouns and named subjects that would appear in the content's title or body. Use domain-specific synonyms, max 10 terms, joined with
-
Confirm with the user — required two-message pattern (labeled-parameters chat message, thenwith
ask_followup_question/Yes - search now/Edit search). Never put the labeled list insideCancel's text — it strips formatting. → Readask_followup_question§ "Confirming the query before searching" for templates.references/content-route.md -
Execute the search call(s) per the scope from Step 1 — one call for public-only scope, two (public + channel-scoped) when ais in scope. → Read
channelId§ "Executing the search call(s)" before parsing results — array/merge rules.references/content-route.md -
Present up to 5 unique results total (de-duplicated byfor display only — an item found under more than one channel still appears once here), grouped by content type, with a
managedContentKeyoption if more remain. Each item shows its Channel as a per-item field — never the grouping key:Load MoretextI found 3 content items: Editorial (c__Editorial): 1. <title> — Channel: Public 2. <title> — Channel: <uiBundle> Blog (sfdc_cms__blog): 3. <title> — Channel: PublicOnly one content type FQN in scope → the heading may be omitted (still one group); the per-item Channel field is always shown. If an item exists under multiple channels, show its first/primary channel here — the choice between channels happens after selection (point 5), not at presentation time. -
User selects one, several, or all items. For each selected item whose delivery-details array has more than one entry, ask which channel's copy to use — oneoption per entry, named from
ask_followup_question— before displaying its details; items with zero or one entry go straight to display. ShowmanagedContentChannelDetails.name,managedContentId,managedContentKey, channel, and — only for alanguage/PUBLIC_UNAUTHENTICATEDentry with aCOMMUNITY, never acontentUrlone — the full Unauthenticated URL (all query parameters). → ReadWEB_APP§ "Disambiguating channel at selection" before asking — pass the channel names asreferences/content-route.md'sask_followup_questionarray, never inline them in the question text.options -
If the channelId in scope came from uiBundle discovery (skip entirely for public-only scope or a user-suppliedwith no uiBundle), offer the
channelIdhand-off using the same two-message pattern, passing each item'sexperience-cms-content-render, content type FQN, its chosen entry'stitle(channel ID) only when it has a delivery entry — omit for a zero-entry item, never a placeholder, and either its Unauthenticated URL or, if absent, itsmanagedContentChannelDetails.idasmanagedContentKey(the receiving skill's field name). → ReadcontentKey§ "Offering the render hand-off" for the full procedure.references/content-route.md
→ Read for the complete end-to-end worked example.
references/content-route.md对步骤2路由至此的每个意图执行以下流程。内容类型FQN已从步骤2中获取。
-
构建搜索查询:
- 提取关键词——内容标题或正文中会出现的具体名词和指定主题。使用领域特定同义词,最多10个术语,用连接。例如“关于可持续商业实践的博客文章”→
OR。sustainable OR sustainability OR business OR environmental - 提取分类法——仅提取描述性特质、类别或主题标签(形容词、类别、属性——非具体名词)。格式化为,若无则为
{"OR": ["term1", "term2"]}。例如“可持续商业实践与环境责任”→"{}";“关于密码重置的常见问题”→{"OR": ["Business", "Corporate", "Environment", "Responsibility"]}(无描述性/分类术语)。"{}" - 加载获取请求负载结构。将
assets/search-payload-template.json设置为步骤2中收集的逗号分隔FQN列表。contentTypeFqn和contentAccessScope互斥——切勿在同一调用中同时发送两者,因此它们将在下方第3点中按调用设置,而非在此处设置。channelIds
- 提取关键词——内容标题或正文中会出现的具体名词和指定主题。使用领域特定同义词,最多10个术语,用
-
与用户确认——必须使用两步消息模式(带标签参数的聊天消息,然后是带有/
Yes - search now/Edit search选项的Cancel)。切勿将标签列表放入ask_followup_question的文本中——它会移除格式。→ 请阅读ask_followup_question中的“搜索前确认查询”部分,获取模板。references/content-route.md -
根据步骤1的范围执行搜索调用——仅公共范围执行一次调用,范围包含时执行两次调用(公共+渠道范围)。→ 在解析结果前,请阅读
channelId中的“执行搜索调用”部分——了解数组/合并规则。references/content-route.md -
最多展示5条唯一结果(仅在展示时按去重——在多个渠道下找到的同一项目仍仅显示一次),按内容类型分组,若有更多结果则提供
managedContentKey选项。每个项目需显示其渠道作为单独字段——切勿将渠道作为分组键:Load Moretext我找到了3个内容项目: Editorial (c__Editorial): 1. <标题> — 渠道:Public 2. <标题> — 渠道:<uiBundle> Blog (sfdc_cms__blog): 3. <标题> — 渠道:Public范围中仅有一种内容类型FQN→可省略标题(仍为一组);每个项目的渠道字段始终显示。如果一个项目存在于多个渠道中,此处显示其首个/主渠道——渠道选择在选择项目后进行(第5点),而非展示时。 -
用户选择一个、多个或全部项目。对于每个交付详情数组包含多个条目的选中项目,询问用户使用哪个渠道的副本——每个条目对应的一个选项,选项名称来自
ask_followup_question——然后再展示详情;交付详情数组为0或1条的项目直接展示详情。展示managedContentChannelDetails.name、managedContentId、managedContentKey、渠道,以及——仅当条目为language/PUBLIC_UNAUTHENTICATED且包含COMMUNITY时,contentUrl条目除外——完整的未认证URL(所有查询参数)。→ 在提问前,请阅读WEB_APP中的“选择时明确渠道”部分——将渠道名称作为references/content-route.md的ask_followup_question数组传入,切勿嵌入问题文本中。options -
如果范围中的channelId来自uiBundle发现(仅公共范围或用户提供的无uiBundle的需跳过此步骤),使用相同的两步消息模式提供
channelId交接,传入每个项目的experience-cms-content-render、内容类型FQN、所选条目的title(渠道ID)仅当该项目有交付条目时——无交付条目的项目省略该字段,切勿使用占位符,以及其未认证URL(若存在),否则传入其managedContentChannelDetails.id作为managedContentKey(接收Skill的字段名)。→ 请阅读contentKey中的“提供渲染交接”部分,获取完整流程。references/content-route.md
→ 请阅读获取完整的端到端示例。
references/content-route.mdStep 4: Media Route
步骤4:媒体路由
Follow this sequence for each intent Step 2 routed here. The media content type FQN (e.g. , , , ) is already known from Step 2 — never assume it's an image; use whatever FQN Step 2 discovered for this intent.
sfdc_cms__imagesfdc_cms__audiosfdc_cms__videosfdc_cms__document-
Present available search sources via— no other tool calls yet. Only the sources whose tools you actually have (via introspection), plus "Other", each as its own option. Wait for the user's selection before any tool call. → Read
ask_followup_question§ "Presenting available search sources" for the full template.references/media-route.md -
Build the query, then confirm with the user before searching — required two-message pattern, in the same turn:
- Search using keywords (): extract keywords (concrete nouns, max 10 terms) and taxonomies (descriptive/style/mood/category terms — extract every one the query actually contains; don't default to empty just because keywords were found). E.g. "luxury apartment with river view" → keywords
search_media_cms_channels, taxonomiesapartment OR villa OR penthouse OR residence; "car" → taxonomies{"OR": ["Luxury", "Premium", "Waterfront", "Riverside"]}(no descriptive terms). Build the payload with"{}"set to the FQN(s) from Step 2,contentTypeFqnset to a locale (searchLanguage,en_US, ... — defaultes_MX; required, never null/omitted),en_US. → ReadsearchLimit: 5for full worked examples.references/media-route.md - Search using Data 360 hybrid search () — pass the user's query as-is to
search_electronic_media, no extraction needed.searchQuery - Other — ask for a direct URL, asset library path, or specific system to check (no confirmation step, since no tool is called).
→ Read§ "Confirming the query before searching" for the confirmation message templates (labeled-parameters chat message, thenreferences/media-route.mdwithask_followup_question/Yes - search now/Edit search).Cancel - Search using keywords (
-
Execute the search call(s) per the scope from Step 1 — one call for public-only scope, two (public + channel-scoped) when ais in scope; Data 360 hybrid search ignores channel scope entirely. → Read
channelId§ "Executing the search call(s)" before parsing results — array/merge rules.references/media-route.md -
Present all unique results via, grouped by content type — one option per result (de-duplicated by unique identifier for display only — an item found under more than one channel still appears once here), labeled with title, content type, and channel (e.g.
ask_followup_question). Mirrors the Content Route: content type is the grouping key, channel is a per-item field. Never auto-select.Product Launch Hero Banner (sfdc_cms__image) — Public -
User selects an item. If its delivery-details array has more than one entry, ask which channel's copy to use — one option per entry, named from— before displaying details. Show Content Name, Content Type, channel, and — only for a
managedContentChannelDetails.name/PUBLIC_UNAUTHENTICATEDentry with aCOMMUNITY, never acontentUrlone — the full Unauthenticated URL (all query parameters). → ReadWEB_APP§ "Disambiguating channel at selection" before asking — pass the channel names asreferences/media-route.md'sask_followup_questionarray, never inline them in the question text.options -
Offer the render hand-off — always, with no uiBundle gating (unlike the Content Route's offer, which only appears when a uiBundle channel was in scope). Same two-message pattern: plain-text mention of the item, thenwith
ask_followup_question/Yes. OnNo, dispatch viaYes— never the built-in Skill tool (separate registry, returnsmcp__skill_bridge__load_skill("experience-cms-content-render")) — passing the selected item'sUnknown skill, content type FQN, the chosen entry'stitle(channel ID) only when it has a delivery entry — this route explicitly supports zero-entry items, so omit the channel ID for those rather than readingmanagedContentChannelDetails.idoff nothing, and either its Unauthenticated URL or, if absent, its.idasmanagedContentKey(the receiving skill's field name). If the load call fails, tell the user the hand-off failed and stop. OncontentKey, stop — the search is complete; do not apply the URL yourself as a fallback.No
→ Read for the complete worked example.
references/media-route.md对步骤2路由至此的每个意图执行以下流程。媒体内容类型FQN(例如、、、)已从步骤2中获取——切勿假设是图片;使用步骤2为此意图发现的任意FQN。
sfdc_cms__imagesfdc_cms__audiosfdc_cms__videosfdc_cms__document-
**通过展示可用搜索来源——暂不调用其他工具。**仅展示您实际拥有的来源(通过自省),加上“其他”,每个来源作为一个选项。等待用户选择后再调用工具。→ 请阅读
ask_followup_question中的“展示可用搜索来源”部分,获取完整模板。references/media-route.md -
构建查询,然后在搜索前与用户确认——必须使用两步消息模式,在同一请求中完成:
- 使用关键词搜索():提取关键词(具体名词,最多10个术语)和分类法(描述性/风格/情绪/类别术语——提取查询中实际包含的所有术语;不要因为找到关键词就默认分类法为空)。例如“带河景的豪华公寓”→ 关键词
search_media_cms_channels,分类法apartment OR villa OR penthouse OR residence;“汽车”→ 分类法{"OR": ["Luxury", "Premium", "Waterfront", "Riverside"]}(无描述性术语)。构建负载时,将"{}"设置为步骤2中的FQN,contentTypeFqn设置为区域设置(searchLanguage、en_US……默认es_MX;必填,切勿留空/省略),en_US。→ 请阅读searchLimit: 5获取完整示例。references/media-route.md - 使用Data 360混合搜索()——直接将用户查询传入
search_electronic_media,无需提取。searchQuery - 其他——请求用户提供直接URL、资产库路径或要检查的特定系统(无需确认步骤,因为不调用工具)。
→ 请阅读中的“搜索前确认查询”部分,获取确认消息模板(带标签参数的聊天消息,然后是带有references/media-route.md/Yes - search now/Edit search选项的Cancel)。ask_followup_question - 使用关键词搜索(
-
根据步骤1的范围执行搜索调用——仅公共范围执行一次调用,范围包含时执行两次调用(公共+渠道范围);Data 360混合搜索完全忽略渠道范围。→ 在解析结果前,请阅读
channelId中的“执行搜索调用”部分——了解数组/合并规则。references/media-route.md -
通过展示所有唯一结果,按内容类型分组——每个结果对应一个选项(仅在展示时按唯一标识符去重——在多个渠道下找到的同一项目仍仅显示一次),标注标题、内容类型和渠道(例如
ask_followup_question)。与内容路由一致:内容类型为分组键,渠道为每个项目的字段。切勿自动选择。Product Launch Hero Banner (sfdc_cms__image) — Public -
用户选择一个项目。如果其交付详情数组包含多个条目,询问用户使用哪个渠道的副本——每个条目对应一个选项,选项名称来自——然后再展示详情。展示内容名称、内容类型、渠道,以及——仅当条目为
managedContentChannelDetails.name/PUBLIC_UNAUTHENTICATED且包含COMMUNITY时,contentUrl条目除外——完整的未认证URL(所有查询参数)。→ 在提问前,请阅读WEB_APP中的“选择时明确渠道”部分——将渠道名称作为references/media-route.md的ask_followup_question数组传入,切勿嵌入问题文本中。options -
提供渲染交接——始终提供,无uiBundle限制(与内容路由的交接不同,内容路由仅当范围包含uiBundle渠道时才提供)。使用相同的两步消息模式:提及项目的纯文本消息,然后是带有/
Yes选项的No。用户选择ask_followup_question时,通过Yes调度——切勿使用内置Skill工具(单独注册表,会返回mcp__skill_bridge__load_skill("experience-cms-content-render"))——传入选中项目的Unknown skill、内容类型FQN、所选条目的title(渠道ID)仅当该项目有交付条目时——此路由明确支持无交付条目的项目,因此此类项目省略渠道ID,切勿从空值中读取managedContentChannelDetails.id,以及其未认证URL(若存在),否则传入其.id作为managedContentKey(接收Skill的字段名)。如果加载调用失败,告知用户交接失败并停止操作。用户选择contentKey时,停止操作——搜索完成;切勿自行使用URL作为备选方案。No
→ 请阅读获取完整示例。
references/media-route.mdStep 5: Present Combined Results
步骤5:展示合并结果
When a request mixes media and content intents, run the two routes sequentially, each to full completion, not interleaved and not merged into one combined presentation:
- Media Route first — for every media intent, run Step 4 in full: present sources, build/confirm the query, search, present results, let the user select, and (point 6) offer the hand-off (Yes/No). Finish this entire route — including the offer — before starting the Content Route.
experience-cms-content-render - Content Route second — for every content intent, run Step 3 in full: build/confirm the query, search, present results grouped by content type (channel shown per-item), let the user select, and (point 6) offer the hand-off if a uiBundle channel is in scope.
experience-cms-content-render
Each route's results are labeled and presented on their own (e.g. "Images:" for the Media Route's output, then "Articles:" for the Content Route's) — never merge the two into one undifferentiated list, and never hold Media Route's results back to present alongside Content Route's.
当请求混合媒体和内容意图时,按顺序执行两个路由,每个路由完整执行,切勿交错或合并为一个展示:
- 先执行媒体路由——针对所有媒体意图,完整执行步骤4:展示来源、构建/确认查询、搜索、展示结果、让用户选择,以及(第6点)提供交接(是/否)。完成整个路由(包括交接)后,再开始执行内容路由。
experience-cms-content-render - 再执行内容路由——针对所有内容意图,完整执行步骤3:构建/确认查询、搜索、按内容类型分组展示结果(每个项目显示渠道)、让用户选择,以及(第6点)如果范围包含uiBundle渠道,则提供交接。
experience-cms-content-render
每个路由的结果需单独标注并展示(例如媒体路由输出标注为“图片:”,内容路由输出标注为“文章:”)——切勿将两者合并为一个无差别的列表,也切勿保留媒体路由的结果与内容路由结果一起展示。
Error Handling
错误处理
| Error | Response |
|---|---|
No | "No content search connection is configured. Please connect a content-readonly MCP server." |
| Neither media tool available | "No automated media search sources are currently configured. Please provide a direct URL or asset library path." |
| Apply the fallback chain in |
| No search results (either route) | "No [content/media] found. Try broader keywords, removing descriptive terms, or a different [content type/source]." |
| Invalid user selection | Re-display options and ask again |
| Tool returns error (invalid input, missing argument, or otherwise) | Show error message, offer retry with corrected parameters on that same tool — never fall through to the other route's search tool as a workaround (see Key Principle 3) |
| Search tool on the connected server returns a server error (5xx, timeout, connection failure — not "no results") | Fail the call — do NOT silently retry against a different server. Tell the user to check that server's connection/session and wait before retrying. |
Never silently fail on a route the user asked for. If one route in a mixed request comes up empty, still present the other route's results and say so explicitly. This does not mean substituting a different server when the connected one errors — see the server-error row above.
| 错误 | 响应 |
|---|---|
通过自省未找到 | "未配置内容搜索连接。请连接一个内容只读MCP服务器。" |
| 无可用媒体工具 | "当前未配置自动化媒体搜索来源。请提供直接URL或资产库路径。" |
| 应用 |
| 无搜索结果(任一路由) | "未找到[内容/媒体]。尝试更宽泛的关键词、移除描述性术语或更换[内容类型/来源]。" |
| 用户选择无效 | 重新展示选项并再次询问 |
| 工具返回错误(无效输入、缺少参数或其他错误) | 展示错误消息,提供使用修正后的参数重试该工具的选项**——切勿作为备选方案切换到另一路由的搜索工具**(参见关键原则3) |
| 关联服务器上的搜索工具返回服务器错误(5xx、超时、连接失败——而非“无结果”) | **终止调用——切勿静默重试其他服务器。**告知用户检查该服务器的连接/会话,等待后再重试。 |
**切勿静默终止用户请求的路由。**如果混合请求中的一个路由无结果,仍需展示另一路由的结果并明确告知。这并不意味着当关联服务器出错时切换到其他服务器——参见上述服务器错误行。
Key Principles
关键原则
- Resolve channel scope first — determine channel scope (Step 1) before any content-type discovery or search
- Search first, route second — +
search_metadatadecide the route; fall back toquery_metadata, then intent wording, only when that comes up empty (Step 2)get_content_types_for_workspace - Never cross-route, including on failure — content requests never hit media search tools and vice versa; if a route's search tool errors for any reason, fix and retry that same tool or stop and report the error — never fall through to the other route's tool as a workaround
- Metadata grounding is mandatory for content — discover content type FQNs dynamically, never hardcode them
- Media route starts text-only — present sources and wait before any tool call
- Confirm before searching (both routes) — user approves query parameters before execution
- Never auto-select — always wait for user choice, across channel scope and both routes
- Run mixed requests sequentially, Media Route first — complete it fully (including the render offer) before starting the Content Route; present each route's results as its own labeled set, never merged
- Handle errors gracefully — clear feedback and alternatives, per route
- Offer to render, don't assume — both routes require Yes/No confirmation before the hand-off; only the gating differs — Content Route offers it only when a uiBundle channel was actually in scope, Media Route always offers it
- Never fail over to a different server on a server error — fail the call and tell the user to check that server's session; don't silently retry elsewhere
- Group by content type, never by channel — in both routes, channel is always a per-item field, never the group heading
- Disambiguate channel at selection, not before — an item is shown once at presentation regardless of its delivery-details array length; only after selection do you ask which channel's copy to use, one option per entry by , in both routes
managedContentChannelDetails.name - Unauthenticated URL is public-channel-only — /
PUBLIC_UNAUTHENTICATEDentries only; never aCOMMUNITY(uiBundle) entry'sWEB_APP, in either routecontentUrl
- 先解析渠道范围——在任何内容类型发现或搜索前,确定渠道范围(步骤1)
- 先搜索,后路由——+
search_metadata决定路由;仅当无结果时,才依次使用query_metadata和意图措辞作为备选(步骤2)get_content_types_for_workspace - 切勿跨路由,包括出错时——内容请求永远不会调用媒体搜索工具,反之亦然;如果某路由的搜索工具因任何原因出错,修复并重试该工具或终止操作并报告错误——切勿作为备选方案切换到另一路由的工具
- 内容必须使用元数据关联——动态发现内容类型FQN,切勿硬编码
- 媒体路由从纯文本开始——先展示来源并等待用户选择,再调用工具
- 搜索前确认(两个路由)——用户在执行前需批准查询参数
- 切勿自动选择——在渠道范围和两个路由中,始终等待用户选择
- 混合请求按顺序执行,先媒体路由——完整执行媒体路由(包括渲染交接)后再开始内容路由;每个路由的结果单独标注展示,切勿合并
- 优雅处理错误——每个路由提供清晰的反馈和备选方案
- 提供渲染选项,勿假设——两个路由在交接前都需要用户确认是/否;仅限制条件不同——内容路由仅当范围包含uiBundle渠道时提供,媒体路由始终提供
- 服务器出错时切勿切换到其他服务器——终止调用并告知用户检查服务器会话;切勿静默重试其他服务器
- 按内容类型分组,切勿按渠道——在两个路由中,渠道始终是每个项目的字段,而非分组标题
- 选择时明确渠道,而非之前——展示时,无论项目的交付详情数组长度如何,均仅显示一次;仅在用户选择后,才询问使用哪个渠道的副本,每个选项对应,两个路由均如此
managedContentChannelDetails.name - 未认证URL仅适用于公共渠道——仅/
PUBLIC_UNAUTHENTICATED条目;两个路由中均不使用COMMUNITY(uiBundle)条目的WEB_APP",contentUrl