agentforce-architecture-analyze

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

agentforce-architecture-analyze — declared architecture snapshot

agentforce-architecture-analyze — 声明式架构快照

Design-time metadata tree for one Agentforce agent: planner → topics → actions → flows → Apex → prompts → NGA plugins. Reads declared metadata only —
BotDefinition
,
GenAiPlanner*
,
GenAiPlugin*
,
GenAiFunction*
,
Flow
,
ApexClass
,
GenAiPromptTemplate
. Does not read runtime audit rows.
Runtime budget: 30–45s typical, ≤60s hard cap on reference fixtures. Sequential baseline would be 90–220s; parallel Tooling SOQL fan-out delivers a 3–5× speedup. Large bots with many flows scale approximately linearly — each flow metadata retrieve is one round-trip.
Runs inline — no subagent. Every phase is deterministic file processing.
单个Agentforce代理的设计时元数据树:规划器 → 主题 → 动作 → 流程 → Apex → 提示 → NGA插件。仅读取声明式元数据——
BotDefinition
GenAiPlanner*
GenAiPlugin*
GenAiFunction*
Flow
ApexClass
GenAiPromptTemplate
读取运行时审计记录。
运行时预算: 典型场景30–45秒,参考用例硬上限≤60秒。串行基线耗时为90–220秒;并行Tooling SOQL扇出可实现3–5倍的速度提升。包含大量流程的大型代理大致呈线性扩展——每个流程元数据检索对应一次往返请求。
内联运行——无需子代理。每个阶段均为确定性文件处理。

If the user hasn't given enough to proceed

若用户提供的信息不足以继续执行

When invoked with no
agent_api_name
AND no org alias, print the following block verbatim — do not paraphrase, do not pre-run any script. Trigger condition:
$ARGUMENTS
is empty OR names no agent (no
--agent
flag and no known agent API name in the prose) OR names no org (no
--org
flag and no known alias).
Which agent should I document, and in which org?
I need:
  • Agent API name — the
    DeveloperName
    of the
    BotDefinition
    (e.g.
    MyAgent
    ,
    MySalesAgent
    ). Not the label.
  • Org alias — for
    sf
    CLI auth (the alias you configured with
    sf org login
    )
Optional:
  • Version — an
    agent_version_api_name
    like
    v5
    . If omitted, I'll resolve the active
    BotVersion
    .
  • --force
    — ignore cached tree; re-fetch everything.
  • --reprobe
    — re-run the 7-day channel-probe cache (only needed after a Salesforce release).
I'll run the metadata pipeline inline. Artifacts land under
~/.vibe/data/agentforce-architecture-analyze/<org_id15>/<agent_api_name>__<agent_version>/
(overridable with
--data-dir
).
当调用时未提供
agent_api_name
且未提供组织别名时,请逐字打印以下内容——请勿意译,请勿预先运行任何脚本。触发条件:
$ARGUMENTS
为空,或未指定代理(无
--agent
标识且文本中无已知代理API名称),或未指定组织(无
--org
标识且无已知别名)。
我应该为哪个代理生成文档,以及在哪个组织中执行?
我需要:
  • 代理API名称 ——
    BotDefinition
    DeveloperName
    (例如
    MyAgent
    MySalesAgent
    ),请勿使用标签名。
  • 组织别名 —— 用于
    sf
    CLI认证(即您通过
    sf org login
    配置的别名)
可选参数:
  • 版本 —— 类似
    v5
    agent_version_api_name
    。若省略,我将解析当前活跃的
    BotVersion
  • --force
    —— 忽略缓存树;重新获取所有数据。
  • --reprobe
    —— 重新运行7天周期的通道探测缓存(仅在Salesforce版本更新后需要)。
我将内联运行元数据管道。生成的产物将存储在
~/.vibe/data/agentforce-architecture-analyze/<org_id15>/<agent_api_name>__<agent_version>/
目录下(可通过
--data-dir
参数覆盖)。

Pipeline invocation

管道调用

When the user has supplied
--org <alias>
+
--agent <api_name>
(plus any optional flags), run this block. One
python3
invocation drives the full pipeline.
main.py
writes
.emit_ctx.json
;
emit_result.py
reads it and prints the final
=== RESULT ===
block last to stdout.
bash
set -euo pipefail
当用户提供
--org <alias>
+
--agent <api_name>
(以及任意可选标识)时,执行以下代码块。一次
python3
调用即可驱动整个管道。
main.py
会写入
.emit_ctx.json
emit_result.py
读取该文件并在最后向标准输出打印最终的
=== RESULT ===
块。
bash
set -euo pipefail

zsh arrays are 1-indexed by default; bash arrays are 0-indexed.

zsh数组默认是1索引;bash数组是0索引。

This block uses 0-indexed semantics throughout (_args[$i] starting at i=0),

本代码块全程使用0索引语义(_args[$i]从i=0开始),

so under zsh +
set -u
the very first read of
_args[0]
would trip

因此在zsh +
set -u
环境下,首次读取
_args[0]
会触发

parameter not set
. KSH_ARRAYS makes zsh treat arrays as 0-indexed,

parameter not set
错误。KSH_ARRAYS可让zsh将数组视为0索引,

matching the bash shebang's expectation. No-op under bash.

与bash脚本的预期一致。在bash环境下无影响。

[ -n "${ZSH_VERSION:-}" ] && setopt KSH_ARRAYS
SKILL_ROOT="${SKILL_ROOT:-${PLUGIN_ROOT:-$HOME/.vibe/skills}/agentforce-architecture-analyze}"
[ -n "${ZSH_VERSION:-}" ] && setopt KSH_ARRAYS
SKILL_ROOT="${SKILL_ROOT:-${PLUGIN_ROOT:-$HOME/.vibe/skills}/agentforce-architecture-analyze}"

Argument parser. Accepts both
--org foo
and
--org=foo
.

参数解析器。支持
--org foo
--org=foo
两种格式。

$ARGUMENTS
is the raw user input Claude Code substitutes.

$ARGUMENTS
是Claude Code替换后的原始用户输入。

ARG_ORG="" ARG_AGENT="" ARG_VERSION="" ARG_FORCE="" ARG_REPROBE="" ARG_PARALLELISM="" ARG_MAX_MERMAID=""
ARG_ORG="" ARG_AGENT="" ARG_VERSION="" ARG_FORCE="" ARG_REPROBE="" ARG_PARALLELISM="" ARG_MAX_MERMAID=""

shellcheck disable=SC2206

shellcheck disable=SC2206

_args=($ARGUMENTS) i=0 while [ $i -lt ${#_args[@]} ]; do tok="${_args[$i]}" case "$tok" in --org=) ARG_ORG="${tok#--org=}" ;; --org) i=$((i+1)); ARG_ORG="${_args[$i]:-}" ;; --agent=) ARG_AGENT="${tok#--agent=}" ;; --agent) i=$((i+1)); ARG_AGENT="${_args[$i]:-}" ;; --version=) ARG_VERSION="${tok#--version=}" ;; --version) i=$((i+1)); ARG_VERSION="${_args[$i]:-}" ;; --parallelism=) ARG_PARALLELISM="${tok#--parallelism=}" ;; --parallelism) i=$((i+1)); ARG_PARALLELISM="${_args[$i]:-}" ;; --max-mermaid-nodes=*) ARG_MAX_MERMAID="${tok#--max-mermaid-nodes=}" ;; --max-mermaid-nodes) i=$((i+1)); ARG_MAX_MERMAID="${_args[$i]:-}" ;; --force) ARG_FORCE="1" ;; --reprobe) ARG_REPROBE="1" ;; esac i=$((i+1)) done
_args=($ARGUMENTS) i=0 while [ $i -lt ${#_args[@]} ]; do tok="${_args[$i]}" case "$tok" in --org=) ARG_ORG="${tok#--org=}" ;; --org) i=$((i+1)); ARG_ORG="${_args[$i]:-}" ;; --agent=) ARG_AGENT="${tok#--agent=}" ;; --agent) i=$((i+1)); ARG_AGENT="${_args[$i]:-}" ;; --version=) ARG_VERSION="${tok#--version=}" ;; --version) i=$((i+1)); ARG_VERSION="${_args[$i]:-}" ;; --parallelism=) ARG_PARALLELISM="${tok#--parallelism=}" ;; --parallelism) i=$((i+1)); ARG_PARALLELISM="${_args[$i]:-}" ;; --max-mermaid-nodes=*) ARG_MAX_MERMAID="${tok#--max-mermaid-nodes=}" ;; --max-mermaid-nodes) i=$((i+1)); ARG_MAX_MERMAID="${_args[$i]:-}" ;; --force) ARG_FORCE="1" ;; --reprobe) ARG_REPROBE="1" ;; esac i=$((i+1)) done

Usage block if required flags missing. Agent reads stderr,

若缺少必填标识则显示使用说明。代理会读取标准错误输出,

prints verbatim, and stops — does NOT pre-run main.py.

逐字打印并停止——不会预先运行main.py。

if [ -z "$ARG_ORG" ] || [ -z "$ARG_AGENT" ]; then cat >&2 <<'USAGE'
Which agent should I document, and in which org?
I need:
  • Agent API name — the BotDefinition.DeveloperName (e.g.
    MyAgent
    )
  • Org alias — for
    sf
    CLI auth (the alias you configured with
    sf org login
    )
Optional flags:
  • --version v5
    — pin a specific BotVersion (default: Active+highest)
  • --force
    — bypass cache
  • --reprobe
    — force channel-probe refresh
  • --parallelism N
    — ThreadPoolExecutor size (default 5)
  • --max-mermaid-nodes N
    — cap Mermaid node count (default 80) USAGE exit 2 fi
if [ -z "$ARG_ORG" ] || [ -z "$ARG_AGENT" ]; then cat >&2 <<'USAGE'
Which agent should I document, and in which org?
I need:
  • Agent API name — the BotDefinition.DeveloperName (e.g.
    MyAgent
    )
  • Org alias — for
    sf
    CLI auth (the alias you configured with
    sf org login
    )
Optional flags:
  • --version v5
    — pin a specific BotVersion (default: Active+highest)
  • --force
    — bypass cache
  • --reprobe
    — force channel-probe refresh
  • --parallelism N
    — ThreadPoolExecutor size (default 5)
  • --max-mermaid-nodes N
    — cap Mermaid node count (default 80) USAGE exit 2 fi

Fresh work dir per invocation. Epoch + random suffix avoids collisions

每次调用使用全新工作目录。时间戳+随机后缀可避免同一主机上并发运行时的冲突

between concurrent runs on the same host.

WORK_DIR="/tmp/agentforce-architecture-analyze-$(date +%s)-$RANDOM" mkdir -p "$WORK_DIR"
WORK_DIR="/tmp/agentforce-architecture-analyze-$(date +%s)-$RANDOM" mkdir -p "$WORK_DIR"

Input validation at the boundary, BEFORE any python3 call.

在边界处进行输入验证,任何python3调用之前

fs_guard exits 1 and prints an INVALID_INPUT RESULT block on failure;

fs_guard验证失败时会退出并打印INVALID_INPUT结果块;

|| exit 1
is mandatory — bare calls silently continue past failures.

|| exit 1
是必须的——直接调用会在失败后静默继续。

python3 "$SKILL_ROOT/scripts/_shared/fs_guard.py" "$ARG_AGENT" agent_api_name api_name || exit 1 python3 "$SKILL_ROOT/scripts/_shared/fs_guard.py" "$ARG_ORG" org_alias not_empty || exit 1 python3 "$SKILL_ROOT/scripts/_shared/fs_guard.py" "$WORK_DIR" WORK_DIR symlink || exit 1 python3 "$SKILL_ROOT/scripts/_shared/fs_guard.py" "$WORK_DIR" WORK_DIR owned || exit 1 if [ -n "$ARG_VERSION" ]; then python3 "$SKILL_ROOT/scripts/_shared/fs_guard.py" "$ARG_VERSION" agent_version api_name || exit 1 fi
python3 "$SKILL_ROOT/scripts/_shared/fs_guard.py" "$ARG_AGENT" agent_api_name api_name || exit 1 python3 "$SKILL_ROOT/scripts/_shared/fs_guard.py" "$ARG_ORG" org_alias not_empty || exit 1 python3 "$SKILL_ROOT/scripts/_shared/fs_guard.py" "$WORK_DIR" WORK_DIR symlink || exit 1 python3 "$SKILL_ROOT/scripts/_shared/fs_guard.py" "$WORK_DIR" WORK_DIR owned || exit 1 if [ -n "$ARG_VERSION" ]; then python3 "$SKILL_ROOT/scripts/_shared/fs_guard.py" "$ARG_VERSION" agent_version api_name || exit 1 fi

Single python3 call drives all pipeline phases. main.py writes

单次python3调用驱动所有管道阶段。main.py会将

.emit_ctx.json
into $WORK_DIR — emit_result.py then renders the

.emit_ctx.json
写入$WORK_DIR——emit_result.py随后根据该上下文渲染

RESULT block from that ctx. No subprocess-per-phase.

RESULT块。无需每个阶段单独启动子进程。

_main_args=(--org-alias "$ARG_ORG" --agent "$ARG_AGENT" --work-dir "$WORK_DIR") [ -n "$ARG_VERSION" ] && _main_args+=(--version "$ARG_VERSION") [ -n "$ARG_FORCE" ] && _main_args+=(--force) [ -n "$ARG_REPROBE" ] && _main_args+=(--reprobe) [ -n "$ARG_PARALLELISM" ] && _main_args+=(--parallelism "$ARG_PARALLELISM") [ -n "$ARG_MAX_MERMAID" ] && _main_args+=(--max-mermaid-nodes "$ARG_MAX_MERMAID")
_main_args=(--org-alias "$ARG_ORG" --agent "$ARG_AGENT" --work-dir "$WORK_DIR") [ -n "$ARG_VERSION" ] && _main_args+=(--version "$ARG_VERSION") [ -n "$ARG_FORCE" ] && _main_args+=(--force) [ -n "$ARG_REPROBE" ] && _main_args+=(--reprobe) [ -n "$ARG_PARALLELISM" ] && _main_args+=(--parallelism "$ARG_PARALLELISM") [ -n "$ARG_MAX_MERMAID" ] && _main_args+=(--max-mermaid-nodes "$ARG_MAX_MERMAID")

main.py returns nonzero on terminal failures; we DON'T short-circuit —

main.py在终端失败时返回非零值;我们不会提前终止——

emit_result still publishes the failure RESULT block.
set -e
is

emit_result仍会发布失败结果块。在此单次调用期间临时禁用
set -e

temporarily relaxed around this single call.

set +e python3 "$SKILL_ROOT/scripts/main.py" "${_main_args[@]}" _rc=$? set -e
set +e python3 "$SKILL_ROOT/scripts/main.py" "${_main_args[@]}" _rc=$? set -e

Final RESULT block is emit_result.py's stdout — MUST be the last thing

最终RESULT块是emit_result.py的标准输出——必须是标准输出的最后内容。

stdout sees. emit_result exits 0 on render success; the bash harness

emit_result渲染成功时退出码为0;bash脚本会传播main.py的退出码作为代理的最终状态。

propagates main.py's rc for the agent's exit status.

WORK_DIR="$WORK_DIR" python3 "$SKILL_ROOT/tools/emit_result.py" exit "$_rc"
undefined
WORK_DIR="$WORK_DIR" python3 "$SKILL_ROOT/tools/emit_result.py" exit "$_rc"
undefined

Inputs

输入参数

InputFlagRequiredDefault
org_alias
--org
yes
agent_api_name
--agent
yes
agent_version_api_name
--version
noactive BotVersion
force_refresh
--force
nofalse (honor cache)
reprobe
--reprobe
nofalse (honor 7-day channel-probe cache)
parallelism
--parallelism
no5
max_mermaid_nodes
--max-mermaid-nodes
no80
data_dir
--data-dir
no
~/.vibe/data/agentforce-architecture-analyze
cache_dir
--cache-dir
no
~/.vibe/cache/agentforce-architecture-analyze
输入项参数标识是否必填默认值
org_alias
--org
agent_api_name
--agent
agent_version_api_name
--version
活跃的BotVersion
force_refresh
--force
false(使用缓存)
reprobe
--reprobe
false(使用7天周期的通道探测缓存)
parallelism
--parallelism
5
max_mermaid_nodes
--max-mermaid-nodes
80
data_dir
--data-dir
~/.vibe/data/agentforce-architecture-analyze
cache_dir
--cache-dir
~/.vibe/cache/agentforce-architecture-analyze

Outputs

输出产物

All artifacts under
~/.vibe/data/agentforce-architecture-analyze/<org_id15>/<agent_api_name>__<agent_version>/
(default; override with
--data-dir <path>
):
<agent>_<ver>_metadata_tree.json   primary artifact — normalized planner/topic/action/flow/apex/prompt/plugin tree
<agent>_<ver>_architecture.md      human-readable section-by-section rendering (H1 + 7 numbered sections, plus a conditional Dependency graph appendix). Mermaid diagrams are embedded inside the relevant sections (Action tree, Data flow, and Dependency graph)
所有产物默认存储在
~/.vibe/data/agentforce-architecture-analyze/<org_id15>/<agent_api_name>__<agent_version>/
目录下(可通过
--data-dir <path>
参数覆盖):
<agent>_<ver>_metadata_tree.json   核心产物——标准化的规划器/主题/动作/流程/Apex/提示/插件树
<agent>_<ver>_architecture.md      人类可读的分节渲染文档(包含H1标题+7个编号章节,以及可选的依赖关系图附录)。Mermaid图表嵌入在相关章节中(动作树、数据流、依赖关系图)

Pipeline — inline, no subagent

管道流程 — 内联运行,无需子代理

resolve_bot.py        → BotDefinition + BotVersion + planner name lookup
retrieve_planner.py   → Metadata API zip retrieve for GenAiPlannerBundle (+ NGA plugins if present)
parallel_retrieve.py  → 6 parallel Tooling SOQL channels fan out from the planner id
                          (resolved by the `planner_definition_by_agent_chain` seed query):
                          - plugins_by_planner (GenAiPluginDefinition)
                          - planner_bundle_functions (GenAiPlannerFunctionDef join)
                          - functions_by_plugins (GenAiFunctionDefinition)
                          - planner_attrs_by_parent_ids (GenAiPlannerAttrDefinition)
                          - plugin_functions_by_plugin_ids (GenAiPluginFunctionDef join)
                          - plugin_instructions_by_plugin_ids (GenAiPluginInstructionDef)
parse_bundle.py       → parse retrieved XML into normalized node shapes
parse_wave.py         → BFS expansion: flow/apex/prompt refs discovered in nodes
                          → SOQL for Flow/Apex bodies (batched by id list)
                          → Metadata retrieve ONLY for GenAiPromptTemplate (+ NGA external plugins conditionally)
finalize.py           → merge waves into metadata_tree.json
render_architecture.py → <agent>_<ver>_architecture.md + Mermaid invocation graph (capped at --max-mermaid-nodes)
Channel strategy — SOQL-first.
  • Tooling SOQL for every normalized tree node (planner, plugins, functions, plugin-functions, plugin-instructions, planner-functions, planner-attrs) — 6 parallel channels keyed on planner id, plus the
    planner_definition_by_agent_chain
    seed query that resolves the planner id from the agent chain.
  • Data API SOQL for Flow (by id) and Apex (by id or name) bodies — batched.
  • Metadata retrieve only for two cases: (a)
    GenAiPromptTemplate
    (prompt bodies aren't cleanly exposed via Tooling SOQL), and (b) NGA external plugins when the planner is Native Generative Agent shape (skipped for classic ReAct).
This is where the 3–5× speedup comes from. A naive implementation would retrieve everything via Metadata API zips sequentially; parallel Tooling SOQL covers ~80% of the tree in a single fan-out.
resolve_bot.py        → 查找BotDefinition + BotVersion + 规划器名称
retrieve_planner.py   → 通过Metadata API zip检索GenAiPlannerBundle(若存在则包含NGA插件)
parallel_retrieve.py  → 从规划器ID扩展出6个并行Tooling SOQL通道
                          (由`planner_definition_by_agent_chain`种子查询解析规划器ID):
                          - plugins_by_planner (GenAiPluginDefinition)
                          - planner_bundle_functions (GenAiPlannerFunctionDef关联查询)
                          - functions_by_plugins (GenAiFunctionDefinition)
                          - planner_attrs_by_parent_ids (GenAiPlannerAttrDefinition)
                          - plugin_functions_by_plugin_ids (GenAiPluginFunctionDef关联查询)
                          - plugin_instructions_by_plugin_ids (GenAiPluginInstructionDef)
parse_bundle.py       → 将检索到的XML解析为标准化节点格式
parse_wave.py         → BFS扩展:在节点中发现的流程/Apex/提示引用
                          → 通过SOQL批量获取Flow/Apex内容(按ID列表批量处理)
                          → 仅针对GenAiPromptTemplate(以及有条件地针对NGA外部插件)执行Metadata检索
finalize.py           → 将多轮结果合并为metadata_tree.json
render_architecture.py → 生成<agent>_<ver>_architecture.md + Mermaid调用图(节点数量上限由--max-mermaid-nodes指定)
通道策略 — 优先使用SOQL。
  • Tooling SOQL:用于所有标准化树节点(规划器、插件、函数、插件-函数、插件-指令、规划器-函数、规划器属性)——6个基于规划器ID的并行通道,加上从代理链解析规划器ID的
    planner_definition_by_agent_chain
    种子查询。
  • Data API SOQL:用于获取Flow(按ID)和Apex(按ID或名称)内容——批量处理。
  • Metadata检索:仅用于两种场景:(a)
    GenAiPromptTemplate
    (提示内容无法通过Tooling SOQL清晰获取),以及(b) 当规划器为原生生成式代理类型时的NGA外部插件(经典ReAct类型跳过)。
这正是实现3–5倍速度提升的关键。 naive实现会通过Metadata API zip串行检索所有内容;而并行Tooling SOQL可在一次扇出中覆盖约80%的树结构。

Planner shapes — classic ReAct vs NGA

规划器类型 — 经典ReAct vs NGA

The skill normalizes two planner families into a single tree shape:
Shape
GenAiPlannerDefinition.PlannerType
InvocationTarget styleNGA plugins?
Classic ReAct
ReactAiPlannerV1
/
SequentialPlannerIntentClassifier
/ etc.
DeveloperName stringsno
NGA
ConcurrentMultiAgentOrchestration
/
AnthropicCompatibleV1
/ etc.
Sometimes 15/18-char Ids (ID-prefix routed)yes (external plugins via Metadata retrieve)
The ID-prefix router in
resolve_invocation_target.py
distinguishes the two: NGA InvocationTargets that look like ids (
01p…
= ApexClass,
301…
= Flow, etc.) get resolved via id-scoped SOQL; DeveloperName targets go through name-scoped SOQL. Unknown prefixes surface as
_unresolved[]
with
reason="unknown-id-prefix:<prefix>"
— never silently dropped.
本技能将两种规划器家族标准化为单一树结构:
类型
GenAiPlannerDefinition.PlannerType
调用目标风格是否支持NGA插件
经典ReAct
ReactAiPlannerV1
/
SequentialPlannerIntentClassifier
/ 其他
DeveloperName字符串
NGA
ConcurrentMultiAgentOrchestration
/
AnthropicCompatibleV1
/ 其他
有时为15/18位ID(按ID前缀路由)是(通过Metadata检索外部插件)
resolve_invocation_target.py
中的ID前缀路由器可区分这两种类型:类似ID格式的NGA调用目标(
01p…
= ApexClass,
301…
= Flow等)会通过ID范围的SOQL解析;DeveloperName目标则通过名称范围的SOQL解析。未知前缀会显示为
_unresolved[]
并附带
reason="unknown-id-prefix:<prefix>"
——绝不会被静默丢弃。

Caching

缓存机制

  • Tree cache:
    metadata_tree.json
    is reused unless
    --force
    is passed. Cache key includes the asset-hash of every
    .soql
    /
    .yaml
    /
    .mmd
    template bundled with the skill — bump a template, the cache busts automatically.
  • Channel probe cache: 7-day TTL on the per-org
    sf sobject describe
    results that validate every field name the SOQL assets reference. A Salesforce quarterly release that renames / removes a field triggers
    status: PROBE_FAILED
    ;
    --reprobe
    forces a refresh.
  • 树缓存
    metadata_tree.json
    会被重复使用,除非传入
    --force
    参数。缓存键包含技能捆绑的所有
    .soql
    /
    .yaml
    /
    .mmd
    模板的资产哈希值——若模板更新,缓存会自动失效。
  • 通道探测缓存:每个组织的
    sf sobject describe
    结果有7天的TTL,用于验证SOQL资产引用的每个字段名称。Salesforce季度版本更新若重命名/删除字段会触发
    status: PROBE_FAILED
    --reprobe
    参数可强制刷新缓存。

Prerequisites

前置条件

ToolRequired
sf
CLI (authenticated against the target org)
yes —
sf org login web --alias <alias>
Python 3.10+yes
工具是否必填
sf
CLI(已针对目标组织完成认证)
是 — 需执行
sf org login web --alias <alias>
Python 3.10+

Reference docs to load when needed

需要时加载的参考文档

Do NOT load eagerly. Load when the user's question requires it:
  • references/soql_fields.md
    — per-sObject field reference for the 13 sObjects this skill touches (2 Data API + 11 Tooling), with
    [mandatory]
    vs
    [optional]
    tags. Load when the user asks about a specific field, or when debugging an
    INVALID_FIELD
    SOQL error.
  • references/contract.json
    — machine-readable schema for
    metadata_tree.json
    . Load when writing downstream tooling that consumes the tree.
  • references/architecture_sections.md
    — section-by-section structure of the rendered
    <agent>_<ver>_architecture.md
    .
请勿提前加载。仅当用户的问题需要时才加载:
  • references/soql_fields.md
    — 本技能涉及的13个sObject(2个Data API + 11个Tooling)的字段参考文档,带有
    [mandatory]
    [optional]
    标签。当用户询问特定字段或调试
    INVALID_FIELD
    SOQL错误时加载。
  • references/contract.json
    metadata_tree.json
    的机器可读 schema。当编写消费该树结构的下游工具时加载。
  • references/architecture_sections.md
    — 渲染后的
    <agent>_<ver>_architecture.md
    的分节结构说明。

Invariants worth knowing upfront

预先需要了解的不变规则

  • Pipeline is deterministic. Same
    (org, agent, version)
    + static org metadata → byte-identical
    <agent>_<ver>_metadata_tree.json
    and
    <agent>_<ver>_architecture.md
    . Only manifest timestamps drift across re-runs.
  • Forward-only traversal. Every discovered ref goes forward from planner → children. No backward lookups.
  • Partial results are surfaced, not silenced. Any unresolved reference lands in
    _unresolved[]
    with
    reason=...
    .
    STATUS=PARTIAL_OK
    if any channel failed;
    STATUS=OK
    only on a clean run.
  • Cycle detection is per-branch. Same flow visited along its own ancestor chain emits
    _cycle_back_to:<path>
    instead of recursing. A defensive
    MAX_BFS_DEPTH=20
    guard backs the per-branch ancestor set; real-world agents bottom out well before either limit fires. (Earlier docs claimed a hard cap of 5; that was the historical limit and was abandoned because shared utility flows like
    handleFlowFault
    tripped it on every nested tree — see
    config.MAX_BFS_DEPTH
    for the rationale.)
  • Child ordering is alphabetical by
    api_name
    (case-insensitive).
    Topics come before non-topic plannerActions at the root level. Flow-actionCall order is NOT sorted — that's the flow author's execution sequence.
  • 管道具有确定性。相同的
    (组织, 代理, 版本)
    + 静态组织元数据 → 字节完全相同的
    <agent>_<ver>_metadata_tree.json
    <agent>_<ver>_architecture.md
    。仅清单时间戳会在重新运行时变化。
  • 仅向前遍历。所有发现的引用均从规划器向子节点单向传递。无反向查找。
  • 显示部分结果而非静默丢弃。任何未解析的引用都会进入
    _unresolved[]
    并附带
    reason=...
    。若任何通道失败则返回
    STATUS=PARTIAL_OK
    ;仅当所有环节成功时才返回
    STATUS=OK
  • 按分支检测循环。若沿自身祖先链访问到同一流程,会输出
    _cycle_back_to:<path>
    而非递归处理。每个分支的祖先集合背后有一个防御性的
    MAX_BFS_DEPTH=20
    限制;实际场景中的代理远在达到任一限制前就会终止遍历。(早期文档声称硬上限为5;这是历史限制,因共享实用流程如
    handleFlowFault
    在每个嵌套树中都会触发该限制而被废弃——详见
    config.MAX_BFS_DEPTH
    的说明。)
  • 子节点按
    api_name
    字母顺序排序(不区分大小写)
    。在根层级,主题会排在非主题规划器动作之前。Flow-actionCall的顺序会被排序——这是流程作者定义的执行顺序。