platform-mcp-tool-widget-coordinate

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Rendering a Custom MCP Tool Output With a Widget

使用Widget渲染自定义MCP工具输出

Coordinate two object-based Custom Lightning Types (CLTs) and an HXL widget to render the output of a custom MCP server tool whose implementation is an Apex
@InvocableMethod
. This skill never authors content directly — it loads and invokes leaf skills in dependency order, gates progress on user approval, and runs validation gates before reporting completion.
协调两个基于对象的自定义Lightning类型(CLT)和一个HXL widget,以渲染由Apex
@InvocableMethod
实现的自定义MCP服务器工具的输出。本技能从不直接编写内容——它会按依赖顺序加载并调用子技能,在用户批准后推进流程,并在报告完成前运行验证检查。

Scope

适用范围

Custom MCP server tools backed by an Apex Invocable Action only. The MCP tool returns the platform's invocable-action result envelope — an object with
actionName
,
isSuccess
, and an
outputValues
node that carries the tool's real payload. To render this envelope with a widget, model it as two object-based CLTs (
lightning__objectType
) of equal standing — the only reason there are two is that one must reference the other by name (a CLT cannot reference itself), so they need distinct deployed names. Name and describe each by what it actually models — never by an invented role-label pair like "Payload CLT"/"Envelope CLT" or "Inner CLT"/"Outer CLT":
  • The CLT that mimics the tool-result envelope, named
    <toolApiName>
    . Its
    outputValues
    property is typed to the other CLT via
    c__<responseCLT>
    .
  • The CLT that is the exact shape of the Invocable Action's response (
    @InvocableVariable
    fields on the
    @InvocableMethod
    response class), named
    <toolApiName>Response
    — "Response" here is not an invented role word, it's the same word the Apex source already uses for that class (e.g.
    GetAccountSummaryResponse
    ).
The widget grounds on the response fields (flat), and the default
renderer.json
in the envelope CLT
bridges the envelope nesting to the flat widget via
{!$attrs.outputValues.<field>}
.
Out of scope, route elsewhere:
  • Customizing an Apex-backed agent action output (Apex-backed CLT
    @apexClassType/...
    , single CLT, surface-specific renderer) →
    platform-lightning-type-widget-coordinate
    .
  • A standalone widget with no MCP tool / Lightning Type →
    platform-widget-generate
    .
  • Authoring only a CLT or only an Apex class →
    platform-custom-lightning-type-generate
    /
    platform-apex-generate
    .
Beta cardinality: the invocable-action result is a bulk array (
content[]
). For the beta release this skill models and renders a single response — the first element of
content[]
. The CLT envelope models one result object, not the
content[]
wrapper.

仅适用于由Apex Invocable Action支持的自定义MCP服务器工具。MCP工具会返回平台的invocable-action结果信封——一个包含
actionName
isSuccess
和承载工具实际负载的
outputValues
节点的对象。要使用widget渲染此信封,需将其建模为两个地位平等的基于对象的CLT
lightning__objectType
)——设置两个CLT的唯一原因是其中一个必须按名称引用另一个(CLT无法引用自身),因此它们需要不同的部署名称。请根据实际建模内容为每个CLT命名和描述——切勿使用诸如“Payload CLT”/“Envelope CLT”或“Inner CLT”/“Outer CLT”这类虚构的角色标签对:
  • 模拟工具结果信封的CLT,命名为
    <toolApiName>
    。其
    outputValues
    属性通过
    c__<responseCLT>
    类型化为另一个CLT。
  • 与Invocable Action响应
    @InvocableMethod
    响应类上的
    @InvocableVariable
    字段)完全匹配的CLT,命名为
    <toolApiName>Response
    ——此处的“Response”并非虚构的角色词,而是Apex源代码中该类已使用的词汇(例如
    GetAccountSummaryResponse
    )。
Widget基于响应字段(扁平化)构建,而信封CLT中的**默认
renderer.json
**通过
{!$attrs.outputValues.<field>}
将信封的嵌套结构桥接到扁平化的widget。
超出范围,请路由至其他技能:
  • 自定义基于Apex的代理动作输出(基于Apex的CLT
    @apexClassType/...
    ,单个CLT,特定界面渲染器)→
    platform-lightning-type-widget-coordinate
  • 不涉及MCP工具/Lightning Type的独立widget →
    platform-widget-generate
  • 仅编写CLT或仅编写Apex类 →
    platform-custom-lightning-type-generate
    /
    platform-apex-generate
Beta版基数限制: invocable-action结果为批量数组(
content[]
)。在Beta版本中,本技能仅建模并渲染单个响应——即
content[]
的第一个元素。CLT信封仅建模一个结果对象,而非
content[]
包装器。

How this differs from
platform-lightning-type-widget-coordinate

platform-lightning-type-widget-coordinate
的差异

Dimensionagent-action flow (
...lightning-type-widget-coordinate
)
this MCP-tool flow
CLT kindApex-backed (
@apexClassType/...
)
Object-based (
lightning__objectType
)
Number of CLTsonetwo (envelope + response)
Field source
@AuraEnabled
@InvocableVariable
on the response class
Renderer location
lightningTypes/<T>/lightningDesktopGenAi/renderer.json
(surface-specific)
lightningTypes/<toolCLT>/renderer.json
(default, parallel to
schema.json
)
Renderer bindingflat
{!$attrs.<field>}
nested
{!$attrs.outputValues.<field>}

维度代理动作流程(
...lightning-type-widget-coordinate
本MCP工具流程
CLT类型基于Apex(
@apexClassType/...
基于对象(
lightning__objectType
CLT数量1个2个(信封 + 响应)
字段来源
@AuraEnabled
响应类上的
@InvocableVariable
渲染器位置
lightningTypes/<T>/lightningDesktopGenAi/renderer.json
(特定界面)
lightningTypes/<toolCLT>/renderer.json
默认位置,与
schema.json
同级
渲染器绑定扁平化
{!$attrs.<field>}
嵌套式
{!$attrs.outputValues.<field>}

Phase Graph

阶段流程图

PhasePurposeOutput
1 — Input selectionDetermine the payload source: an invocable action API name (preferred), an Apex Invocable class, or a pasted tool-output JSON sample.
source
(
action
|
apex
|
sample
), tool API name
2 — Payload discoveryDescribe the invocable action via the Actions REST API and read its typed
outputs
(or parse the response class from source, or
outputValues
from the sample).
payloadFields
(name +
lightning:type
)
3 — Build planPrint the plan in full; proceed unless the next reply explicitly pushes back.printed plan
4 — GenerationLoad and invoke leaf skills: response CLT → envelope CLT → widget → inline default renderer in the envelope CLT.files written
5 — ValidationRun hard gates (block) and warn gates (advisory).gate report
6 — SummaryFiles, validations, deploy order, preview readiness.summary
Per-phase pattern: load the skill fresh → execute its workflow → verify outputs → checkpoint before the next phase. Even if you remember a leaf skill's content, skills evolve — always load fresh.

阶段目标输出
1 — 输入选择确定负载来源:invocable action API名称(首选)、Apex Invocable类,或粘贴的工具输出JSON示例。
source
action
|
apex
|
sample
)、工具API名称
2 — 负载发现通过Actions REST API描述invocable action并读取其类型化的
outputs
(或从源代码解析响应类,或从示例中解析
outputValues
)。
payloadFields
(名称 +
lightning:type
3 — 构建计划完整打印计划;除非下一条回复明确反对,否则继续推进。打印的计划
4 — 生成加载并调用子技能:响应CLT → 信封CLT → widget → 信封CLT中的内联默认渲染器。生成的文件
5 — 验证运行强制检查(阻止流程)和警告检查(建议性)。检查报告
6 — 总结文件列表、验证结果、部署顺序、预览就绪状态。总结报告
各阶段模式: 重新加载技能 → 执行其工作流 → 验证输出 → 进入下一阶段前检查。即使您记得子技能的内容,技能也会不断演进——始终重新加载最新版本。

Phase 1 — Input selection

阶段1 — 输入选择

Determine where the payload shape comes from. Prefer the sources top-to-bottom:
SourceTriggerPhase 2 action
action
Prompt gives an invocable action API name — directly, or via an Apex class name that resolves to one — AND an authenticated org is available. Preferred.Describe the action via the Actions REST API and read its typed
outputs
.
sample
No reachable org (or the describe 404s), but a pasted tool-output JSON sample is available.Parse the
outputValues
object from the sample.
apex
Only the Apex class is available (no action name resolvable, no reachable org, no sample) — fallback only, may be stale relative to what's deployed.Resolve the response class and enumerate
@InvocableVariable
fields.
Capture the tool API name (used to name all artifacts — see the naming convention below).
Source priority: live/authoritative schema sources beat parsing a local class, which beats a pasted example. In order:
  1. action
    if an action API name and an authenticated org are available. The Actions REST API describe is the same schema the platform itself exposes, so it needs no request/helper filtering and gives real field types.
  2. sample
    if a runtime JSON sample is pasted (runtime response — explicit and current).
  3. apex
    if an Apex class exists locally AND none of the above apply (fallback only — may be stale relative to what's actually deployed behind the action).
If none are available, STOP and ask the user for an action name, a class, a sample, or a schema.

确定负载结构的来源。优先选择以下从上到下的来源:
来源触发条件阶段2操作
action
提示提供invocable action API名称——直接提供,或通过可解析为该名称的Apex类名称提供——且存在已认证的组织。首选。通过Actions REST API描述动作并读取其类型化的
outputs
sample
无法访问组织(或描述请求返回404),但提供了粘贴的工具输出JSON示例。从示例中解析
outputValues
对象。
apex
仅能获取Apex(无法解析动作名称,无法访问组织,无示例)——仅作为备选,可能与已部署内容不一致。解析响应类并枚举
@InvocableVariable
字段。
捕获工具API名称(用于命名所有工件——请参见下文的命名约定)。
来源优先级: 实时/权威的 schema 来源优于解析本地类,解析本地类优于粘贴示例。顺序如下:
  1. action
    :如果提供了动作API名称且存在已认证的组织。Actions REST API描述与平台自身暴露的schema一致,因此无需请求/辅助过滤,可提供真实的字段类型。
  2. sample
    :如果提供了运行时JSON示例(运行时响应——明确且最新)。
  3. apex
    :如果本地存在Apex类且上述来源均不可用(仅作为备选——可能与动作背后实际部署的内容不一致)。
如果没有可用来源,请停止并向用户请求动作名称、类、示例或schema。

Phase 2 — Payload discovery

阶段2 — 负载发现

FIRST Read
references/mcp-tool-output-discovery.md
(REQUIRED — do NOT run Phase 2 from this summary alone), then execute the procedure for the chosen source. Reminders:
For
action
(preferred):
describe the action with the Actions REST API and read its
outputs
:
  • Resolve the action API name (for Apex actions this is the class name declaring
    @InvocableMethod
    , not the method label).
  • sf api request rest '/services/data/v<APIVER>/actions/custom/apex/<ActionApiName>' -o <org>
    .
  • Use the
    outputs
    array only (each entry
    { name, label, type, maxOccurs }
    ). Ignore
    inputs
    — that is the tool input (request wrapper). A field with
    maxOccurs > 1
    is a list — surface it in the plan (beta renders a single response).
  • Map the Actions API
    type
    → CLT
    lightning:type
    (see the discovery reference's table;
    STRING
    /
    ID
    /
    REFERENCE
    /… →
    lightning__textType
    ,
    INTEGER
    /
    LONG
    lightning__integerType
    ,
    DOUBLE
    /
    DECIMAL
    /
    CURRENCY
    /
    PERCENT
    lightning__numberType
    ,
    BOOLEAN
    lightning__booleanType
    ,
    DATE
    /
    DATETIME
    → date types). Match case-insensitively.
  • An entry with
    "type": null
    and an
    "apexClass": "<OuterClass>$<InnerClass>"
    key
    instead of a primitive
    type
    is a nested-object field, not a describe gap — see "Nested-object payload fields" below. The describe never exposes that class's own leaf fields, so retrieving/reading the named Apex class to enumerate them is the expected next step, not a fallback away from
    action
    .
  • If the describe 404s, fall back to
    sample
    (a pasted tool-output JSON) if one is available, else
    apex
    (parse the class from source, if locally available).
For
apex
(fallback):
  • Locate the class (
    <pkgDir>/classes/<ClassName>.cls
    ; retrieve
    ApexClass:<ClassName>
    if absent).
  • Identify the response class — the element type of the
    @InvocableMethod
    return
    List<...>
    (e.g.
    List<GetAccountSummaryResponse>
    GetAccountSummaryResponse
    ).
  • Enumerate its
    @InvocableVariable
    fields. Exclude the request class (the
    @InvocableMethod
    parameter type) and any
    private
    helper classes — those are not part of the tool's externally visible output schema.
  • Map Apex → CLT
    lightning:type
    :
    String
    /
    Id
    lightning__textType
    ,
    Integer
    lightning__integerType
    ,
    Decimal
    /
    Double
    lightning__numberType
    ,
    Boolean
    lightning__booleanType
    ,
    Date
    lightning__dateType
    ,
    Datetime
    lightning__dateTimeType
    .
  • A field whose type is itself an Apex class (e.g.
    flightInfo : SearchFlightsAction.Flight
    ) is a second, additive case alongside the flat-primitive mapping above — see "Nested-object payload fields" below. This applies to every source (
    action
    ,
    apex
    ,
    sample
    ), not just
    apex
    .
For
sample
(fallback):
parse the
outputValues
object; infer each field's
lightning:type
from its JSON value (string →
lightning__textType
, integer →
lightning__integerType
, fractional number →
lightning__numberType
, boolean →
lightning__booleanType
).
Nested-object payload fields (applies to every source above): when a response/output field's type is not a primitive but another Apex class (object), do NOT model it as
{"type":"object"}
or an inlined
lightning__objectType
— both produce an opaque, unrenderable blob and neither deploys. Instead:
  • Type the response CLT property as
    "@apexClassType/<ns>__<OuterClass>$<InnerClass>"
    (e.g.
    "@apexClassType/c__SearchFlightsAction$Flight"
    ), matching the Apex-backed-CLT convention
    platform-custom-lightning-type-generate
    already documents.
  • Enumerate the referenced Apex class's own
    @InvocableVariable
    /public fields as the leaf set; the widget schema flattens to those leaves (never the object field itself).
  • The renderer binds one level deeper:
    {!$attrs.outputValues.<objectField>.<leaf>}
    (e.g.
    {!$attrs.outputValues.flightInfo.flightId}
    ), not
    {!$attrs.outputValues.<objectField>}
    .
  • A field typed
    List<ApexClass>
    is out of scope for the beta single-response flow — surface it in the build plan like a
    maxOccurs > 1
    scalar, do not emit a schema for it.
  • See
    references/two-clt-modeling.md
    ("Nested-object payload fields") and
    examples/nested-object-source-prompt.md
    for the full walkthrough.
Capture
payloadFields
— the ordered list of
{ name, title, lightning:type }
that defines the response CLT and the widget schema. Record which source produced it in the build plan.
Staleness: do NOT maintain a cross-session cache. Read the local project fresh and re-retrieve from the org per session.

首先阅读
references/mcp-tool-output-discovery.md
(必填——请勿仅根据本摘要运行阶段2),然后针对所选来源执行流程。注意事项:
对于
action
(首选):
通过Actions REST API描述动作并读取其
outputs
  • 解析动作API名称(对于Apex动作,这是声明
    @InvocableMethod
    类名称,而非方法标签)。
  • 执行命令:
    sf api request rest '/services/data/v<APIVER>/actions/custom/apex/<ActionApiName>' -o <org>
  • 仅使用
    outputs
    数组(每个条目包含
    { name, label, type, maxOccurs }
    )。忽略
    inputs
    ——这是工具输入(请求包装器)。
    maxOccurs > 1
    的字段为列表——请在计划中注明(Beta版仅渲染单个响应)。
  • 将Actions API的
    type
    映射到CLT的
    lightning:type
    (请参见发现参考文档中的表格;
    STRING
    /
    ID
    /
    REFERENCE
    /… →
    lightning__textType
    INTEGER
    /
    LONG
    lightning__integerType
    DOUBLE
    /
    DECIMAL
    /
    CURRENCY
    /
    PERCENT
    lightning__numberType
    BOOLEAN
    lightning__booleanType
    DATE
    /
    DATETIME
    → 日期类型)。匹配时不区分大小写。
  • 如果条目包含**
    "type": null
    "apexClass": "<OuterClass>$<InnerClass>"
    键**而非原始类型,则表示该字段为嵌套对象字段,而非描述缺失——请参见下文的“嵌套对象负载字段”。描述不会暴露该类自身的叶子字段,因此预期的下一步是检索/读取指定的Apex类以枚举其字段,而非放弃
    action
    来源。
  • 如果描述请求返回404,若有粘贴的工具输出JSON示例则回退到
    sample
    ,否则回退到
    apex
    (从源代码解析类,如果本地可用)。
对于
apex
(备选):
  • 定位类文件(
    <pkgDir>/classes/<ClassName>.cls
    ;如果不存在则检索
    ApexClass:<ClassName>
    )。
  • 识别响应类——
    @InvocableMethod
    返回的
    List<...>
    的元素类型(例如
    List<GetAccountSummaryResponse>
    GetAccountSummaryResponse
    )。
  • 枚举其
    @InvocableVariable
    字段。排除请求类(
    @InvocableMethod
    参数类型)和任何
    private
    辅助类——这些不属于工具对外暴露的输出schema。
  • 将Apex类型映射到CLT的
    lightning:type
    String
    /
    Id
    lightning__textType
    Integer
    lightning__integerType
    Decimal
    /
    Double
    lightning__numberType
    Boolean
    lightning__booleanType
    Date
    lightning__dateType
    Datetime
    lightning__dateTimeType
  • 类型为Apex类的字段(例如
    flightInfo : SearchFlightsAction.Flight
    )是除扁平化原始类型映射之外的另一种情况——请参见下文的“嵌套对象负载字段”。这适用于所有来源(
    action
    apex
    sample
    ),而非仅
    apex
对于
sample
(备选):
解析
outputValues
对象;根据JSON值推断每个字段的
lightning:type
(字符串 →
lightning__textType
,整数 →
lightning__integerType
,小数 →
lightning__numberType
,布尔值 →
lightning__booleanType
)。
嵌套对象负载字段(适用于上述所有来源): 当响应/输出字段的类型不是原始类型而是另一个Apex类(对象)时,请勿将其建模为
{"type":"object"}
或内联的
lightning__objectType
——这两种方式都会生成不透明、无法渲染的二进制大对象,且均无法部署。正确做法是:
  • 将响应CLT属性类型设置为
    "@apexClassType/<ns>__<OuterClass>$<InnerClass>"
    (例如
    "@apexClassType/c__SearchFlightsAction$Flight"
    ),与
    platform-custom-lightning-type-generate
    已记录的基于Apex的CLT约定一致。
  • 将引用的Apex类自身的
    @InvocableVariable
    /公共字段枚举为叶子字段集;widget schema会扁平化到这些叶子字段(而非对象字段本身)。
  • 渲染器的绑定会深入一层:
    {!$attrs.outputValues.<objectField>.<leaf>}
    (例如
    {!$attrs.outputValues.flightInfo.flightId}
    ),而非
    {!$attrs.outputValues.<objectField>}
  • 类型为
    List<ApexClass>
    的字段超出Beta版单响应流程的范围——请在构建计划中注明,类似于
    maxOccurs > 1
    的标量字段,不要为其生成schema。
  • 请参见
    references/two-clt-modeling.md
    (“嵌套对象负载字段”)和
    examples/nested-object-source-prompt.md
    获取完整流程说明。
捕获
payloadFields
——定义响应CLT和widget schema的有序列表
{ name, title, lightning:type }
。在构建计划中记录生成该列表的来源。
时效性:请勿维护跨会话缓存。每次会话都要重新读取本地项目并从组织重新检索内容。

Phase 3 — Build plan + approval gate

阶段3 — 构建计划 + 批准检查

Print a build plan using the template in
references/build-plan-format.md
. The plan must list:
  • A one-line developer-facing summary (the
    PLAN:
    line).
  • The tool API name and the response class FQN (or "from pasted sample").
  • The two CLT names (envelope + payload) and the widget name, with absolute paths.
  • The envelope fields the envelope CLT will carry, and the response fields the response CLT + widget will carry.
  • Properties omitted:
    — any response fields intentionally dropped, with rationale.
    actionName
    and
    isSuccess
    are envelope fields and never appear here or on the widget
    — they belong to the envelope CLT only. Any payload-side operational/status field (
    isSuccess
    ,
    errorMessage
    ,
    status
    ,
    message
    , and similar) that the response happens to carry is omitted from the widget by default and MUST be listed here with a one-line rationale — the widget renders
    outputValues
    data fields only.
  • The validations that will run after generation.
Print the plan in full, then proceed unless the user's next reply explicitly pushes back. Explicit pushback =
no
,
stop
,
wait
,
change X
,
use Y instead
, or an equivalent rejection / revision request. Explicit approval is welcome but NOT required — silence, an unrelated follow-up, or the natural continuation of a single-turn eval all count as implicit approval. The invariant is the plan being visible in the transcript. If pushback arrives, revise and re-print before moving on.

使用
references/build-plan-format.md
中的模板打印构建计划。计划必须包含:
  • 一行面向开发者的摘要(
    PLAN:
    行)。
  • 工具API名称和响应类完全限定名(或“来自粘贴的示例”)。
  • 两个CLT的名称(信封 + 负载)和widget名称,以及绝对路径。
  • 信封CLT将包含的信封字段,以及响应CLT + widget将包含的响应字段。
  • Properties omitted:
    ——有意省略的任何响应字段及理由。
    actionName
    isSuccess
    是信封字段,绝不会出现在此处或widget中
    ——它们仅属于信封CLT。如果响应中包含负载侧的操作/状态字段(
    isSuccess
    errorMessage
    status
    message
    及类似字段),默认会从widget中省略,且必须在此处列出并附上一行理由——widget仅渲染
    outputValues
    数据字段。
  • 生成后将运行的验证项。
完整打印计划,然后继续推进,除非用户的下一条回复明确反对。 明确反对包括
no
stop
wait
change X
use Y instead
或等效的拒绝/修改请求。明确批准是受欢迎的,但并非必需——沉默、无关的后续回复或单轮评估的自然延续均视为隐含批准。核心要求是计划必须在对话记录中可见。如果收到反对意见,请修改并重新打印后再继续。

Phase 4 — Generation

阶段4 — 生成

Load and invoke leaf skills in this order. For each: load the skill, execute its workflow against the Phase 3 spec, verify the outputs, checkpoint before the next.
  1. Response CLT — load
    platform-custom-lightning-type-generate
    . Author an object-based CLT
    <responseCLT>
    (convention:
    <toolApiName>Response
    ) whose
    properties
    are the
    payloadFields
    from Phase 2 (1:1 with the response
    @InvocableVariable
    fields). Root is
    lightning__objectType
    , with root-level
    "lightning:tags": ["mcp"]
    .
  2. Envelope CLT — load
    platform-custom-lightning-type-generate
    . Author an object-based CLT
    <toolCLT>
    (convention:
    <toolApiName>
    , the envelope), also with root-level
    "lightning:tags": ["mcp"]
    , and:
    • actionName
      lightning__textType
    • isSuccess
      lightning__booleanType
    • outputValues
      c__<responseCLT>
      (the referenced-CLT pattern; the response CLT must be deployed before the envelope CLT)
    • Add
      message
      / other envelope scalars only if the widget needs to render them.
  3. Widget — load
    platform-widget-generate
    . Author a flat widget whose
    schema.json
    properties are the
    payloadFields
    (name + primitive type) — a standalone widget contract, not derived from or coupled to any Lightning Type. It renders only
    outputValues
    data fields
    : never
    actionName
    /
    isSuccess
    (envelope-only), and never a response-side operational/status field declared in
    Properties omitted:
    . The widget body binds each field via
    {!$attrs.<field>}
    — the widget is envelope-agnostic and never references
    outputValues
    itself.
  4. Default renderer (authored inline in the ENVELOPE CLT — never optional). FIRST Read
    platform-custom-lightning-type-generate/references/widget-rendition.md
    (REQUIRED — do NOT author from memory or copy an existing sample, which may use a deprecated shape). Then author
    <pkgDir>/lightningTypes/<toolCLT>/renderer.json
    — the default renderer, at the bundle root, parallel to
    schema.json
    (NOT under
    lightningDesktopGenAi/
    ). Shape:
    json
    {
      "renderer": {
        "componentOverrides": {
          "$": {
            "definition": "@widget/c/<widgetName>",
            "attributes": {
              "<payloadField>": "{!$attrs.outputValues.<payloadField>}"
            }
          }
        }
      }
    }
    The renderer maps every widget schema property to the matching payload field nested under the envelope's
    outputValues
    node via
    {!$attrs.outputValues.<payloadField>}
    . This nested binding is the crux of this flow — it bridges the envelope CLT to the flat widget. Do NOT duplicate the widget body inside
    renderer.json
    .
Existing-renderer handling: if
renderer.json
already exists at the target path, read it first. If it references the same widget with the same bindings, leave it. If it references a different widget or a custom-LWC root override (
c/<component>
), STOP and surface the conflict before overwriting.

按以下顺序加载并调用子技能。对于每个子技能:加载技能,针对阶段3的规范执行其工作流,验证输出,进入下一阶段前检查。
  1. 响应CLT——加载
    platform-custom-lightning-type-generate
    。编写基于对象的CLT
    <responseCLT>
    (约定:
    <toolApiName>Response
    ),其
    properties
    与阶段2的
    payloadFields
    完全匹配(与响应的
    @InvocableVariable
    字段一一对应)。根类型为
    lightning__objectType
    ,根级别包含
    "lightning:tags": ["mcp"]
  2. 信封CLT——加载
    platform-custom-lightning-type-generate
    。编写基于对象的CLT
    <toolCLT>
    (约定:
    <toolApiName>
    ,即信封),同样在根级别包含
    "lightning:tags": ["mcp"]
    ,并包含以下字段:
    • actionName
      lightning__textType
    • isSuccess
      lightning__booleanType
    • outputValues
      c__<responseCLT>
      (引用CLT模式;响应CLT必须在信封CLT之前部署)
    • 仅当widget需要渲染时才添加
      message
      或其他信封标量字段。
  3. Widget——加载
    platform-widget-generate
    。编写扁平化的widget,其
    schema.json
    属性为
    payloadFields
    (名称 + 原始类型)——这是独立的widget契约,并非派生自或耦合于任何Lightning Type。它仅渲染**
    outputValues
    数据字段**:绝不渲染
    actionName
    /
    isSuccess
    (仅属于信封),也绝不渲染阶段3的
    Properties omitted:
    中声明的响应侧操作/状态字段。widget主体通过
    {!$attrs.<field>}
    绑定每个字段——widget与信封无关,绝不会引用
    outputValues
    本身。
  4. 默认渲染器(内联编写在信封CLT中——绝非可选)。首先阅读
    platform-custom-lightning-type-generate/references/widget-rendition.md
    (必填——请勿凭记忆编写或复制现有示例,因为示例可能使用已弃用的格式)。然后编写
    <pkgDir>/lightningTypes/<toolCLT>/renderer.json
    ——默认渲染器,位于包根目录,与
    schema.json
    同级
    (而非
    lightningDesktopGenAi/
    目录下)。格式如下:
    json
    {
      "renderer": {
        "componentOverrides": {
          "$": {
            "definition": "@widget/c/<widgetName>",
            "attributes": {
              "<payloadField>": "{!$attrs.outputValues.<payloadField>}"
            }
          }
        }
      }
    }
    渲染器通过
    {!$attrs.outputValues.<payloadField>}
    每个widget schema属性映射到信封
    outputValues
    节点下的匹配负载字段。这种嵌套绑定是本流程的核心——它将信封CLT桥接到扁平化的widget。请勿在
    renderer.json
    中重复widget主体内容。
现有渲染器处理: 如果目标路径已存在
renderer.json
,请先读取它。如果它引用相同的widget且绑定相同,则保留它。如果它引用不同的widget或自定义LWC根覆盖(
c/<component>
),请停止并在覆盖前告知冲突。

Phase 5 — Validation gates

阶段5 — 验证检查

Read
references/validation-gates.md
and run every gate. Widget-bundle-internal checks (schema parse, root keys, leaf types,
{!$attrs.X}
resolution,
.uiwidget-meta.xml
well-formedness) are owned by
platform-widget-generate
and run in its own self-validation.
Hard — block on failure:
  1. clt-reference-integrity
    — the envelope CLT's
    outputValues
    property has
    lightning:type === "c__<responseCLT>"
    , the response CLT exists at
    <pkgDir>/lightningTypes/<responseCLT>/schema.json
    , both parse as JSON, and neither carries
    $schema
    or (nested)
    items
    .
  2. renderer-wires-widget
    <pkgDir>/lightningTypes/<toolCLT>/renderer.json
    exists (at the bundle root, not
    lightningDesktopGenAi/
    ), parses, wires the widget via
    componentOverrides["$"].definition === "@widget/c/<widgetName>"
    , and binds every widget schema property as
    {!$attrs.outputValues.<property>}
    (nested path). Bidirectional: missing or extra bindings both fail.
Warn — advisory:
  1. field-trace
    — RUN the trace in
    references/validation-gates.md
    : grep
    @InvocableVariable
    from the response class,
    jq
    the widget schema property keys, print both lists, classify INVENTED vs OMITTED. Invented widget fields fail; silent omissions (a response field absent from the widget AND absent from the Phase 3
    Properties omitted:
    plan) warn.
Report each gate result by name in Phase 6 (
pass
,
fail (<reason>)
,
warn (<reason>)
,
not run
). Do not summarize as "all passed". This skill produces metadata only — it does not deploy; deployment is the caller's responsibility.

阅读
references/validation-gates.md
运行所有检查项。widget包内部检查(schema解析、根键、叶子类型、
{!$attrs.X}
解析、
.uiwidget-meta.xml
格式正确性)由
platform-widget-generate
负责,并在其自验证中运行。
强制检查——失败则阻止流程:
  1. clt-reference-integrity
    ——信封CLT的
    outputValues
    属性的
    lightning:type === "c__<responseCLT>"
    ,响应CLT存在于
    <pkgDir>/lightningTypes/<responseCLT>/schema.json
    ,两者均可解析为JSON,且均不包含
    $schema
    或(嵌套的)
    items
  2. renderer-wires-widget
    ——
    <pkgDir>/lightningTypes/<toolCLT>/renderer.json
    存在(位于包根目录,而非
    lightningDesktopGenAi/
    ),可解析,通过
    componentOverrides["$"].definition === "@widget/c/<widgetName>"
    关联widget,并将每个widget schema属性绑定为**
    {!$attrs.outputValues.<property>}
    **(嵌套路径)。双向检查:缺失或多余的绑定均视为失败。
警告检查——建议性:
  1. field-trace
    ——运行
    references/validation-gates.md
    中的跟踪:从响应类中 grep
    @InvocableVariable
    ,使用
    jq
    提取widget schema属性键,打印两个列表,分类为“虚构字段”和“省略字段”。虚构的widget字段视为失败;静默省略(响应字段未出现在widget中且未在阶段3的
    Properties omitted:
    计划中声明)视为警告。
在阶段6中按名称报告每个检查项的结果(
pass
fail (<reason>)
warn (<reason>)
not run
)。请勿总结为“全部通过”。本技能仅生成元数据——不负责部署;部署由调用方负责。

Phase 6 — Summary

阶段6 — 总结

text
MCP Tool Widget Build Complete: <widgetName>

FILES GENERATED:
  Response CLT:
    <pkgDir>/lightningTypes/<responseCLT>/schema.json
  Envelope CLT:
    <pkgDir>/lightningTypes/<toolCLT>/schema.json
    <pkgDir>/lightningTypes/<toolCLT>/renderer.json          # default renderer — wires the widget
  Widget bundle:
    <pkgDir>/uiWidgets/<widgetName>/<widgetName>.json
    <pkgDir>/uiWidgets/<widgetName>/schema.json
    <pkgDir>/uiWidgets/<widgetName>/<widgetName>.uiwidget-meta.xml

VALIDATIONS:
  widget self-validation (platform-widget-generate gates): <pass | fail — see sub-skill report>
  clt-reference-integrity (envelope.outputValues → c__<responseCLT>): <pass | fail (<reason>)>
  renderer-wires-widget (nested {!$attrs.outputValues.X} bindings): <pass | fail (<reason>)>
  field-trace (INVENTED + OMITTED lists printed): <pass | warn (<reason>) | fail (invented: <list>)>

text
MCP工具Widget构建完成:<widgetName>

生成的文件:
  响应CLT:
    <pkgDir>/lightningTypes/<responseCLT>/schema.json
  信封CLT:
    <pkgDir>/lightningTypes/<toolCLT>/schema.json
    <pkgDir>/lightningTypes/<toolCLT>/renderer.json          # 默认渲染器——关联widget
  Widget包:
    <pkgDir>/uiWidgets/<widgetName>/<widgetName>.json
    <pkgDir>/uiWidgets/<widgetName>/schema.json
    <pkgDir>/uiWidgets/<widgetName>/<widgetName>.uiwidget-meta.xml

验证结果:
  widget自验证(platform-widget-generate检查项):<pass | fail — 请参见子技能报告>
  clt-reference-integrity(envelope.outputValues → c__<responseCLT>):<pass | fail (<reason>)>
  renderer-wires-widget(嵌套{!$attrs.outputValues.X}绑定):<pass | fail (<reason>)>
  field-trace(打印虚构字段+省略字段列表):<pass | warn (<reason>) | fail (虚构字段:<list>)>

Hard Rules (always apply)

硬性规则(始终适用)

  1. Plan-first, then proceed. Print the full Phase 3 build plan before writing any file. Explicit rejection or a change request → stop and revise; otherwise continue. The invariant is the plan being visible in the transcript, not an interactive human approval — this holds in manual chat, agent-to-agent flows, and single-turn evals.
  2. Two object-based CLTs, never one. The envelope and the payload are separate CLTs. The envelope's
    outputValues
    is typed via
    c__<responseCLT>
    , never inlined as a nested
    lightning__objectType
    . Both CLTs carry root-level
    "lightning:tags": ["mcp"]
    (see
    platform-custom-lightning-type-generate/assets/primitive-types-and-constraints.md
    ).
  3. Renderer lives in the ENVELOPE CLT, at the bundle root.
    lightningTypes/<toolCLT>/renderer.json
    — the default renderer, parallel to
    schema.json
    . Never
    lightningDesktopGenAi/renderer.json
    (that is the agent-action flow's surface-specific path), never in the response CLT.
  4. Renderer bindings are nested. Every widget attribute maps to
    {!$attrs.outputValues.<field>}
    , not
    {!$attrs.<field>}
    . The widget schema stays flat; the renderer does the bridging.
  5. Widget grounds on the payload, not the envelope, and renders
    outputValues
    data fields only.
    The widget schema properties are the payload fields. The widget never references
    actionName
    or
    isSuccess
    — those are envelope-only. A payload field that is itself operational/status (
    isSuccess
    ,
    errorMessage
    ,
    status
    ,
    message
    , and similar) is omitted from the widget by default and declared in
    Properties omitted:
    .
  6. Field source is
    @InvocableVariable
    on the response class.
    Enumerate the response class only. Exclude the request class and private helper classes.
  7. No invented fields, no silent omissions. The widget schema (and the response CLT) must be a subset of the response
    @InvocableVariable
    fields. Omission requires the field to appear in the Phase 3
    Properties omitted:
    section with an approved rationale.
    field-trace
    prints both lists.
  8. Single response for beta. Model one result object, not the
    content[]
    bulk wrapper.
  9. Always load the leaf skill before generation. Do not author from memory.
  10. Run gates, do not describe them. Reporting
    pass
    without executing a gate is a hard violation; report
    not run
    instead.
  11. No shell metacharacters that trigger the Vibes safe-shell filter. In every
    Bash
    tool call emitted by this orchestrator and by any leaf skill it invokes, do NOT use command substitution (
    $(…)
    or backticks), process substitution (
    <(…)
    ,
    >(…)
    ), brace expansion (
    {a,b,c}
    or
    {1..N}
    ), or
    eval
    /
    exec
    . These force manual approval even under Bypass mode and stall the eval. Run separate commands (
    mkdir -p a && mkdir -p b
    ), print each intermediate value with its own command and reason about the result, and use plain shell variables (
    X=literal
    ) or here-strings when a value must be reused.
  12. Resolve
    action
    schema from the Actions REST API describe, never from raw HTTP to the MCP endpoint or from credential extraction.
    Use
    sf api request rest
    against the org's Actions REST API (which uses the existing
    sf
    org auth). Never read
    a4d_mcp_settings.json
    or any MCP settings file, never extract an org access token, never
    curl
    an MCP server endpoint directly — that requires credentials the session doesn't have and targets a URL the runtime doesn't actually expose that way.
  13. Never invoke an MCP tool to discover its output shape. Describing the payload must never execute the underlying action. Resolve the schema via the Actions REST API describe of the backing action — never by calling the tool with sample/guessed input to observe a response. If no action name is resolvable, ask the user for a pasted
    sample
    instead of invoking anything.
  14. A response field typed as another Apex class is never a bare
    {"type":"object"}
    .
    Type it
    @apexClassType/<ns>__<OuterClass>$<InnerClass>
    in the response CLT, flatten to its leaf fields in the widget, and bind the renderer two levels deep (
    {!$attrs.outputValues.<objectField>.<leaf>}
    ). This is additive to the flat-primitive case (Hard Rule 5), not a replacement for it — see
    references/two-clt-modeling.md
    .

  1. 先计划,再推进。 在编写任何文件前,完整打印阶段3的构建计划。明确拒绝或修改请求→停止并修改;否则继续。核心要求是计划必须在对话记录中可见,而非需要交互式人工批准——这适用于手动聊天、代理间流程和单轮评估。
  2. 两个基于对象的CLT,绝不使用一个。 信封和负载是独立的CLT。信封的
    outputValues
    通过
    c__<responseCLT>
    类型化,绝不内联为嵌套的
    lightning__objectType
    。两个CLT均在根级别包含
    "lightning:tags": ["mcp"]
    (请参见
    platform-custom-lightning-type-generate/assets/primitive-types-and-constraints.md
    )。
  3. 渲染器位于信封CLT的包根目录。
    lightningTypes/<toolCLT>/renderer.json
    ——默认渲染器,与
    schema.json
    同级。绝不要放在
    lightningDesktopGenAi/renderer.json
    (这是代理动作流程的特定界面路径),也不要放在响应CLT中。
  4. 渲染器绑定为嵌套式。 每个widget属性都映射到
    {!$attrs.outputValues.<field>}
    ,而非
    {!$attrs.<field>}
    。widget schema保持扁平化;渲染器负责桥接。
  5. Widget基于负载而非信封构建,且仅渲染
    outputValues
    数据字段。
    widget schema属性为负载字段。widget绝不引用
    actionName
    isSuccess
    ——这些仅属于信封。负载侧的操作/状态字段(
    isSuccess
    errorMessage
    status
    message
    及类似字段)默认从widget中省略,并在
    Properties omitted:
    中声明。
  6. 字段来源为响应类上的
    @InvocableVariable
    仅枚举响应类。排除请求类和私有辅助类。
  7. 无虚构字段,无静默省略。 widget schema(及响应CLT)必须是响应
    @InvocableVariable
    字段的子集。省略字段必须在阶段3的
    Properties omitted:
    部分列出并附上批准的理由。
    field-trace
    会打印两个列表。
  8. Beta版仅支持单个响应。 建模一个结果对象,而非
    content[]
    批量包装器。
  9. 生成前始终加载子技能。 请勿凭记忆编写内容。
  10. 运行检查项,而非描述它们。 未执行检查项就报告
    pass
    属于严重违规;请改为报告
    not run
  11. 不使用触发Vibes安全shell过滤器的shell元字符。 在本编排器及其调用的任何子技能发出的每个Bash工具调用中,请勿使用命令替换(
    $(…)
    或反引号)、进程替换(
    <(…)
    ,
    >(…)
    )、大括号扩展(
    {a,b,c}
    {1..N}
    )或
    eval
    /
    exec
    。即使在绕过模式下,这些也会强制手动批准并延迟评估。请运行单独的命令(
    mkdir -p a && mkdir -p b
    ),使用单独的命令打印每个中间值并说明结果,使用普通shell变量(
    X=literal
    )或here-string重用值。
  12. 从Actions REST API描述解析
    action
    schema,绝不从MCP端点的原始HTTP请求或凭证提取。
    使用
    sf api request rest
    针对组织的Actions REST API(使用现有的
    sf
    组织认证)。绝不要读取
    a4d_mcp_settings.json
    或任何MCP设置文件,绝不要提取组织访问令牌,绝不要直接
    curl
    MCP服务器端点——这需要会话中没有的凭证,且目标URL并非运行时实际暴露的方式。
  13. 绝不调用MCP工具来发现其输出结构。 描述负载绝不能执行底层动作。通过支持动作的Actions REST API描述解析schema——绝不要通过调用工具并提供示例/猜测的输入来观察响应。如果无法解析动作名称,请向用户请求粘贴的
    sample
    ,而非调用任何内容。
  14. 类型为另一个Apex类的响应字段绝不能是裸
    {"type":"object"}
    在响应CLT中将其类型设置为
    @apexClassType/<ns>__<OuterClass>$<InnerClass>
    ,在widget中扁平化到其叶子字段,并将渲染器绑定深入两层(
    {!$attrs.outputValues.<objectField>.<leaf>}
    )。这是对扁平化原始类型情况(硬性规则5)的补充,而非替代——请参见
    references/two-clt-modeling.md

Reference File Index

参考文件索引

FileWhen to read
references/mcp-tool-output-discovery.md
Phase 2 — the three sources (
action
describe via Actions REST API; pasted
sample
;
apex
class parse), field enumeration, and type mapping.
references/two-clt-modeling.md
Phase 4 — how the envelope + response CLTs and the nested renderer binding fit together, with the naming convention and nested-object payload handling.
references/build-plan-format.md
Phase 3 — plan template the model fills before proceeding.
references/validation-gates.md
Phase 5 — full hard / warn gate table with RUN procedures.
examples/action-name-source-prompt.md
Phase 3 — a complete walkthrough starting from an invocable action API name (preferred source).
examples/apex-invocable-source-prompt.md
Phase 3 — a complete walkthrough starting from an Apex Invocable class (fallback).
examples/pasted-tool-output-prompt.md
Phase 3 — a complete walkthrough starting from a pasted tool-output sample (fallback).
examples/nested-object-source-prompt.md
Phase 3 — a complete walkthrough where a payload field is itself an Apex-class reference, not a primitive.
文件阅读时机
references/mcp-tool-output-discovery.md
阶段2——三个来源(通过Actions REST API描述
action
;粘贴的
sample
;解析
apex
类)、字段枚举和类型映射。
references/two-clt-modeling.md
阶段4——信封+响应CLT和嵌套渲染器绑定如何配合工作,包括命名约定和嵌套对象负载处理。
references/build-plan-format.md
阶段3——模型在推进前需填充的计划模板。
references/validation-gates.md
阶段5——完整的强制/警告检查项表格及执行流程。
examples/action-name-source-prompt.md
阶段3——从invocable action API名称开始的完整流程说明(首选来源)。
examples/apex-invocable-source-prompt.md
阶段3——从Apex Invocable类开始的完整流程说明(备选)。
examples/pasted-tool-output-prompt.md
阶段3——从粘贴的工具输出示例开始的完整流程说明(备选)。
examples/nested-object-source-prompt.md
阶段3——负载字段为Apex类引用(而非原始类型)的完整流程说明。