service-itsm-agentic-setup-agentforce-studio-configure

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Enable Agentforce for IT Service Prerequisites

启用Agentforce for IT Service前置条件

Enable the Agentforce for IT Service Salesforce Go feature toggles — Einstein Generative AI, Agentforce Studio, the parent umbrella, and the path-specific agent template (Fulfiller or Employee) — entirely through the Salesforce CLI (
sf
)
. This is the write-capable step in a three-skill flow; every write goes through the Setup Discovery
POST /connect/setup/discovery/feature/{apiName}/enable
Connect API route — the only correct write path for these toggles. Each toggle is enabled idempotently (skipped if already
ENABLED
), dependencies are enabled first, and explicit confirmation is required before any write.
StepSkillWhat it does
1. Validate
service-itsm-agentic-setup-agentforce-studio-validate
Read the toggles → READY / NOT-READY (no writes)
2. Configure (this skill)
service-itsm-agentic-setup-agentforce-studio-configure
Turn the disabled toggles ON
3. Create agent
service-itsm-agentic-setup-fulfiller-agent-configure
Create + activate the Fulfiller agent
This skill is typically reached via hand-off from the validate skill's NOT-READY report, but can also be run directly.
A helper script —
scripts/classify-enable-plan.mjs
— reads the batched
/features/status
response and deterministically computes the dependency-ordered enable plan (before writing) and the final per-feature verdict (after writing). This mirrors the validate skill's
classify-readiness.mjs
contract (authoring standard A9): the decision logic lives in a script, not in prose.
完全通过Salesforce CLI(
sf
启用Agentforce for IT Service
Salesforce Go功能开关——包括Einstein Generative AIAgentforce Studio父级总开关以及路径特定的代理模板(FulfillerEmployee)。这是三步技能流程中的支持写入步骤;所有写入操作均通过Setup Discovery的
POST /connect/setup/discovery/feature/{apiName}/enable
Connect API路由执行——这是操作这些开关的唯一正确写入路径。每个开关的启用都具备幂等性(若已处于
ENABLED
状态则跳过),依赖项会优先启用,且在执行任何写入操作前需要明确确认。
步骤技能功能
1. 验证
service-itsm-agentic-setup-agentforce-studio-validate
读取开关状态 → 就绪/未就绪(无写入操作)
2. 配置(本技能)
service-itsm-agentic-setup-agentforce-studio-configure
开启未启用的开关
3. 创建代理
service-itsm-agentic-setup-fulfiller-agent-configure
创建并激活Fulfiller代理
本技能通常由验证技能的未就绪报告触发,但也可直接运行。
辅助脚本
scripts/classify-enable-plan.mjs
会读取批量的
/features/status
响应,确定性地计算按依赖顺序排列的启用计划(写入前)和每个功能的最终判定结果(写入后)。这与验证技能的
classify-readiness.mjs
规范一致(创作标准A9):决策逻辑存在于脚本中,而非文字描述。

Scope

范围

  • In scope: Enabling Einstein Generative AI (
    sales-cloud-einstein-generative-ai
    ), Agentforce Studio (
    sales-cloud-agent-studio
    ), the parent umbrella (
    service-cloud-agentforce-for-itsm
    ), and the path-specific template (
    service-cloud-it-fulfiller-agent
    for fulfiller;
    service-cloud-requestor-agent
    +
    service-cloud-it-service-employee-agent
    for employee) via
    POST .../feature/{apiName}/enable
    ; reading live per-org state from
    /features/status
    before and after each write; enabling dependencies first; confirming enablement stuck via re-query; surfacing an ENABLED / ALREADY-ENABLED / FAILED verdict per feature. Writes are idempotent — skip if already
    ENABLED
    .
  • Out of scope: Provisioning Agentforce licenses (Setup > Company Information > Permission Set Licenses); assigning permission sets to users; creating, configuring, or activating an agent (
    service-itsm-agentic-setup-fulfiller-agent-configure
    ); read-only prerequisite validation without writes (
    service-itsm-agentic-setup-agentforce-studio-validate
    ); the org-wide multi-agent orchestration toggle (a Headless360-only pref, not a Connect feature).

  • 纳入范围:通过
    POST .../feature/{apiName}/enable
    启用Einstein Generative AI(
    sales-cloud-einstein-generative-ai
    )、Agentforce Studio(
    sales-cloud-agent-studio
    )、父级总开关(
    service-cloud-agentforce-for-itsm
    )以及路径特定模板(Fulfiller对应
    service-cloud-it-fulfiller-agent
    ;Employee对应
    service-cloud-requestor-agent
    +
    service-cloud-it-service-employee-agent
    );在每次写入前后从
    /features/status
    读取组织实时状态;优先启用依赖项;通过重新查询确认启用状态;为每个功能显示ENABLED/ALREADY-ENABLED/FAILED判定结果。写入操作具备幂等性——若已处于
    ENABLED
    状态则跳过。
  • 排除范围:配置Agentforce许可证(设置 > 公司信息 > 权限集许可证);为用户分配权限集;创建、配置或激活代理(
    service-itsm-agentic-setup-fulfiller-agent-configure
    );仅读取前置条件验证而无写入操作(
    service-itsm-agentic-setup-agentforce-studio-validate
    );组织级多代理编排开关(仅Headless360可用的偏好设置,非Connect功能)。

Which path?

选择哪条路径?

Determine whether the user is enabling prerequisites for the fulfiller agent or an employee agent. If unclear, ask (
AskUserQuestion
) — same path selection the validate skill uses:
  • fulfiller
    sales-cloud-einstein-generative-ai
    sales-cloud-agent-studio
    service-cloud-agentforce-for-itsm
    service-cloud-it-fulfiller-agent
  • employee
    sales-cloud-einstein-generative-ai
    sales-cloud-agent-studio
    service-cloud-agentforce-for-itsm
    service-cloud-requestor-agent
    service-cloud-it-service-employee-agent
Einstein Generative AI is a dependency of Agentforce Studio and is not one of the toggles the validate skill reports on directly, but it must be enabled first if it is off — the classifier includes it in the enable plan for both paths.

确定用户是为Fulfiller代理还是Employee代理启用前置条件。若不确定,请询问用户(
AskUserQuestion
)——与验证技能使用的路径选择逻辑一致:
  • Fulfiller
    sales-cloud-einstein-generative-ai
    sales-cloud-agent-studio
    service-cloud-agentforce-for-itsm
    service-cloud-it-fulfiller-agent
  • Employee
    sales-cloud-einstein-generative-ai
    sales-cloud-agent-studio
    service-cloud-agentforce-for-itsm
    service-cloud-requestor-agent
    service-cloud-it-service-employee-agent
Einstein Generative AI是Agentforce Studio的依赖项,验证技能不会直接报告该开关状态,但如果它处于关闭状态,则必须优先启用——分类器会将其纳入两条路径的启用计划中。

Preconditions

前置条件

Same as the validate skill (they share the target org and API surface). If unmet,
sf
surfaces an auth error or a
401
/
403
/
404
; do not fabricate state — surface the raw error and stop.
  1. sf
    CLI installed and authenticated to the target org
    (
    sf org display -o <alias>
    shows Connected). All calls use
    --target-org <alias>
    ; never extract or pass the access token by hand.
  2. API v67.0+: the
    connect/setup/discovery
    feature APIs are available at v67.0. The version is pinned in the URL path; do not hand-edit it below the minimum.
  3. node
    ≥ 18
    on PATH (runs the classifier script).
  4. Agentforce license on the org (
    accessCheck
    ) — a missing license surfaces as
    403
    or as
    enableBlockedReasons
    on the read.

与验证技能相同(两者共享目标组织和API接口)。若未满足,
sf
会显示认证错误或
401
/
403
/
404
请勿伪造状态——直接显示原始错误并停止操作
  1. 已安装
    sf
    CLI并已认证到目标组织
    sf org display -o <alias>
    显示已连接)。所有调用均使用
    --target-org <alias>
    ;切勿手动提取或传递访问令牌。
  2. API v67.0+
    connect/setup/discovery
    功能API在v67.0版本可用。URL路径中已固定版本号,请勿手动修改为低于最低要求的版本。
  3. PATH中存在
    node
    ≥ 18
    (用于运行分类器脚本)。
  4. 组织已拥有Agentforce许可证
    accessCheck
    )——缺失许可证会显示为
    403
    错误或在读取时显示
    enableBlockedReasons

Operations at a glance

操作概览

OperationCommandReturns
Read feature toggles
sf api request rest ".../connect/setup/discovery/features/status" --method POST --body '{"featureApiNames":[...]}' --target-org <alias>
{items:[{apiName,status,enableBlockedReasons[],dependencyStatuses[]}]}
Enable one toggle
sf api request rest ".../connect/setup/discovery/feature/{apiName}/enable" --method POST --body '{}' --target-org <alias>
{success:boolean}
— endpoint takes no meaningful body, but
--body '{}'
must be passed explicitly (see gotchas)
Both are Connect API routes reachable via
sf api request rest
— no Headless360 dispatcher required. Full command shapes, the response envelope, and the error taxonomy live in
references/cli-invocation.md
.
Never extract the access token. Use
sf api request rest
directly — it uses the CLI's stored session for the target org. Do not pull the
accessToken
out of
sf org display
and hand-build an HTTP request with it.
CRITICAL: DO NOT use IPCManagement
updateOrgPref
to flip agent prefs.
That controller's write allow-list rejects the agent prefNames (
Invalid prefName
, 500). The Setup Discovery
POST /feature/{apiName}/enable
endpoint is the only correct write path for these toggles.

操作命令返回结果
读取功能开关
sf api request rest ".../connect/setup/discovery/features/status" --method POST --body '{"featureApiNames":[...]}' --target-org <alias>
{items:[{apiName,status,enableBlockedReasons[],dependencyStatuses[]}]}
启用单个开关
sf api request rest ".../connect/setup/discovery/feature/{apiName}/enable" --method POST --body '{}' --target-org <alias>
{success:boolean}
— 端点不接受有效请求体,但必须显式传递
--body '{}'
(注意事项见下文)
两者均为可通过
sf api request rest
访问的Connect API路由——无需Headless360调度器。完整命令格式、响应包和错误分类请参考
references/cli-invocation.md
切勿提取访问令牌。直接使用
sf api request rest
——它会使用CLI为目标组织存储的会话信息。请勿从
sf org display
中提取
accessToken
并手动构建HTTP请求。
重要提示:请勿使用IPCManagement的
updateOrgPref
来切换代理偏好设置
。该控制器的写入白名单会拒绝代理偏好名称(
Invalid prefName
,500错误)。Setup Discovery的
POST /feature/{apiName}/enable
端点是操作这些开关的唯一正确写入路径。

Architecture — How enablement works

架构——启用流程原理

StepWhat happensTool used
Pick pathDetermine fulfiller vs employee (ask if unclear)
AskUserQuestion
Read current statePOST the feature-status batch for the path's toggles, capture to a file
Bash
(
sf api request rest
)
PlanRun
scripts/classify-enable-plan.mjs <file> <agentType> [exitStatus]
→ dependency-ordered
pending
list
Bash
(
node
)
Confirm-to-writePresent the exact
pending
list and require explicit "yes"
AskUserQuestion
EnableRe-read + reclassify before each
apiName
in
order
, POST
.../feature/{apiName}/enable
when unblocked, record the result
Bash
(
sf api request rest
+
node scripts/record-enable-result.mjs
)
VerifyRe-read
/features/status
, re-run the classifier
Bash
(
sf
+
node
)
ReportRun
scripts/classify-final-report.mjs
over the before/results/after files → final verdict
Bash
(
node
)

步骤操作内容使用工具
选择路径确定是Fulfiller还是Employee路径(若不确定则询问)
AskUserQuestion
读取当前状态批量POST路径所需开关的状态,将结果捕获到文件中
Bash
sf api request rest
生成计划运行
scripts/classify-enable-plan.mjs <file> <agentType> [exitStatus]
→ 按依赖顺序排列的
pending
列表
Bash
node
确认写入显示确切的
pending
列表并要求用户明确回复"yes"
AskUserQuestion
启用开关在启用
order
中的每个
<apiName>
前重新读取并重新分类,当开关未被阻止时POST
.../feature/{apiName}/enable
,记录结果
Bash
sf api request rest
+
node scripts/record-enable-result.mjs
验证重新读取
/features/status
,重新运行分类器
Bash
sf
+
node
生成报告运行
scripts/classify-final-report.mjs
处理写入前/结果/写入后的文件 → 最终判定结果
Bash
node

Workflow

工作流程

Substitute
<alias>
with the target org alias.
<agentType>
is
fulfiller
or
employee
.
<alias>
替换为目标组织别名。
<agentType>
fulfiller
employee

Phase 1 — Read Current State

阶段1 — 读取当前状态

  1. POST the feature-status batch for every toggle the chosen path needs, capturing stdout to a file. Do not add
    --json
    . Write the request body once to a temp file and reuse it verbatim in Phases 1, 4, and 5 via
    --body "$(cat ...)"
    — never retype it, substitute a placeholder like
    [...]
    , or rely on a shell variable, since each Bash invocation may run in a fresh shell where a plain variable would be unset:
    bash
    cat > /tmp/feature-status-body.json <<'EOF'
    {"featureApiNames":["sales-cloud-einstein-generative-ai","sales-cloud-agent-studio","service-cloud-agentforce-for-itsm","service-cloud-it-fulfiller-agent","service-cloud-requestor-agent","service-cloud-it-service-employee-agent"]}
    EOF
    
    sf api request rest "/services/data/v67.0/connect/setup/discovery/features/status" \
      --method POST \
      --body "$(cat /tmp/feature-status-body.json)" \
      --target-org <alias> > /tmp/enable-status-before.json 2>/tmp/enable-status-before.err
    echo $? > /tmp/enable-status-before.exit
    Capture the exit status — do not swallow it with
    || true
    .
  1. POST所选路径所需所有开关的状态,将标准输出捕获到文件中。请勿添加
    --json
    。将请求体一次性写入临时文件,并在阶段1、4、5中通过
    --body "$(cat ...)"
    重复使用——切勿重新输入、替换为
    [...]
    之类的占位符或依赖shell变量,因为每个Bash调用可能在全新的shell中运行,普通变量可能未设置:
    bash
    cat > /tmp/feature-status-body.json <<'EOF'
    {"featureApiNames":["sales-cloud-einstein-generative-ai","sales-cloud-agent-studio","service-cloud-agentforce-for-itsm","service-cloud-it-fulfiller-agent","service-cloud-requestor-agent","service-cloud-it-service-employee-agent"]}
    EOF
    
    sf api request rest "/services/data/v67.0/connect/setup/discovery/features/status" \
      --method POST \
      --body "$(cat /tmp/feature-status-body.json)" \
      --target-org <alias> > /tmp/enable-status-before.json 2>/tmp/enable-status-before.err
    echo $? > /tmp/enable-status-before.exit
    捕获退出状态——请勿使用
    || true
    忽略它。

Phase 2 — Plan (helper script)

阶段2 — 生成计划(辅助脚本)

  1. Run the classifier over the captured file to compute the dependency-ordered enable plan, saving its output — Phase 6 consumes this file, not the raw
    /features/status
    response:
    bash
    node "<skill_dir>/scripts/classify-enable-plan.mjs" /tmp/enable-status-before.json <agentType> "$(cat /tmp/enable-status-before.exit)" > /tmp/enable-plan-before.json
    It prints
    { agentType, readState, features, order, alreadyEnabled, pending, blocked, unconfirmed, verdict, reasons, rawError }
    .
    verdict: "ALL-ENABLED"
    means nothing to do — skip to Phase 6.
    verdict: "NEEDS-ENABLE"
    means
    pending
    (in
    order
    ) lists what to enable.
    blocked
    lists any
    pending
    toggle whose
    enableBlockedReasons
    is non-empty as of this read — a toggle blocked only on an earlier dependency in
    order
    becomes enable-able once that dependency is on, so Phase 4 re-checks each toggle immediately before attempting it rather than trusting this snapshot for the whole loop.
    unconfirmed
    lists any required toggle missing from the response or carrying a status this classifier doesn't recognize —
    verdict: "CANNOT-CONFIRM"
    (not
    "ALL-ENABLED"
    ) when
    unconfirmed
    is non-empty and
    pending
    is empty.
    readState: "error"
    ⇒ surface
    rawError
    and stop;
    readState: "not-wired"
    ⇒ report CANNOT-CONFIRM and stop.
  1. 对捕获的文件运行分类器,计算按依赖顺序排列的启用计划,保存输出结果——阶段6会使用此文件,而非原始的
    /features/status
    响应:
    bash
    node "<skill_dir>/scripts/classify-enable-plan.mjs" /tmp/enable-status-before.json <agentType> "$(cat /tmp/enable-status-before.exit)" > /tmp/enable-plan-before.json
    输出内容为
    { agentType, readState, features, order, alreadyEnabled, pending, blocked, unconfirmed, verdict, reasons, rawError }
    。若
    verdict: "ALL-ENABLED"
    则无需执行任何操作——直接跳至阶段6。若
    verdict: "NEEDS-ENABLE"
    pending
    (位于
    order
    中)列出需要启用的开关。
    blocked
    列出当前读取状态下
    enableBlockedReasons
    非空的
    pending
    开关——仅因
    order
    中更早的依赖项未启用而被阻止的开关,在依赖项启用后即可变为可启用状态,因此阶段4会在尝试启用每个开关前立即重新检查,而非依赖阶段2的快照。
    unconfirmed
    列出响应中缺失或状态无法被分类器识别的必需开关——当
    unconfirmed
    非空且
    pending
    为空时,
    verdict: "CANNOT-CONFIRM"
    (而非
    "ALL-ENABLED"
    )。若
    readState: "error"
    则显示
    rawError
    并停止操作;若
    readState: "not-wired"
    则报告CANNOT-CONFIRM并停止操作。

Phase 3 — Confirm-to-Write Checkpoint (REQUIRED)

阶段3 — 确认写入检查点(必需)

  1. Present the exact
    pending
    list
    (excluding anything in
    blocked
    ) and require an explicit "yes" from the user via
    AskUserQuestion
    before proceeding. Enabling org prefs mutates org state. Proceed to Phase 4 ONLY on an explicit "yes". On "no", stop and report the current state without any writes.
  1. 显示确切的
    pending
    列表
    (排除
    blocked
    中的内容),并通过
    AskUserQuestion
    要求用户明确回复"yes"后再继续。启用组织偏好设置会修改组织状态。仅在用户明确回复"yes"时才进入阶段4。若回复"no",则停止操作并报告当前状态,不执行任何写入。

Phase 4 — Enable (Dependencies First, Re-Checked Before Each Toggle)

阶段4 — 启用开关(优先处理依赖项,每个开关前重新检查)

  1. Iterate
    order
    in sequence (Einstein GenAI → Studio → parent → child template(s)). Before attempting to enable each
    <apiName>
    , re-read and reclassify — this is what lets a child that was
    blocked
    in Phase 2 (only because Studio/parent was still off) become enable-able once that dependency's own enable has landed, instead of being permanently written off from the Phase-2 snapshot:
    bash
    sf api request rest "/services/data/v67.0/connect/setup/discovery/features/status" \
      --method POST \
      --body "$(cat /tmp/feature-status-body.json)" \
      --target-org <alias> > /tmp/enable-status-loop.json 2>/tmp/enable-status-loop.err
    echo $? > /tmp/enable-status-loop.exit
    node "<skill_dir>/scripts/classify-enable-plan.mjs" /tmp/enable-status-loop.json <agentType> "$(cat /tmp/enable-status-loop.exit)"
    Inspect
    features["<apiName>"].signal
    from that output:
    • PASS
      → already
      ENABLED
      ; nothing to do, move to the next
      apiName
      in
      order
      .
    • FAIL
      with an empty
      enableBlockedReasons
      → enable it now:
      bash
      sf api request rest "/services/data/v67.0/connect/setup/discovery/feature/<apiName>/enable" \
        --method POST \
        --body '{}' \
        --target-org <alias> > /tmp/enable-<apiName>.json 2>/tmp/enable-<apiName>.err
      node "<skill_dir>/scripts/record-enable-result.mjs" /tmp/enable-<apiName>.json <apiName> /tmp/enable-results.json
      The
      /enable
      endpoint itself takes no meaningful body, but
      sf api request rest --method POST
      with no
      --body
      flag at all fails with
      Error (SfError): No 'mode' found in 'body' entry
      — always pass
      --body '{}'
      explicitly.
      record-enable-result.mjs
      reads the response, classifies it ENABLED/FAILED, and accumulates it into
      /tmp/enable-results.json
      keyed by
      apiName
      — the deterministic per-toggle bookkeeping Phase 6 consumes.
    • FAIL
      with a non-empty
      enableBlockedReasons
      → still blocked even after this iteration's re-check (a real, not merely-sequential, blocker — e.g. unlicensed) — do not POST; move to the next
      apiName
      in
      order
      and let Phase 6 report the blocker verbatim.
    • CANNOT-CONFIRM
      /
      ERROR
      on this specific
      apiName
      's read → stop the loop and surface the read failure; do not guess at remaining toggles.
    One failed toggle does not block the rest of the plan — continue the loop.
  1. 按顺序遍历
    order
    (Einstein GenAI → Studio → 父级开关 → 子模板)。在尝试启用每个
    <apiName>
    前,重新读取并重新分类——这样阶段2中因依赖项未启用而被
    blocked
    的子开关,在依赖项启用后即可变为可启用状态,而非因阶段2的快照而被判定为FAILED:
    bash
    sf api request rest "/services/data/v67.0/connect/setup/discovery/features/status" \
      --method POST \
      --body "$(cat /tmp/feature-status-body.json)" \
      --target-org <alias> > /tmp/enable-status-loop.json 2>/tmp/enable-status-loop.err
    echo $? > /tmp/enable-status-loop.exit
    node "<skill_dir>/scripts/classify-enable-plan.mjs" /tmp/enable-status-loop.json <agentType> "$(cat /tmp/enable-status-loop.exit)"
    检查输出中的
    features["<apiName>"].signal
    • PASS
      → 已处于
      ENABLED
      状态;无需操作,继续处理
      order
      中的下一个
      apiName
    • FAIL
      enableBlockedReasons
      为空 → 立即启用:
      bash
      sf api request rest "/services/data/v67.0/connect/setup/discovery/feature/<apiName>/enable" \
        --method POST \
        --body '{}' \
        --target-org <alias> > /tmp/enable-<apiName>.json 2>/tmp/enable-<apiName>.err
      node "<skill_dir>/scripts/record-enable-result.mjs" /tmp/enable-<apiName>.json <apiName> /tmp/enable-results.json
      /enable
      端点本身不接受有效请求体,但
      sf api request rest --method POST
      若未传递
      --body
      标志会报错
      Error (SfError): No 'mode' found in 'body' entry
      ——必须始终显式传递
      --body '{}'
      record-enable-result.mjs
      会读取响应,将其分类为ENABLED/FAILED,并将结果累积到
      /tmp/enable-results.json
      中(以
      apiName
      为键)——阶段6会使用此确定性的每个开关记录信息。
    • FAIL
      enableBlockedReasons
      非空 → 即使本次重新检查后仍被阻止(真实的、非顺序性的阻止因素,例如无许可证)——请勿执行POST;继续处理
      order
      中的下一个
      apiName
      ,由阶段6直接报告阻止原因。
    • 读取此特定
      apiName
      时出现
      CANNOT-CONFIRM
      /
      ERROR
      → 停止循环并显示读取失败;请勿猜测剩余开关的状态。
    单个开关启用失败不会阻止计划的其余部分——继续执行循环。

Phase 5 — Verify Enablement

阶段5 — 验证启用状态

  1. Re-run the Phase 1 read (same
    /tmp/feature-status-body.json
    ) into a fresh file, and re-run the classifier over it, saving its output for Phase 6:
    bash
    sf api request rest "/services/data/v67.0/connect/setup/discovery/features/status" \
      --method POST \
      --body "$(cat /tmp/feature-status-body.json)" \
      --target-org <alias> > /tmp/enable-status-after.json 2>/tmp/enable-status-after.err
    echo $? > /tmp/enable-status-after.exit
    node "<skill_dir>/scripts/classify-enable-plan.mjs" /tmp/enable-status-after.json <agentType> "$(cat /tmp/enable-status-after.exit)" > /tmp/enable-plan-after.json
    verdict: "ALL-ENABLED"
    ⇒ every toggle in
    order
    is confirmed
    ENABLED
    — success. Anything still in
    pending
    /
    blocked
    /
    unconfirmed
    needs Phase 6 to classify it precisely (FAILED vs CANNOT-CONFIRM).
  1. 重新执行阶段1的读取操作(使用相同的
    /tmp/feature-status-body.json
    )并保存到新文件中,然后对其重新运行分类器,保存输出结果供阶段6使用:
    bash
    sf api request rest "/services/data/v67.0/connect/setup/discovery/features/status" \
      --method POST \
      --body "$(cat /tmp/feature-status-body.json)" \
      --target-org <alias> > /tmp/enable-status-after.json 2>/tmp/enable-status-after.err
    echo $? > /tmp/enable-status-after.exit
    node "<skill_dir>/scripts/classify-enable-plan.mjs" /tmp/enable-status-after.json <agentType> "$(cat /tmp/enable-status-after.exit)" > /tmp/enable-plan-after.json
    verdict: "ALL-ENABLED"
    order
    中的所有开关均已确认处于
    ENABLED
    状态——操作成功。若仍有开关处于
    pending
    /
    blocked
    /
    unconfirmed
    状态,则需要阶段6进行精确分类(FAILED vs CANNOT-CONFIRM)。

Phase 6 — Aggregate Verdict (helper script)

阶段6 — 汇总判定结果(辅助脚本)

  1. Run the final aggregator over the Phase-2 classifier output (
    /tmp/enable-plan-before.json
    , not the raw
    /features/status
    response), the Phase-4 accumulated results (or
    -
    if Phase 2 was already
    ALL-ENABLED
    /
    CANNOT-CONFIRM
    /
    ERROR
    and Phase 4 never ran), and the Phase-5 classifier output (
    /tmp/enable-plan-after.json
    ):
    bash
    node "<skill_dir>/scripts/classify-final-report.mjs" /tmp/enable-plan-before.json /tmp/enable-results.json /tmp/enable-plan-after.json
    It prints
    { features: { <apiName>: { finalStatus, reason } }, order, overall, reasons }
    where
    finalStatus
    is
    ALREADY-ENABLED | ENABLED | FAILED | CANNOT-CONFIRM | ERROR
    and
    overall
    is
    SUCCESS | PARTIAL | FAILED | CANNOT-CONFIRM | ERROR
    . Render this directly into the Output Format — do not re-derive the per-feature verdict or the overall summary in prose (authoring standard A9). On
    overall: "SUCCESS"
    , point the user at
    service-itsm-agentic-setup-fulfiller-agent-configure
    (fulfiller) or
    service-itsm-agentic-setup-employee-agent-configure
    (employee) to proceed.

  1. 运行最终汇总脚本,处理阶段2的分类器输出(
    /tmp/enable-plan-before.json
    ,而非原始的
    /features/status
    响应)、阶段4的累积结果(若阶段2已为
    ALL-ENABLED
    /
    CANNOT-CONFIRM
    /
    ERROR
    且未执行阶段4,则传递
    -
    )以及阶段5的分类器输出(
    /tmp/enable-plan-after.json
    ):
    bash
    node "<skill_dir>/scripts/classify-final-report.mjs" /tmp/enable-plan-before.json /tmp/enable-results.json /tmp/enable-plan-after.json
    输出内容为
    { features: { <apiName>: { finalStatus, reason } }, order, overall, reasons }
    ,其中
    finalStatus
    ALREADY-ENABLED | ENABLED | FAILED | CANNOT-CONFIRM | ERROR
    overall
    SUCCESS | PARTIAL | FAILED | CANNOT-CONFIRM | ERROR
    。直接将此结果渲染为输出格式——请勿通过文字描述重新推导每个开关的判定结果或总体摘要(创作标准A9)。若
    overall: "SUCCESS"
    ,请引导用户使用
    service-itsm-agentic-setup-fulfiller-agent-configure
    (Fulfiller)或
    service-itsm-agentic-setup-employee-agent-configure
    (Employee)继续操作。

Rules / Constraints

规则/约束

ConstraintRationale
Enable via
POST /connect/setup/discovery/feature/{apiName}/enable
only
The IPCManagement
updateOrgPref
write allow-list rejects the agent prefNames (
Invalid prefName
) — this is the only correct write path
Read live per-feature state from
POST /features/status
, never a flat catalog list
Only
/status
carries per-org
ENABLED
/
NOT_ENABLED
+
enableBlockedReasons[]
+
dependencyStatuses[]
Enable dependencies before children, in the classifier's
order
Enabling a child before Einstein GenAI / Studio surfaces unmet-dependency blockers
Re-read and reclassify immediately before each toggle in the Phase-4 loop, not once at the top of the loopA child
blocked
only because an earlier dependency was still off becomes enable-able the instant that dependency's own
/enable
lands — a single Phase-2 snapshot would report it FAILED even though it was never really blocked
Idempotent: skip
/enable
for anything already
ENABLED
The classifier's
alreadyEnabled
list is authoritative; enabling an already-enabled feature returns
{success:true}
but is redundant
REQUIRED confirm-to-write checkpoint before any
/enable
POST
Enabling org prefs mutates org state; the user must explicitly approve the exact
pending
list
Never attempt to enable a toggle whose current (re-checked)
enableBlockedReasons
is non-empty
Non-empty
enableBlockedReasons
means the write would fail — report the blocker instead of a doomed POST
verdict: "CANNOT-CONFIRM"
when
unconfirmed
is non-empty, even if
pending
is empty
A required toggle missing from the response, or with an unrecognized status, must not be reported as ALL-ENABLED just because nothing is left in
pending
Classification and per-toggle result recording live in
scripts/classify-enable-plan.mjs
,
scripts/record-enable-result.mjs
, and
scripts/classify-final-report.mjs
, invoked via
Bash
— not in prose
Deterministic decision tables and aggregation over fixed feature statuses (authoring standard A9)
The read/write goes through
sf api request rest
; never extract the access token
sf api request rest
uses the CLI's stored session for
--target-org
Do not pass
--json
to
sf api request rest
Unsupported on some Connect endpoints; the raw stdout body is already JSON
These are Connect API features — use SF CLI, not Headless360A Connect/Tooling equivalent exists, so SF CLI is preferred (avoids the Headless360HostedMcpServer org-perm gate)

约束理由
仅通过
POST /connect/setup/discovery/feature/{apiName}/enable
启用开关
IPCManagement的
updateOrgPref
写入白名单会拒绝代理偏好名称(
Invalid prefName
)——这是唯一正确的写入路径
POST /features/status
读取每个功能的实时状态,而非静态目录列表
只有
/status
会返回每个组织的
ENABLED
/
NOT_ENABLED
状态 +
enableBlockedReasons[]
+
dependencyStatuses[]
按分类器的
order
优先启用依赖项,再启用子项
在Einstein GenAI/Studio启用前启用子项会显示未满足依赖的阻止信息
在阶段4循环中,每个开关启用前立即重新读取并重新分类,而非仅在循环开始时读取一次仅因早期依赖项未启用而被阻止的子开关,在依赖项启用后立即变为可启用状态——仅阶段2的单次快照会错误地将其报告为FAILED,即使它从未真正被阻止
幂等性:跳过已处于
ENABLED
状态的开关的
/enable
操作
分类器的
alreadyEnabled
列表是权威的;启用已启用的功能会返回
{success:true}
但属于冗余操作
必需的确认写入检查点,在执行任何
/enable
POST前
启用组织偏好设置会修改组织状态;用户必须明确批准确切的
pending
列表
切勿尝试启用当前(重新检查后)
enableBlockedReasons
非空的开关
enableBlockedReasons
非空意味着写入操作会失败——直接报告阻止原因,而非执行注定失败的POST
unconfirmed
非空时,即使
pending
为空,
verdict: "CANNOT-CONFIRM"
响应中缺失或状态无法识别的必需开关,既不能被确认为ENABLED,也不能被确认为NOT_ENABLED
分类和每个开关的结果记录逻辑位于
scripts/classify-enable-plan.mjs
scripts/record-enable-result.mjs
scripts/classify-final-report.mjs
中,通过
Bash
调用——而非文字描述
基于固定功能状态的确定性决策表和汇总逻辑(创作标准A9)
读取/写入操作通过
sf api request rest
执行;切勿提取访问令牌
sf api request rest
会使用
--target-org
对应的CLI存储会话
请勿向
sf api request rest
传递
--json
部分Connect端点不支持该参数;原始标准输出已为JSON格式
这些是Connect API功能——使用SF CLI,而非Headless360存在对应的Connect/Tooling等效接口,因此优先使用SF CLI(避免Headless360HostedMcpServer组织权限限制)

Gotchas

注意事项

IssueResolution
sf api request rest --method POST
with no
--body
flag errors
No 'mode' found in 'body' entry
The
/enable
endpoint itself takes no meaningful body, but the CLI still requires the flag — always pass
--body '{}'
explicitly (verified on CLI 2.140.6 and 2.145.6)
Feature API name unavailable / unlicensed on the orgNo catalog endpoint enumerates valid names — the Phase-1
/features/status
read surfaces an unavailable/unlicensed feature via
enableBlockedReasons[]
before any enable attempt
/features/status
shows
NOT_ENABLED
with
dependencyStatuses[]
unmet
Enable the listed dependency first (Einstein GenAI before Studio, Studio before the parent/child toggles)
updateOrgPref
→ 500
Invalid prefName
for an agent pref
Wrong write path — use the Setup Discovery
feature/{apiName}/enable
endpoint instead
Auth error from
sf api request rest
The target org's session needs re-authentication (
sf org login web
)
Treating an auth/permission/empty-body read failure as "not wired"Pass the captured
$?
as the classifier's 3rd arg — only a confirmed 404 is CANNOT-CONFIRM; anything else is ERROR (surface
rawError
, stop)
Trusting the Phase-2
blocked
list for the entire Phase-4 loop
It is a snapshot before any write — re-read + reclassify before each toggle attempt instead, or a dependency-blocked child gets reported FAILED even after its blocker was just cleared
Reporting
ALL-ENABLED
because
pending
is empty
Also check
unconfirmed
— a required toggle missing from the response or with an unrecognized status is neither confirmed ENABLED nor NOT_ENABLED
Re-deriving the per-feature / overall verdict in prose from the before/after JSONRun
scripts/classify-final-report.mjs
— the aggregation is fixed comparison logic (authoring standard A9), not a judgment call
Setting the feature-status request body in a shell variable in Phase 1 and expecting it in Phase 4/5Each
Bash
invocation may run in a fresh shell where the variable is unset, silently sending an empty body — persist it to
/tmp/feature-status-body.json
once and read it back with
--body "$(cat /tmp/feature-status-body.json)"
in every phase

问题解决方案
sf api request rest --method POST
未传递
--body
标志时报错
No 'mode' found in 'body' entry
/enable
端点本身不接受有效请求体,但CLI仍需要该标志——始终显式传递
--body '{}'
(已在CLI 2.140.6和2.145.6版本验证)
组织中不存在功能API名称/无对应许可证无目录端点枚举有效名称——阶段1的
/features/status
读取会在尝试启用前通过
enableBlockedReasons[]
显示不可用/无许可证的功能
/features/status
显示
NOT_ENABLED
dependencyStatuses[]
未满足
优先启用列出的依赖项(Einstein GenAI在Studio之前,Studio在父级/子级开关之前)
updateOrgPref
→ 代理偏好设置出现500错误
Invalid prefName
写入路径错误——使用Setup Discovery的
feature/{apiName}/enable
端点替代
sf api request rest
出现认证错误
目标组织的会话需要重新认证(
sf org login web
将认证/权限/空请求体读取错误视为"not wired"将捕获的
$?
作为分类器的第三个参数传递——仅确认的404错误为CANNOT-CONFIRM;其他情况均为ERROR(显示
rawError
并停止操作)
依赖阶段2的
blocked
列表执行整个阶段4循环
该列表是写入前的快照——在尝试启用每个开关前重新读取并重新分类,否则依赖项已启用后不再被阻止的子开关仍会被报告为FAILED
pending
为空而报告
ALL-ENABLED
同时检查
unconfirmed
——响应中缺失或状态无法识别的必需开关,既不能被确认为ENABLED,也不能被确认为NOT_ENABLED
通过文字描述从写入前/后JSON重新推导每个开关/总体判定结果运行
scripts/classify-final-report.mjs
——汇总逻辑为固定的比较逻辑(创作标准A9),而非主观判断
在阶段1将功能状态请求体设置为shell变量,并期望在阶段4/5中使用每个Bash调用可能在全新的shell中运行,变量可能未设置,导致静默发送空请求体——将请求体一次性保存到
/tmp/feature-status-body.json
,并在每个阶段通过
--body "$(cat /tmp/feature-status-body.json)"
读取

Verification Checklist

验证检查清单

  • The agent path (fulfiller / employee) was determined (asked if unclear).
  • Phase 1 read
    /features/status
    via
    sf api request rest
    , captured to a file, with its exit status captured.
  • scripts/classify-enable-plan.mjs
    computed the
    pending
    (dependency-ordered),
    blocked
    , and
    unconfirmed
    lists before any write.
  • The user explicitly confirmed the exact
    pending
    list at the Phase-3 checkpoint before any
    /enable
    POST.
  • Phase 4 re-read and reclassified before each toggle, not once for the whole loop — so a child unblocked by an earlier dependency's enable was still attempted.
  • Each attempted
    /enable
    POST's response was recorded via
    scripts/record-enable-result.mjs
    , accumulated across the loop.
  • /features/status
    was re-read after enablement and the classifier re-run to confirm the final per-feature verdict.
  • scripts/classify-final-report.mjs
    (not prose) computed the final per-feature status and overall summary from the before/results/after files; the access token was never extracted.

  • 已确定代理路径(Fulfiller/Employee)(若不确定则已询问用户)。
  • 阶段1通过
    sf api request rest
    读取
    /features/status
    ,并将结果捕获到文件中,同时捕获了退出状态。
  • scripts/classify-enable-plan.mjs
    在写入前计算了
    pending
    (按依赖顺序)、
    blocked
    unconfirmed
    列表。
  • 在阶段3检查点,用户已明确确认确切的
    pending
    列表,之后才执行任何
    /enable
    POST。
  • 阶段4在每个开关启用前重新读取并重新分类,而非仅在循环开始时读取一次——因此依赖项启用后不再被阻止的子开关仍会被尝试启用。
  • 每个尝试的
    /enable
    POST响应均通过
    scripts/record-enable-result.mjs
    记录,并在循环中累积。
  • 启用后重新读取
    /features/status
    并重新运行分类器,以确认每个功能的最终判定结果。
  • scripts/classify-final-report.mjs
    (而非文字描述)根据写入前/结果/写入后的文件计算了每个功能的最终状态和总体摘要;从未提取访问令牌。

Output Format

输出格式

Present the enablement report as:
text
Agentforce for IT Service — Enable Prerequisites (via service-itsm-agentic-setup-agentforce-studio-configure)

Org:          <org-alias> (API v67.0)
Agent path:   fulfiller | employee

  [1] Einstein Generative AI ................. ENABLED | ALREADY-ENABLED | FAILED | CANNOT-CONFIRM
  [2] Agentforce Studio ...................... ENABLED | ALREADY-ENABLED | FAILED | CANNOT-CONFIRM
  [3] Agentforce for IT Service (parent) ..... ENABLED | ALREADY-ENABLED | FAILED | CANNOT-CONFIRM
  [4] <path-specific template(s)> ............ ENABLED | ALREADY-ENABLED | FAILED | CANNOT-CONFIRM

Verdict: SUCCESS  |  PARTIAL  |  FAILED  |  CANNOT-CONFIRM  |  ERROR

Next steps:
  - <If SUCCESS: "Org satisfies the prerequisites for the <path> agent. Create it via service-itsm-agentic-setup-fulfiller-agent-configure (fulfiller) / the employee-agent skill.">
  - <If PARTIAL/FAILED/CANNOT-CONFIRM/ERROR: list the affected toggle(s) + reason (enableBlockedReasons, unconfirmed status, or read error) + remediation steps>
Render
overall
and each feature's
finalStatus
from
scripts/classify-final-report.mjs
verbatim — do not recompute them. No files are produced beyond the temporary response captures used by the classifiers.

按以下格式呈现启用报告:
text
Agentforce for IT Service — 启用前置条件(通过service-itsm-agentic-setup-agentforce-studio-configure)

组织:          <org-alias> (API v67.0)
代理路径:   fulfiller | employee

  [1] Einstein Generative AI ................. ENABLED | ALREADY-ENABLED | FAILED | CANNOT-CONFIRM
  [2] Agentforce Studio ...................... ENABLED | ALREADY-ENABLED | FAILED | CANNOT-CONFIRM
  [3] Agentforce for IT Service (父级) ..... ENABLED | ALREADY-ENABLED | FAILED | CANNOT-CONFIRM
  [4] <路径特定模板> ............ ENABLED | ALREADY-ENABLED | FAILED | CANNOT-CONFIRM

判定结果: SUCCESS  |  PARTIAL  |  FAILED  |  CANNOT-CONFIRM  |  ERROR

下一步操作:
  - <若SUCCESS: "组织已满足<路径>代理的前置条件。通过service-itsm-agentic-setup-fulfiller-agent-configure(Fulfiller)/员工代理技能创建代理。">
  - <若PARTIAL/FAILED/CANNOT-CONFIRM/ERROR: 列出受影响的开关 + 原因(enableBlockedReasons、未确认状态或读取错误) + 修复步骤>
直接渲染
scripts/classify-final-report.mjs
返回的
overall
和每个功能的
finalStatus
——请勿重新计算。除分类器使用的临时响应捕获文件外,不生成其他文件。

Reference File Index

参考文件索引

FileWhen to read
references/cli-invocation.md
Every phase — exact
sf api request rest
read/write call shapes, response envelope, feature API names, the classifier contract, and the error taxonomy
文件阅读时机
references/cli-invocation.md
每个阶段——确切的
sf api request rest
读取/写入命令格式、响应包、功能API名称、分类器规范和错误分类