service-itsm-agentic-setup-employee-agent-configure

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Create an IT Service Employee Agent (broad or specialized)

创建IT服务员工Agent(通用或专用)

Create and activate an IT Service Employee Agent as a Next-Gen Authoring (NGA) native agent — Agent-Script-based (
AiAuthoringBundleDefVer
/bundle), appearing natively in Agentforce Studio's Agents list with no external-link icon — entirely through the Salesforce CLI (
sf
)
. This skill does not call the legacy
/connect/service-itsm/createAgent
; instead it reuses a shipped ITSM Employee template's
agentScript
field and feeds it into the NGA bundle pipeline:
POST /nextgen-authoring/bundles
POST /nextgen-authoring/bundle-versions/{id}/publish
POST /nextgen-authoring/bundle-versions/{id}/activate
. Commands:
sf api request rest
for Connect API GET/POST;
sf data query
for the SOQL idempotency + verify reads.
GET /connect/service-itsm/agent-templates?agentType=AgentforceEmployeeAgent
returns the broad
IT Service Employee
template plus ~47 specialized Employee templates under the
svc_emp_intelligence__
namespace as siblings in
data[]
. Every specialized template ships the same
agentScript
shape with the same
config.developer_name
/
config.agent_label
substitution points, so the same NGA sequence works for any of them — only the
masterLabel
that Phases 1 and 4 pin against changes.
Full catalog + namespace filter + disambiguation rules live in
references/specialized-templates.md
.
Helper scripts (invoked via
Bash
) hold every JSON-parsing / decision rule so the model never eyeballs a response body (A9):
classify-preflight.mjs
,
classify-agent-existence.mjs
,
build-create-body.mjs
(HTML-decodes + substitutes the template's
agentScript
and writes the body to a JSON file so large content and free-text quotes never hit an inline shell string),
render-report.mjs
(deterministic report renderer).
Template selection (before Phase 1). Resolve the
<masterLabel>
this run pins: (1) no specialization named ⇒ pin
IT Service Employee
(id
svc_emp_intelligence__ItEmployeeAssistance
) — the backwards-compatible default; (2) user names a specialization ⇒ keyword-match against
references/specialized-templates.md
, single unambiguous match ⇒ pin that
masterLabel
and derive
developerName
from
id
after
__
(snake-cased); ambiguous ⇒
AskUserQuestion
keyed on
id
; (3) filter
data[]
to
svc_emp_intelligence__
only
svc_itsm_intelligence__*
(Fulfiller) redirects to
service-itsm-agentic-setup-fulfiller-agent-configure
, other namespaces are out of scope. The resolved
<masterLabel>
is the single knob passed to
classify-preflight.mjs
(Phase 1) and
build-create-body.mjs
(Phase 4).
Prerequisites. Creation assumes the org-level Agentforce for IT Service prerequisites are already satisfied (Agentforce Studio access +
service-cloud-requestor-agent
+
service-cloud-it-service-employee-agent
). If Phase 1 detects Studio is not accessible — or if any write returns
403 FUNCTIONALITY_NOT_ENABLED
— this skill offers to delegate to
service-itsm-agentic-setup-agentforce-studio-validate
(employee path) then resume; on "no", stops. This skill never enables features itself — enablement is a Setup-UI/admin action.
创建并激活一个IT服务员工Agent作为下一代创作(NGA)原生Agent——基于Agent脚本(
AiAuthoringBundleDefVer
/包),在Agentforce Studio的Agent列表中以原生形式显示,无外部链接图标——全程通过**Salesforce CLI(
sf
)**完成。本技能不会调用旧版
/connect/service-itsm/createAgent
接口
;而是复用已发布的ITSM员工模板的
agentScript
字段,并将其输入到NGA包流水线中:
POST /nextgen-authoring/bundles
POST /nextgen-authoring/bundle-versions/{id}/publish
POST /nextgen-authoring/bundle-versions/{id}/activate
。使用的命令:
sf api request rest
用于Connect API的GET/POST请求;
sf data query
用于SOQL幂等性检查和验证读取。
GET /connect/service-itsm/agent-templates?agentType=AgentforceEmployeeAgent
接口会返回通用
IT Service Employee
模板,以及约47个属于
svc_emp_intelligence__
命名空间的专用员工模板,它们在
data[]
中同级显示。每个专用模板的
agentScript
结构相同,且包含相同的
config.developer_name
/
config.agent_label
替换点,因此同一套NGA流程适用于所有模板——仅需修改第1阶段和第4阶段所关联的
masterLabel
。完整的模板目录、命名空间过滤规则及消歧规则可查看
references/specialized-templates.md
辅助脚本(通过
Bash
调用)包含所有JSON解析/决策逻辑,避免模型直接解析响应体(规则A9):
classify-preflight.mjs
classify-agent-existence.mjs
build-create-body.mjs
(对模板的
agentScript
进行HTML解码和替换,并将请求体写入JSON文件,避免大内容和自由文本引号出现在内联shell字符串中)、
render-report.mjs
(确定性报告渲染器)。
模板选择(第1阶段前)。确定本次运行要关联的
<masterLabel>
:(1) 用户未指定专用模板 ⇒ 关联
IT Service Employee
(ID为
svc_emp_intelligence__ItEmployeeAssistance
)——向后兼容的默认选项;(2) 用户指定了专用模板 ⇒ 通过
references/specialized-templates.md
进行关键词匹配,匹配结果唯一明确 ⇒ 关联该
masterLabel
,并从ID中
__
后的部分派生
developerName
(蛇形命名);匹配结果模糊 ⇒ 触发
AskUserQuestion
,以ID为键进行询问;(3)
data[]
过滤为仅包含
svc_emp_intelligence__
命名空间的模板
——
svc_itsm_intelligence__*
(处理者模板)会重定向到
service-itsm-agentic-setup-fulfiller-agent-configure
流程,其他命名空间的模板不在本技能范围内。确定后的
<masterLabel>
会传入
classify-preflight.mjs
(第1阶段)和
build-create-body.mjs
(第4阶段)。
前置条件。创建Agent的前提是,组织级别的Agentforce for IT Service前置条件已满足(拥有Agentforce Studio访问权限 +
service-cloud-requestor-agent
+
service-cloud-it-service-employee-agent
权限)。如果第1阶段检测到无法访问Studio——或任何写入操作返回
403 FUNCTIONALITY_NOT_ENABLED
——本技能会主动提议将任务委托给
service-itsm-agentic-setup-agentforce-studio-validate
(员工路径),然后继续流程;若用户拒绝,则停止操作。本技能不会自行启用任何功能——功能启用属于Setup-UI/管理员操作。

Scope

范围

  • In scope: Reading
    agent-templates
    ; extracting an Employee template's Agent Script (broad default or a user-named specialization from
    references/specialized-templates.md
    — all under
    svc_emp_intelligence__
    ); creating the Employee agent as an NGA-native agent via
    createBundleWithVersion
    publish
    activate
    ; SOQL-verifying live; idempotent skip on duplicate developer name — all via
    sf
    .
  • Out of scope: The Fulfiller agent (
    service-itsm-agentic-setup-fulfiller-agent-configure
    ); enabling org-level feature toggles (validated by
    service-itsm-agentic-setup-agentforce-studio-validate
    ); low-level topic/action authoring; perm-set assignment; content-bundle deployment; CMDB CRUD; Discovery / Service Graph; the legacy
    createAgent
    route; any
    data[]
    entry outside
    svc_emp_intelligence__
    .

  • 包含范围:读取
    agent-templates
    ;提取员工模板的Agent脚本(通用默认模板或用户指定的专用模板,均来自
    references/specialized-templates.md
    且属于
    svc_emp_intelligence__
    命名空间);通过
    createBundleWithVersion
    publish
    activate
    流程将员工Agent创建为NGA原生Agent;通过SOQL验证Agent是否生效;基于重复开发者名称实现幂等性跳过——所有操作均通过
    sf
    完成。
  • 排除范围:处理者Agent(
    service-itsm-agentic-setup-fulfiller-agent-configure
    流程);启用组织级功能开关(由
    service-itsm-agentic-setup-agentforce-studio-validate
    流程验证);低级别主题/动作创作;权限集分配;内容包部署;CMDB增删改查;Discovery/服务图谱;旧版
    createAgent
    路由;
    data[]
    中不属于
    svc_emp_intelligence__
    命名空间的任何条目。

Preconditions

前置条件

If any of these are unmet,
sf
surfaces an auth error or a
401
/
403
/
404
; surface the raw error verbatim and stop — do not fabricate state.
  1. sf
    CLI authenticated
    to the target org (
    sf org display -o <alias>
    shows Connected). All calls use
    --target-org <alias>
    ; never extract the access token by hand.
  2. API v67.0+ — pinned in the URL path; do not hand-edit below the minimum.
  3. ITSM features + templates provisioned — resolved template must be present. If
    agent-templates
    returns nothing or the routes 404, run
    service-itsm-agentic-setup-agentforce-studio-validate
    (agent path
    employee
    ).
  4. node
    ≥ 18
    on PATH.

若以下任一条件未满足,
sf
会显示认证错误或返回
401
/
403
/
404
直接显示原始错误并停止操作——请勿虚构状态
  1. sf
    CLI已认证
    到目标组织(
    sf org display -o <alias>
    显示已连接)。所有调用均使用
    --target-org <alias>
    参数;请勿手动提取访问令牌。
  2. API版本v67.0+——在URL路径中固定指定;请勿手动修改为低于该版本。
  3. 已配置ITSM功能和模板——确定的模板必须存在。若
    agent-templates
    接口返回空或路由返回404,请运行
    service-itsm-agentic-setup-agentforce-studio-validate
    流程(员工路径)。
  4. PATH中存在
    node
    ≥ 18
    版本。

Operations at a glance

操作概览

ConcernCommandNotes
Studio access (precondition read)
sf api request rest "/services/data/v67.0/agentforce-studio/access/Agents" --method GET -o <alias>
hasAccess=false
⇒ prereq hand-off
List agent templates + Agent Script (read)
sf api request rest "/services/data/v67.0/connect/service-itsm/agent-templates?agentType=AgentforceEmployeeAgent" --method GET -o <alias>
agentType=AgentforceEmployeeAgent
required; confirms resolved
<masterLabel>
template + non-empty
agentScript
Enumerate existing agent + latest version status (read)
sf data query -q "SELECT Id,DeveloperName,MasterLabel,(SELECT Id,Status FROM BotVersions ORDER BY VersionNumber DESC LIMIT 1) FROM BotDefinition WHERE Id='<botDefinitionId>' OR DeveloperName='<developerName>'" -o <alias> --json
Keyed PRIMARILY on the template's
botDefinitionId
(Phase-1 row); the
OR DeveloperName=
clause is both the null-
botDefinitionId
fallback AND the guard for a dangling Id link (deleted target). Classified by
scripts/classify-agent-existence.mjs
; Active latest ⇒ ALREADY-CREATED; Inactive latest ⇒ offer reactivation
Create the NGA bundle (write)
sf api request rest "/services/data/v67.0/nextgen-authoring/bundles" --method POST --body @<body-file> -o <alias>
Body built by
scripts/build-create-body.mjs
; response
id
= the bundle version Id
Publish the bundle version (write)
sf api request rest "/services/data/v67.0/nextgen-authoring/bundle-versions/<bundleVersionId>/publish" --method POST --body '{}' -o <alias>
Returns
publishedBotId
/
publishedBotVersionId
— creates the underlying
BotDefinition
/
BotVersion
Activate the bundle version (write)
sf api request rest "/services/data/v67.0/nextgen-authoring/bundle-versions/<bundleVersionId>/activate" --method POST --body '{}' -o <alias>
Empty response on success; agent is now live and NGA-native
Activate an existing inactive version (write)
sf api request rest "/services/data/v67.0/connect/bot-versions/<latestVersionId>/activation" --method POST --body '{"status":"Active"}' -o <alias>
Reactivation path only (Phase 2b) — skips create/publish
Verify agent is live (read)
sf data query -q "SELECT ... FROM BotDefinition WHERE Id='<verifyId>'" -o <alias> --json
<verifyId>
= create path's
publishedBotId
(Phase-5) or the Phase-2 classifier's returned live matched Id (its
botDefinitionId
/
agentId
) on ALREADY-CREATED / reactivation — not the null Phase-1 template
botDefinitionId
, never the collected developerName; confirm
BotDefinition
present + latest version Active
Full command shapes and the ITSM Connect API reference live in
references/cli-invocation.md
; the reactivation-path call + idempotency verdict table live in
references/reactivation.md
; the response-body error codes and recurring gotchas live in
references/error-taxonomy.md
.
Never extract the access token. Use
sf api request rest
/
sf data query
directly — they use 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; that bypasses the CLI session and leaks a bearer token into shell context.
--json
rule.
sf data query
takes
--json
(results come back in a
.result.records[]
envelope — that's what the classifier expects).
sf api request rest
does not — omit
--json
there; its raw stdout body is already JSON.

关注点命令说明
Studio访问权限(前置条件读取)
sf api request rest "/services/data/v67.0/agentforce-studio/access/Agents" --method GET -o <alias>
hasAccess=false
⇒ 委托处理前置条件
列出Agent模板及Agent脚本(读取)
sf api request rest "/services/data/v67.0/connect/service-itsm/agent-templates?agentType=AgentforceEmployeeAgent" --method GET -o <alias>
必须指定
agentType=AgentforceEmployeeAgent
;确认已确定的
<masterLabel>
模板及非空的
agentScript
枚举现有Agent及最新版本状态(读取)
sf data query -q "SELECT Id,DeveloperName,MasterLabel,(SELECT Id,Status FROM BotVersions ORDER BY VersionNumber DESC LIMIT 1) FROM BotDefinition WHERE Id='<botDefinitionId>' OR DeveloperName='<developerName>'" -o <alias> --json
主要基于模板的
botDefinitionId
(第1阶段获取);
OR DeveloperName=
子句既是
botDefinitionId
为空时的回退方案,也是针对无效ID链接(目标已删除)的防护措施。通过
scripts/classify-agent-existence.mjs
进行分类;最新版本为Active ⇒ 已创建;最新版本为Inactive ⇒ 提议重新激活
创建NGA包(写入)
sf api request rest "/services/data/v67.0/nextgen-authoring/bundles" --method POST --body @<body-file> -o <alias>
请求体由
scripts/build-create-body.mjs
构建;响应中的
id
为包版本ID
发布包版本(写入)
sf api request rest "/services/data/v67.0/nextgen-authoring/bundle-versions/<bundleVersionId>/publish" --method POST --body '{}' -o <alias>
返回
publishedBotId
/
publishedBotVersionId
——创建底层的
BotDefinition
/
BotVersion
激活包版本(写入)
sf api request rest "/services/data/v67.0/nextgen-authoring/bundle-versions/<bundleVersionId>/activate" --method POST --body '{}' -o <alias>
成功时返回空响应;此时Agent已生效且为NGA原生Agent
激活现有未激活版本(写入)
sf api request rest "/services/data/v67.0/connect/bot-versions/<latestVersionId>/activation" --method POST --body '{"status":"Active"}' -o <alias>
仅用于重新激活流程(第2b阶段)——跳过创建/发布步骤
验证Agent是否生效(读取)
sf data query -q "SELECT ... FROM BotDefinition WHERE Id='<verifyId>'" -o <alias> --json
<verifyId>
为创建流程中的
publishedBotId
(第5阶段获取),或已创建/重新激活流程中第2阶段分类器返回的匹配ID(其
botDefinitionId
/
agentId
输出——匹配记录的实际
BotDefinition.Id
),请勿使用第1阶段模板的
botDefinitionId
(当匹配方式为
matchedBy:"developerName"
时,该ID为空,会导致验证查询
WHERE Id=''
并错误报告失败);确认
BotDefinition
存在且最新版本为Active
完整的命令格式和ITSM Connect API参考可查看
references/cli-invocation.md
;重新激活流程的调用及幂等性判定表可查看
references/reactivation.md
;响应体错误码及常见问题可查看
references/error-taxonomy.md
请勿提取访问令牌。直接使用
sf api request rest
/
sf data query
——它们会使用CLI中存储的目标组织会话。请勿
sf org display
中提取
accessToken
并手动构建HTTP请求;这会绕过CLI会话,并将Bearer令牌泄露到shell环境中。
--json
规则
sf data query
必须添加
--json
参数(结果会封装在
.result.records[]
中——这是分类器所需的格式)。
sf api request rest
无需添加该参数;其标准输出本身就是JSON格式。

Clarifying Questions

澄清问题

Collect from the user (ask only what is not already in conversation context):
FieldDefault
Target orgDefault org (
sf config get target-org
)
Template (
masterLabel
)
IT Service Employee
(broad umbrella, id
svc_emp_intelligence__ItEmployeeAssistance
). If the user hints at a specialization (password manager, certificate, onboarding, hardware request, etc.), resolve via
references/specialized-templates.md
; ambiguous ⇒
AskUserQuestion
keyed on
id
Developer nameBroad:
IT_Service_Employee_Agent
. Specialized: substring after
__
in the picked
id
, snake-cased (e.g.
PasswordManagerAssistance
Password_Manager_Assistance
)
LabelBroad:
IT Service Employee Agent
. Specialized: the picked template's
masterLabel
verbatim (e.g.
Password Manager Assistance
)
Confirm the writeREQUIRED — present resolved template + developerName + label, then require "yes" via
AskUserQuestion
The collected
<masterLabel>
,
<developerName>
,
<label>
are threaded through every call —
<masterLabel>
selects the row in
agent-templates.data[]
(which also carries the
botDefinitionId
idempotency key);
<developerName>
/
<label>
are used in the
createBundleWithVersion
body (both outer
apiName
/
label
AND the substituted internal
config.developer_name
/
config.agent_label
). The idempotency + verify reads key PRIMARILY on the template's
botDefinitionId
(or, after a fresh create, the publish response's
publishedBotId
) and fall back to the collected
<developerName>
when that is null. A hardcode/collect mismatch on the create body diverges the bundle's outer identity from the script's internal identity.
Idempotency: keyed PRIMARILY on the template's
botDefinitionId
(Phase-1
agent-templates
row — the platform's authoritative template→
BotDefinition
link) and FALLING BACK to the collected
<developerName>
. The Phase-2 read is
BotDefinition WHERE Id='<botDefinitionId>' OR DeveloperName='<developerName>'
(the
OR
half is both the null-
botDefinitionId
fallback AND the guard for a dangling Id link — one whose target
BotDefinition
was deleted — so a stale link can't slip through to create), + latest
BotVersion.Status
. Outcomes: no match on either key ⇒ create;
Active
⇒ ALREADY-CREATED (skip write);
Inactive
⇒ Phase-2b reactivation offer. Why both keys: the broad agent ships pre-provisioned as
IT_Service_Employee
≠ the guess
IT_Service_Employee_Agent
, so
botDefinitionId
catches it — but an agent this skill creates never back-fills
botDefinitionId
(the create path omits
templateName
), so its template row stays null and the
developerName
fallback is what catches a repeat run. The server does reject a duplicate
DeveloperName
at publish (unique-constraint → bundle cleanup), but only this read turns a repeat into a graceful skip instead of a
DUPLICATE_VALUE
.

向用户收集以下信息(仅询问对话上下文未包含的内容):
字段默认值
目标组织默认组织(
sf config get target-org
模板(
masterLabel
IT Service Employee
(通用模板,ID为
svc_emp_intelligence__ItEmployeeAssistance
)。若用户暗示使用专用模板(密码管理器、证书、入职、硬件请求等),则通过
references/specialized-templates.md
进行解析;若解析结果模糊 ⇒ 触发
AskUserQuestion
,以ID为键进行询问
开发者名称通用模板:
IT_Service_Employee_Agent
。专用模板:所选模板ID中
__
后的子串,转换为蛇形命名(例如
PasswordManagerAssistance
Password_Manager_Assistance
标签通用模板:
IT Service Employee Agent
。专用模板:所选模板的
masterLabel
原文(例如
Password Manager Assistance
确认写入操作必填——展示已确定的模板、开发者名称和标签,然后通过
AskUserQuestion
要求用户回复"yes"确认
收集到的
<masterLabel>
<developerName>
<label>
会贯穿所有调用——
<masterLabel>
用于选择
agent-templates.data[]
中的行(该行还包含幂等性键
botDefinitionId
);
<developerName>
/
<label>
用于
createBundleWithVersion
请求体(包括外部的
apiName
/
label
以及内部替换的
config.developer_name
/
config.agent_label
)。幂等性和验证读取主要基于模板的
botDefinitionId
(或创建后发布响应中的
publishedBotId
),当该ID为空时,回退到收集到的
<developerName>
。若创建请求体中的硬编码值与收集值不匹配,会导致包的外部标识与脚本内部标识不一致。
幂等性:主要基于模板的
botDefinitionId
(第1阶段
agent-templates
行——平台权威的模板→
BotDefinition
链接),回退到收集到的
<developerName>
。第2阶段的查询为
BotDefinition WHERE Id='<botDefinitionId>' OR DeveloperName='<developerName>'
OR
部分既是
botDefinitionId
为空时的回退方案,也是针对无效ID链接(目标
BotDefinition
已删除)的防护措施,避免陈旧链接导致重复创建),同时查询最新的
BotVersion.Status
。结果:两个键均无匹配 ⇒ 创建;版本为Active ⇒ 已创建(跳过写入);版本为Inactive ⇒ 进入第2b阶段的重新激活提议。为何使用两个键:通用Agent预配置为
IT_Service_Employee
,与推测的
IT_Service_Employee_Agent
不同,因此
botDefinitionId
可以捕获到它——但本技能创建的Agent不会回填
botDefinitionId
(创建流程省略了
templateName
),因此其模板行始终为空,此时
developerName
回退方案可以捕获重复运行。服务器会在发布时拒绝重复的
DeveloperName
(唯一约束→包清理),但只有该查询能将重复运行转换为优雅的跳过,而非
DUPLICATE_VALUE
错误。

Workflow

工作流程

Substitute
<alias>
with the collected target org and
<developerName>
/
<label>
with the collected values. Full command shapes + per-phase verdict-branch handling live in
references/workflow-detail.md
— the phase summary below names each step and its load-bearing rule; the reference file holds the exact
sf
/
node
invocations to copy.
  1. Phase 0 — Establish
    ${SCRATCH_DIR}
    .
    Before any phase writes a transient JSON file, invoke the deterministic helper (path is skill-root-qualified so it resolves regardless of the shell's CWD):
    SCRATCH_DIR="$(node "<skill_dir>/scripts/create-scratch-dir.mjs" "${outputDir:-}")"
    . The helper picks the base dir (
    ${TMPDIR}
    , else
    /tmp
    , else the harness
    ${outputDir}
    last-resort — scratch stays OUT of the scored
    ${outputDir}
    tree) and emits the created dir's absolute path on stdout. Every subsequent phase writes its transient JSON under
    ${SCRATCH_DIR}
    ; the durable
    ${outputDir}/report.md
    stays under the harness dir.
  2. Phase 1 — Preflight. Capture the Studio-access read +
    agent-templates
    read (with the required
    agentType=AgentforceEmployeeAgent
    query param), then classify via
    scripts/classify-preflight.mjs "<masterLabel>"
    — pass the resolved
    <masterLabel>
    (
    "IT Service Employee"
    for the broad path or the picked specialization's
    masterLabel
    ). The classifier also emits
    template.botDefinitionId
    from the matched row — capture it; it is the primary Phase-2 idempotency key (the collected
    <developerName>
    is the fallback key).
    Branch on
    verdict
    :
    READY
    ⇒ Phase 2;
    NOT-READY
    ⇒ prerequisite hand-off via
    AskUserQuestion
    (delegate to
    service-itsm-agentic-setup-agentforce-studio-validate
    employee path on "yes");
    ERROR
    ⇒ surface + stop;
    studio.signal="CANNOT-CONFIRM"
    (confirmed 404) does not block.
  3. Phase 2 — Idempotency (primary key
    botDefinitionId
    , fallback key
    <developerName>
    ).
    Take
    template.botDefinitionId
    from Phase 1. Present ⇒ SOQL
    BotDefinition WHERE Id='<botDefinitionId>' OR DeveloperName='<developerName>'
    (+
    BotVersions
    subquery — required, else
    needsActivation
    is permanently false; the
    OR
    clause makes a dangling Id link — deleted target — fall back to the live same-name agent instead of a false
    exists:false
    → duplicate create). Empty/null ⇒ do NOT skip to create; fall back to
    WHERE DeveloperName='<developerName>'
    (a self-created agent's template row is never back-filled, so its
    botDefinitionId
    stays null even though the agent exists). Either way classify via
    scripts/classify-agent-existence.mjs ${SCRATCH_DIR}/bot-existing.json "<botDefinitionId-or-empty>" "<developerName>"
    . Branch:
    exists:false
    ⇒ Phase 3 (create);
    exists:true
    +
    needsActivation:false
    ALREADY-CREATED (skip to Phase 7);
    exists:true
    +
    needsActivation:true
    ⇒ Phase 2b. Non-zero exit ⇒ surface CLI error; never assume absent. Why both keys:
    botDefinitionId
    catches the pre-provisioned
    IT_Service_Employee
    (≠ the guess
    IT_Service_Employee_Agent
    ); the
    developerName
    fallback catches self-created repeats — a miss on both re-creates and hits
    DUPLICATE_VALUE
    .
  4. Phase 2b — Reactivation offer.
    AskUserQuestion
    : "Employee agent
    <developerName>
    exists but latest version is Inactive. Activate it?"
    . On Yes:
    POST /connect/bot-versions/<latestVersionId>/activation
    with
    {"status":"Active"}
    — skips Phases 3–6, straight to Phase 7. Aggregate verdict is ACTIVATED, not CREATED. On No: stop, no writes.
  5. Phase 3 — Confirm-to-Write (REQUIRED, create path only). If
    ${outputDir}
    was provided, first render the checkpoint file via
    render-report.mjs
    with
    verdict:"PENDING CONFIRMATION"
    (skip for interactive runs). THEN raise the
    AskUserQuestion
    gate presenting developerName + label + "NGA-native from the Employee template's Agent Script". Proceed only on explicit "yes"; on "no" (including "hold off on activation" / "not yet" / any decline of the atomic chain), re-render with
    verdict:"DECLINED"
    and a one-line
    reason
    .
  6. Phase 4 — Create.
    scripts/build-create-body.mjs ${SCRATCH_DIR}/agent-templates.json "<masterLabel>" "<developerName>" "<label>" ${SCRATCH_DIR}/create-bundle-body.json
    (helper re-reads Phase-1 templates JSON, HTML-decodes the matched
    agentScript
    , substitutes internal
    config.developer_name
    /
    config.agent_label
    , writes body to file — pass the same
    <masterLabel>
    used in Phase 1), then
    POST /nextgen-authoring/bundles --body @${SCRATCH_DIR}/create-bundle-body.json
    . Capture response
    id
    — that is the
    bundleVersionId
    for Phases 5–6, not
    bundleId
    .
    403 FUNCTIONALITY_NOT_ENABLED
    /
    404
    ⇒ trigger the Phase-1 hand-off; build-script exit 3 ⇒ surface stderr.
  7. Phase 5 — Publish.
    POST /nextgen-authoring/bundle-versions/<bundleVersionId>/publish --body '{}'
    (empty body required). Success:
    { lastPublishedOn, publishedBotId, publishedBotVersionId }
    — this call creates the underlying
    BotDefinition
    /
    BotVersion
    . Any error ⇒ surface verbatim; never activate an unpublished version.
  8. Phase 6 — Activate.
    POST /nextgen-authoring/bundle-versions/<bundleVersionId>/activate --body '{}'
    . Success returns an empty body — check exit code, do not parse a payload.
  9. Phase 7 — Verify. SOQL
    BotDefinition WHERE Id='<id>'
    (+
    BotVersions
    subquery) and classify —
    <id>
    is the create path's
    publishedBotId
    (captured from Phase 5) or, on the ALREADY-CREATED / reactivation path, the live matched Id the Phase-2 classifier returned (its
    botDefinitionId
    /
    agentId
    output — the actual
    BotDefinition.Id
    of the matched record), not the Phase-1 template
    botDefinitionId
    (which is null on a
    matchedBy:"developerName"
    fallback hit → the verify would run
    WHERE Id=''
    and falsely report failure after a successful skip/activation). Confirm
    exists:true, count:1, latestVersionStatus:"Active"
    . Any discrepancy ⇒ report verbatim, do not fabricate success.
  10. Phase 8 — Aggregate verdict. Emit CREATED / ALREADY-CREATED / ACTIVATED / FAILED (ACTIVATED on the Phase-2b path) +
    BotDefinition
    Id / bundle
    id
    by re-invoking
    render-report.mjs
    — the single source of report text. If
    ${outputDir}
    was provided, overwrite
    ${outputDir}/report.md
    ; otherwise emit stdout as the turn-side report.

<alias>
替换为收集到的目标组织,
<developerName>
/
<label>
替换为收集到的值。完整的命令格式及各阶段判定分支处理可查看
references/workflow-detail.md
——以下阶段摘要列出了每个步骤及其核心规则;参考文件包含可直接复制的精确
sf
/
node
调用命令。
  1. 第0阶段——创建
    ${SCRATCH_DIR}
    。在任何阶段写入临时JSON文件前,调用确定性辅助脚本(路径为技能根目录相对路径,确保无论shell的当前工作目录如何都能解析):
    SCRATCH_DIR="$(node "<skill_dir>/scripts/create-scratch-dir.mjs" "${outputDir:-}")"
    。该辅助脚本会选择基础目录(优先
    ${TMPDIR}
    ,其次
    /tmp
    ,最后是测试工具的
    ${outputDir}
    作为备选——临时目录不会包含在计分的
    ${outputDir}
    目录树中),并在标准输出中输出创建的目录绝对路径。后续所有阶段的临时JSON文件均写入
    ${SCRATCH_DIR}
    ;持久化的
    ${outputDir}/report.md
    保留在测试工具目录中。
  2. 第1阶段——预检。获取Studio访问权限读取结果 +
    agent-templates
    读取结果(必须包含
    agentType=AgentforceEmployeeAgent
    查询参数),然后通过
    scripts/classify-preflight.mjs "<masterLabel>"
    进行分类——传入已确定的
    <masterLabel>
    (通用流程为
    "IT Service Employee"
    ,专用流程为所选模板的
    masterLabel
    )。分类器还会输出匹配行的
    template.botDefinitionId
    ——请捕获该值;它是第2阶段的主要幂等性键(收集到的
    <developerName>
    为回退键)
    。根据
    verdict
    分支:
    READY
    ⇒ 进入第2阶段;
    NOT-READY
    ⇒ 通过
    AskUserQuestion
    提议委托处理前置条件(用户回复"yes"则委托给
    service-itsm-agentic-setup-agentforce-studio-validate
    员工路径);
    ERROR
    ⇒ 显示错误并停止;
    studio.signal="CANNOT-CONFIRM"
    (已确认404)不会阻止流程。
  3. 第2阶段——幂等性检查(主键为
    botDefinitionId
    ,回退键为
    <developerName>
    。使用第1阶段获取的
    template.botDefinitionId
    该值存在 ⇒ 执行SOQL查询
    BotDefinition WHERE Id='<botDefinitionId>' OR DeveloperName='<developerName>'
    (必须包含
    BotVersions
    子查询,否则
    needsActivation
    始终为false;
    OR
    子句使无效ID链接(目标已删除)回退到同名的现有Agent,而非错误地判定
    exists:false
    →重复创建)。该值为空/不存在 ⇒ 请勿直接跳转到创建流程;回退到
    WHERE DeveloperName='<developerName>'
    查询(本技能创建的Agent的模板行永远不会回填,因此即使Agent存在,其
    botDefinitionId
    仍为空)。无论哪种情况,均通过
    scripts/classify-agent-existence.mjs ${SCRATCH_DIR}/bot-existing.json "<botDefinitionId-or-empty>" "<developerName>"
    进行分类。分支:
    exists:false
    ⇒ 进入第3阶段(创建);
    exists:true
    +
    needsActivation:false
    已创建(跳转到第7阶段);
    exists:true
    +
    needsActivation:true
    ⇒ 进入第2b阶段。若脚本非零退出 ⇒ 显示CLI错误;请勿假设Agent不存在。为何使用两个键
    botDefinitionId
    可以捕获预配置的
    IT_Service_Employee
    (与推测的
    IT_Service_Employee_Agent
    不同);
    developerName
    回退方案可以捕获本技能创建的重复Agent——若两个键均未匹配,则会重新创建并触发
    DUPLICATE_VALUE
    错误。
  4. 第2b阶段——重新激活提议。触发
    AskUserQuestion
    "员工Agent
    <developerName>
    已存在,但最新版本为未激活状态。是否激活它?"
    。用户回复:执行
    POST /connect/bot-versions/<latestVersionId>/activation
    请求,请求体为
    {"status":"Active"}
    ——跳过第3-6阶段,直接进入第7阶段。最终判定为已激活,而非已创建。用户回复:停止操作,不执行任何写入。
  5. 第3阶段——确认写入(必填,仅创建流程)。若提供了
    ${outputDir}
    ,首先通过
    render-report.mjs
    渲染检查点文件,
    verdict
    设为
    "PENDING CONFIRMATION"
    (交互式运行可跳过)。然后触发
    AskUserQuestion
    ,展示开发者名称、标签以及"基于员工模板的Agent脚本创建NGA原生Agent"的信息。仅当用户明确回复"yes"时才继续;若用户回复"no"(包括"暂不激活"/"还没准备好"/任何拒绝原子流程的回复),则重新渲染报告,
    verdict
    设为
    "DECLINED"
    并添加一行原因说明。
  6. 第4阶段——创建。执行
    scripts/build-create-body.mjs ${SCRATCH_DIR}/agent-templates.json "<masterLabel>" "<developerName>" "<label>" ${SCRATCH_DIR}/create-bundle-body.json
    (辅助脚本会重新读取第1阶段的模板JSON,对匹配的
    agentScript
    进行HTML解码,替换内部的
    config.developer_name
    /
    config.agent_label
    ,并将请求体写入文件——传入与第1阶段相同的
    <masterLabel>
    ),然后执行
    POST /nextgen-authoring/bundles --body @${SCRATCH_DIR}/create-bundle-body.json
    请求。捕获响应中的
    id
    ——该值为第5-6阶段使用的
    bundleVersionId
    ,而非
    bundleId
    。若返回
    403 FUNCTIONALITY_NOT_ENABLED
    /
    404
    ⇒ 触发第1阶段的委托处理;若构建脚本退出码为3 ⇒ 显示标准错误输出。
  7. 第5阶段——发布。执行
    POST /nextgen-authoring/bundle-versions/<bundleVersionId>/publish --body '{}'
    请求(必须传入空请求体)。成功时返回:
    { lastPublishedOn, publishedBotId, publishedBotVersionId }
    ——该调用会创建底层的
    BotDefinition
    /
    BotVersion
    。若出现任何错误 ⇒ 直接显示原始错误;请勿激活未发布的版本。
  8. 第6阶段——激活。执行
    POST /nextgen-authoring/bundle-versions/<bundleVersionId>/activate --body '{}'
    请求。成功时返回空响应——请检查退出码,无需解析响应体。
  9. 第7阶段——验证。执行SOQL查询
    BotDefinition WHERE Id='<id>'
    (包含
    BotVersions
    子查询)并进行分类——
    <id>
    为创建流程中的
    publishedBotId
    (第5阶段捕获),或已创建/重新激活流程中第2阶段分类器返回的匹配ID(其
    botDefinitionId
    /
    agentId
    输出——匹配记录的实际
    BotDefinition.Id
    ),请勿使用第1阶段模板的
    botDefinitionId
    (当匹配方式为
    matchedBy:"developerName"
    时,该ID为空,会导致验证查询
    WHERE Id=''
    并错误报告成功跳过/激活后的失败)。确认
    exists:true, count:1, latestVersionStatus:"Active"
    。若出现任何差异 ⇒ 直接报告原始信息,请勿虚构成功状态。
  10. 第8阶段——汇总判定。通过重新调用
    render-report.mjs
    输出CREATED / ALREADY-CREATED / ACTIVATED / FAILED(第2b阶段流程输出ACTIVATED) +
    BotDefinition
    ID / 包
    id
    ——该脚本是报告文本的唯一来源。若提供了
    ${outputDir}
    ,则覆盖
    ${outputDir}/report.md
    ;否则在标准输出中显示报告内容。

Rules / Constraints

规则/约束

ConstraintRationale
All calls go through
sf api request rest
/
sf data query
; never extract the access token
Leaks a bearer token into shell context; the CLI's stored session is the correct surface
Idempotency + verify reads key PRIMARILY on the template's
botDefinitionId
(Phase-1 row) / the publish
publishedBotId
, falling back to the collected
<developerName>
; that same
<developerName>
/
<label>
also thread through the create body (outer
apiName
/
label
AND the substituted
config.developer_name
/
config.agent_label
)
botDefinitionId
catches the pre-provisioned
IT_Service_Employee
(≠ the guessed
IT_Service_Employee_Agent
, so a name-only read would false-negative →
DUPLICATE_VALUE
); but self-created agents never back-fill it, so the
<developerName>
fallback catches those. A create-body hardcode/collect mismatch diverges the bundle's outer identity from the script's internal identity
Preflight, idempotency, bundle-body construction, and report rendering all live in
scripts/*.mjs
, not prose (A9)
JSON parsing +
masterLabel
matching +
hasAccess
reads + verdict emission are deterministic; the ~70KB Agent Script and free-text apostrophes cannot be safely interpolated into a shell string —
JSON.stringify
in the helper escapes them
Three-call sequence:
createBundleWithVersion
publish
activate
, in that order, on the SAME captured
bundleVersionId
(response
id
, not
bundleId
)
Platform enforces DRAFT → published → active; response-body / empty-body /
--json
/
agentType
/ HTML-decode gotchas live in
references/error-taxonomy.md
Resolve
<masterLabel>
BEFORE Phase 1; filter
data[]
to
svc_emp_intelligence__
only; disambiguate ambiguous keywords via
AskUserQuestion
keyed on
id
Label-similar pairs exist; other namespaces belong to other flows (
svc_itsm_intelligence__*
→ Fulfiller skill)
Enumerate
BotDefinition
with the
BotVersions
subquery
; skip create when Active; offer Phase-2b reactivation when Inactive — never silent skip, never duplicate create
Subquery is what distinguishes Active/Inactive; the server rejects a duplicate
DeveloperName
at publish (unique-constraint → bundle cleanup) but not the pre-provisioned broad agent, so this read is what turns a repeat into a graceful skip instead of a hard error
REQUIRED confirm-to-write checkpoint before create sequence or reactivation callBoth change live org state — explicit user approval required
On
hasAccess=false
/
403 FUNCTIONALITY_NOT_ENABLED
, offer the readiness hand-off — never enable features here; never call legacy
/connect/service-itsm/createAgent
Enablement is a Setup-UI/admin action;
createAgent
produces a Setup-page bot with an external-link icon (wrong kind of agent for this skill)
Report exact CLI response text on any errorEnables support to diagnose failures

约束理由
所有调用均通过
sf api request rest
/
sf data query
完成;请勿提取访问令牌
避免将Bearer令牌泄露到shell环境中;CLI存储的会话是正确的操作入口
幂等性和验证读取主要基于模板的
botDefinitionId
(第1阶段行)/发布时的
publishedBotId
,回退到收集到的
<developerName>
;同一
<developerName>
/
<label>
也会贯穿创建请求体(外部的
apiName
/
label
以及内部替换的
config.developer_name
/
config.agent_label
botDefinitionId
可以捕获预配置的
IT_Service_Employee
(与推测的
IT_Service_Employee_Agent
不同,仅基于名称的查询会误判为不存在→触发
DUPLICATE_VALUE
错误);但本技能创建的Agent不会回填该ID,因此
<developerName>
回退方案可以捕获这些Agent。若创建请求体中的硬编码值与收集值不匹配,会导致包的外部标识与脚本内部标识不一致
预检、幂等性检查、包请求体构建和报告渲染均通过
scripts/*.mjs
完成,而非硬编码文本(规则A9)
JSON解析 +
masterLabel
匹配 +
hasAccess
读取 + 判定输出均为确定性操作;约70KB的Agent脚本和自由文本引号无法安全插入到shell字符串中——辅助脚本中的
JSON.stringify
会对其进行转义
三步调用流程:
createBundleWithVersion
publish
activate
,顺序不可变,且使用同一个捕获的
bundleVersionId
(响应中的
id
,而非
bundleId
平台要求必须遵循草稿→已发布→已激活的流程;响应体/空响应/
--json
/
agentType
/HTML解码等常见问题可查看
references/error-taxonomy.md
在第1阶段前确定
<masterLabel>
;将
data[]
过滤为仅包含
svc_emp_intelligence__
命名空间的模板;通过
AskUserQuestion
以ID为键对模糊关键词进行消歧
存在标签相似的模板对;其他命名空间的模板属于其他流程(
svc_itsm_intelligence__*
→处理者技能)
枚举
BotDefinition
必须包含
BotVersions
子查询
;当版本为Active时跳过创建;当版本为Inactive时进入第2b阶段的重新激活提议——请勿静默跳过,请勿重复创建
子查询是区分Active/Inactive的关键;服务器会在发布时拒绝重复的
DeveloperName
(唯一约束→包清理),但不会拒绝预配置的通用Agent,因此该查询可以将重复运行转换为优雅的跳过,而非硬错误
必填的写入确认检查点,位于创建流程或重新激活调用之前两种操作都会修改组织的实时状态——需要用户明确批准
hasAccess=false
/ 返回
403 FUNCTIONALITY_NOT_ENABLED
时,提议委托处理前置条件——请勿在此启用功能;请勿调用旧版
/connect/service-itsm/createAgent
接口
功能启用属于Setup-UI/管理员操作;
createAgent
接口会创建带有外部链接图标的Setup页面Agent(不符合本技能的Agent类型要求)
任何错误均报告精确的CLI响应文本便于支持人员诊断故障

Verification Checklist

验证 checklist

  • Resolved
    <masterLabel>
    before Phase 1 (broad default or specialization from
    references/specialized-templates.md
    ,
    data[]
    filtered to
    svc_emp_intelligence__
    , disambiguated on
    id
    ).
  • Preflight classified by
    classify-preflight.mjs
    (PASS or documented CANNOT-CONFIRM); hand-off offered on FAIL; raw error surfaced on ERROR.
  • Idempotency keyed on the template's
    botDefinitionId
    (Phase-1 row) with the collected developerName as fallback;
    BotDefinition WHERE Id='<botDefinitionId>' OR DeveloperName='<developerName>'
    (the
    OR
    covers both a null and a dangling
    botDefinitionId
    ) + latest
    BotVersion.Status
    (subquery present) read + classified before any write.
  • If
    needsActivation:true
    , Phase-2b reactivation offer presented — no silent skip, no duplicate create.
  • Explicit user confirmation at Phase 3 (create) or Phase 2b (reactivation) before any write.
  • Bundle body built by
    build-create-body.mjs
    , POSTed via
    --body @<file>
    with the collected
    developerName
    /
    label
    ; or write correctly skipped.
  • Same
    bundleVersionId
    (response
    id
    ) used for publish + activate; reactivation used
    POST /connect/bot-versions/<id>/activation
    ; legacy
    createAgent
    never called.
  • Phase-7 verify confirmed
    BotDefinition
    present + latest version Active.
  • Access token never extracted; final verdict +
    BotDefinition
    /bundle Id reported.

  • 在第1阶段前已确定
    <masterLabel>
    (通用默认模板或来自
    references/specialized-templates.md
    的专用模板,
    data[]
    已过滤为
    svc_emp_intelligence__
    命名空间,已基于ID进行消歧)。
  • 预检已通过
    classify-preflight.mjs
    分类(通过或记录为CANNOT-CONFIRM);失败时提议委托处理;错误时显示原始错误。
  • 幂等性检查基于模板的
    botDefinitionId
    (第1阶段行),收集到的开发者名称为回退键;已执行
    BotDefinition WHERE Id='<botDefinitionId>' OR DeveloperName='<developerName>'
    查询(
    OR
    覆盖了
    botDefinitionId
    为空和无效的情况) + 最新
    BotVersion.Status
    (包含子查询)读取并分类,然后才执行任何写入操作。
  • needsActivation:true
    ,已展示第2b阶段的重新激活提议——未静默跳过,未重复创建。
  • 在创建流程的第3阶段或重新激活流程的第2b阶段,已获得用户明确确认,然后才执行任何写入操作。
  • 包请求体由
    build-create-body.mjs
    构建,通过
    --body @<file>
    传入收集到的
    developerName
    /
    label
    ;或已正确跳过写入操作。
  • 发布和激活使用同一个
    bundleVersionId
    (响应中的
    id
    );重新激活使用
    POST /connect/bot-versions/<id>/activation
    接口;未调用旧版
    createAgent
    接口。
  • 第7阶段的验证已确认
    BotDefinition
    存在且最新版本为Active。
  • 未提取访问令牌;已报告最终判定 +
    BotDefinition
    /包ID。

Output Format

输出格式

The report layout is generated deterministically by
scripts/render-report.mjs
— the single source of report text for both the chat turn and the harness's
${outputDir}/report.md
. Never hand-compose the layout in prose (A9); always shell out to the helper. Full rendered shape, report-state JSON schema, and checkpoint-write rules live in
references/report-format.md
.
Terminal verdicts:
CREATED | ALREADY-CREATED | ACTIVATED | PENDING CONFIRMATION | DECLINED | FAILED
. When
${outputDir}
is set, write at Phase 2, Phase 6 (or Phase 2b), and Phase 8 — each write overwrites the same file. Skip these writes in interactive/chat surfaces.

报告布局由
scripts/render-report.mjs
确定性生成——该脚本是聊天对话和测试工具
${outputDir}/report.md
的报告文本唯一来源。请勿手动编写报告布局(规则A9);始终通过shell调用辅助脚本。完整的渲染格式、报告状态JSON schema和检查点写入规则可查看
references/report-format.md
最终判定:
CREATED | ALREADY-CREATED | ACTIVATED | PENDING CONFIRMATION | DECLINED | FAILED
。当设置
${outputDir}
时,在第2阶段、第6阶段(或第2b阶段)和第8阶段写入报告——每次写入都会覆盖同一文件。交互式/聊天场景可跳过这些写入操作。

Reference File Index

参考文件索引

  • references/specialized-templates.md
    — catalog + namespace filter +
    id
    -based disambiguation (before Phase 1 on any specialization).
  • references/workflow-detail.md
    — exact
    sf
    /
    node
    commands + full verdict-branch narrative per phase.
  • references/cli-invocation.md
    — command shapes, never-extract-token rule, ITSM Connect API reference, helper-script contracts.
  • references/reactivation.md
    — Phase-2b activation call + full idempotency verdict table.
  • references/report-format.md
    — rendered shape, phase-state JSON schema, three-checkpoint write policy.
  • references/error-taxonomy.md
    — response-body error codes + recurring foot-guns (any non-2xx / empty body / script non-zero exit).
  • references/specialized-templates.md
    ——模板目录 + 命名空间过滤规则 + 基于ID的消歧规则(适用于任何专用模板的第1阶段前)。
  • references/workflow-detail.md
    ——精确的
    sf
    /
    node
    命令 + 各阶段完整的判定分支说明。
  • references/cli-invocation.md
    ——命令格式、禁止提取令牌规则、ITSM Connect API参考、辅助脚本契约。
  • references/reactivation.md
    ——第2b阶段的激活调用 + 完整的幂等性判定表。
  • references/report-format.md
    ——渲染格式、阶段状态JSON schema、三检查点写入策略。
  • references/error-taxonomy.md
    ——响应体错误码 + 常见陷阱(任何非2xx响应/空响应/脚本非零退出)。