investigating-agentforce-architecture
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chineseinvestigating-agentforce-architecture — declared architecture snapshot
investigating-agentforce-architecture — 已声明架构快照
Design-time metadata tree for one Agentforce agent: planner → topics → actions → flows → Apex → prompts → NGA plugins. Reads declared metadata only — , , , , , , . Does not read runtime audit rows.
BotDefinitionGenAiPlanner*GenAiPlugin*GenAiFunction*FlowApexClassGenAiPromptTemplateRuntime 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插件。仅读取已声明的元数据——、、、、、、。不读取运行时审计记录。
BotDefinitionGenAiPlanner*GenAiPlugin*GenAiFunction*FlowApexClassGenAiPromptTemplate运行时预算: 典型场景30–45秒,参考测试用例下硬上限≤60秒。顺序执行基准耗时为90–220秒;并行Tooling SOQL分支可实现3–5倍的速度提升。包含大量流程的大型代理大致呈线性扩展——每个流程元数据的获取需一次往返。
内联运行——无子代理。每个阶段都是确定性的文件处理。
If the user hasn't given enough to proceed
若用户未提供足够信息以继续执行
When invoked with no AND no org alias, print the following block verbatim — do not paraphrase, do not pre-run any script. Trigger condition: is empty OR names no agent (no flag and no known agent API name in the prose) OR names no org (no flag and no known alias).
agent_api_name$ARGUMENTS--agent--orgWhich agent should I document, and in which org?I need:
- Agent API name — the
of theDeveloperName(e.g.BotDefinition,MyAgent). Not the label.MySalesAgent- Org alias — for
CLI auth (the alias you configured withsf)sf org loginOptional:
- Version — an
likeagent_version_api_name. If omitted, I'll resolve the activev5.BotVersion — ignore cached tree; re-fetch everything.--force — re-run the 7-day channel-probe cache (only needed after a Salesforce release).--reprobeI'll run the metadata pipeline inline. Artifacts land under(overridable with~/.vibe/data/investigating-agentforce-architecture/<org_id15>/<agent_api_name>__<agent_version>/).--data-dir
当调用时未指定且未指定组织别名时,逐字打印以下内容——请勿改写,请勿预运行任何脚本。触发条件:为空,或未指定代理(无标志且文本中无已知代理API名称),或未指定组织(无标志且无已知别名)。
agent_api_name$ARGUMENTS--agent--org我需要为哪个代理、在哪个组织中生成文档?我需要:
- 代理API名称——
的BotDefinition(例如DeveloperName、MyAgent)。不是显示标签。MySalesAgent- 组织别名——用于
CLI认证(您通过sf配置的别名)sf org login可选参数:
- 版本——类似
的v5。若省略,我将解析当前活跃的agent_version_api_name。BotVersion ——忽略缓存的树结构;重新获取所有数据。--force ——重新运行7天周期的通道探测缓存(仅在Salesforce版本更新后需要)。--reprobe我将内联运行元数据管道。生成的工件将存储在目录下(可通过~/.vibe/data/investigating-agentforce-architecture/<org_id15>/<agent_api_name>__<agent_version>/参数覆盖)。--data-dir
Pipeline invocation
管道调用
When the user has supplied + (plus any optional flags), run this block. One invocation drives the full pipeline. writes ; reads it and prints the final block last to stdout.
--org <alias>--agent <api_name>python3main.py.emit_ctx.jsonemit_result.py=== RESULT ===bash
set -euo pipefail当用户提供 + (以及任何可选标志)时,运行以下代码块。一次调用即可驱动整个管道。会写入;读取该文件并将最终的块最后打印到标准输出。
--org <alias>--agent <api_name>python3main.py.emit_ctx.jsonemit_result.py=== RESULT ===bash
set -euo pipefailzsh arrays are 1-indexed by default; bash arrays are 0-indexed.
zsh arrays are 1-indexed by default; bash arrays are 0-indexed.
This block uses 0-indexed semantics throughout (_args[$i] starting at i=0),
This block uses 0-indexed semantics throughout (_args[$i] starting at i=0),
so under zsh + set -u
the very first read of _args[0]
would trip
set -u_args[0]so under zsh + set -u
the very first read of _args[0]
would trip
set -u_args[0]parameter not set
. KSH_ARRAYS makes zsh treat arrays as 0-indexed,
parameter not setparameter not set
. KSH_ARRAYS makes zsh treat arrays as 0-indexed,
parameter not setmatching the bash shebang's expectation. No-op under bash.
matching the bash shebang's expectation. No-op under bash.
[ -n "${ZSH_VERSION:-}" ] && setopt KSH_ARRAYS
SKILL_ROOT="${SKILL_ROOT:-${PLUGIN_ROOT:-$HOME/.vibe/skills}/investigating-agentforce-architecture}"
[ -n "${ZSH_VERSION:-}" ] && setopt KSH_ARRAYS
SKILL_ROOT="${SKILL_ROOT:-${PLUGIN_ROOT:-$HOME/.vibe/skills}/investigating-agentforce-architecture}"
Argument parser. Accepts both --org foo
and --org=foo
.
--org foo--org=fooArgument parser. Accepts both --org foo
and --org=foo
.
--org foo--org=foo$ARGUMENTS
is the raw user input Claude Code substitutes.
$ARGUMENTS$ARGUMENTS
is the raw user input Claude Code substitutes.
$ARGUMENTSARG_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,
Usage block if required flags missing. Agent reads stderr,
prints verbatim, and stops — does NOT pre-run main.py.
prints verbatim, and stops — does NOT pre-run 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
CLI auth (the alias you configured withsf)sf org loginOptional flags:
— pin a specific BotVersion (default: Active+highest)--version v5 — bypass cache--force — force channel-probe refresh--reprobe — ThreadPoolExecutor size (default 5)--parallelism N — cap Mermaid node count (default 80) USAGE exit 2 fi--max-mermaid-nodes N
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
CLI auth (the alias you configured withsf)sf org loginOptional flags:
— pin a specific BotVersion (default: Active+highest)--version v5 — bypass cache--force — force channel-probe refresh--reprobe — ThreadPoolExecutor size (default 5)--parallelism N — cap Mermaid node count (default 80) USAGE exit 2 fi--max-mermaid-nodes N
Fresh work dir per invocation. Epoch + random suffix avoids collisions
Fresh work dir per invocation. Epoch + random suffix avoids collisions
between concurrent runs on the same host.
between concurrent runs on the same host.
WORK_DIR="/tmp/investigating-agentforce-architecture-$(date +%s)-$RANDOM"
mkdir -p "$WORK_DIR"
WORK_DIR="/tmp/investigating-agentforce-architecture-$(date +%s)-$RANDOM"
mkdir -p "$WORK_DIR"
Input validation at the boundary, BEFORE any python3 call.
Input validation at the boundary, BEFORE any python3 call.
fs_guard exits 1 and prints an INVALID_INPUT RESULT block on failure;
fs_guard exits 1 and prints an INVALID_INPUT RESULT block on failure;
|| exit 1
is mandatory — bare calls silently continue past failures.
|| exit 1|| exit 1
is mandatory — bare calls silently continue past failures.
|| exit 1python3 "$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
Single python3 call drives all pipeline phases. main.py writes
.emit_ctx.json
into $WORK_DIR — emit_result.py then renders the
.emit_ctx.json.emit_ctx.json
into $WORK_DIR — emit_result.py then renders the
.emit_ctx.jsonRESULT block from that ctx. No subprocess-per-phase.
RESULT block from that ctx. No subprocess-per-phase.
_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 returns nonzero on terminal failures; we DON'T short-circuit —
emit_result still publishes the failure RESULT block. set -e
is
set -eemit_result still publishes the failure RESULT block. set -e
is
set -etemporarily relaxed around this single call.
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
Final RESULT block is emit_result.py's stdout — MUST be the last thing
stdout sees. emit_result exits 0 on render success; the bash harness
stdout sees. emit_result exits 0 on render success; the bash harness
propagates main.py's rc for the agent's exit status.
propagates main.py's rc for the agent's exit status.
WORK_DIR="$WORK_DIR" python3 "$SKILL_ROOT/tools/emit_result.py"
exit "$_rc"
undefinedWORK_DIR="$WORK_DIR" python3 "$SKILL_ROOT/tools/emit_result.py"
exit "$_rc"
undefinedInputs
输入参数
| Input | Flag | Required | Default |
|---|---|---|---|
| | yes | — |
| | yes | — |
| | no | active BotVersion |
| | no | false (honor cache) |
| | no | false (honor 7-day channel-probe cache) |
| | no | 5 |
| | no | 80 |
| | no | |
| | no | |
| 输入项 | 标志 | 是否必填 | 默认值 |
|---|---|---|---|
| | 是 | — |
| | 是 | — |
| | 否 | 活跃的BotVersion |
| | 否 | false(使用缓存) |
| | 否 | false(使用7天周期的通道探测缓存) |
| | 否 | 5 |
| | 否 | 80 |
| | 否 | |
| | 否 | |
Outputs
输出结果
All artifacts under (default; override with ):
~/.vibe/data/investigating-agentforce-architecture/<org_id15>/<agent_api_name>__<agent_version>/--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/investigating-agentforce-architecture/<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 seed query that resolves the planner id from the agent chain.
planner_definition_by_agent_chain - Data API SOQL for Flow (by id) and Apex (by id or name) bodies — batched.
- Metadata retrieve only for two cases: (a) (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).
GenAiPromptTemplate
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 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 → 将获取的XML解析为标准化节点格式
parse_wave.py → 广度优先搜索扩展:在节点中发现的流程/Apex/提示引用
→ 通过SOQL批量获取Flow/Apex内容
→ 仅针对GenAiPromptTemplate(以及有条件地针对NGA外部插件)执行Metadata retrieve
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 retrieve仅用于两种情况:(a) (提示内容无法通过Tooling SOQL清晰获取);(b) 当规划器为原生生成式代理(Native Generative Agent)类型时的NGA外部插件(经典ReAct类型跳过此步骤)。
GenAiPromptTemplate
这正是实现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 | | InvocationTarget style | NGA plugins? |
|---|---|---|---|
| Classic ReAct | | DeveloperName strings | no |
| NGA | | Sometimes 15/18-char Ids (ID-prefix routed) | yes (external plugins via Metadata retrieve) |
The ID-prefix router in distinguishes the two: NGA InvocationTargets that look like ids ( = ApexClass, = Flow, etc.) get resolved via id-scoped SOQL; DeveloperName targets go through name-scoped SOQL. Unknown prefixes surface as with — never silently dropped.
resolve_invocation_target.py01p…301…_unresolved[]reason="unknown-id-prefix:<prefix>"此技能将两种规划器家族标准化为单一树结构:
| 类型 | | 调用目标风格 | 是否支持NGA插件? |
|---|---|---|---|
| 经典ReAct | | DeveloperName字符串 | 否 |
| NGA | | 有时为15/18位ID(按ID前缀路由) | 是(通过Metadata retrieve获取外部插件) |
resolve_invocation_target.py01p…301…_unresolved[]reason="unknown-id-prefix:<prefix>"Caching
缓存机制
- Tree cache: is reused unless
metadata_tree.jsonis passed. Cache key includes the asset-hash of every--force/.soql/.yamltemplate bundled with the skill — bump a template, the cache busts automatically..mmd - Channel probe cache: 7-day TTL on the per-org results that validate every field name the SOQL assets reference. A Salesforce quarterly release that renames / removes a field triggers
sf sobject describe;status: PROBE_FAILEDforces a refresh.--reprobe
- 树结构缓存:会被重复使用,除非传入
metadata_tree.json参数。缓存键包含技能捆绑的所有--force/.soql/.yaml模板的资产哈希值——若模板更新,缓存将自动失效。.mmd - 通道探测缓存:每个组织的结果缓存有效期为7天,用于验证SOQL资产引用的每个字段名称。Salesforce季度版本更新若重命名/删除字段,将触发
sf sobject describe;status: PROBE_FAILED参数可强制刷新缓存。--reprobe
Prerequisites
前置条件
| Tool | Required |
|---|---|
| yes — |
| Python 3.10+ | yes |
| 工具 | 是否必填 |
|---|---|
| 是 — 需执行 |
| Python 3.10+ | 是 |
Reference docs to load when needed
必要时加载的参考文档
Do NOT load eagerly. Load when the user's question requires it:
- — per-sObject field reference for the 13 sObjects this skill touches (2 Data API + 11 Tooling), with
references/soql_fields.mdvs[mandatory]tags. Load when the user asks about a specific field, or when debugging an[optional]SOQL error.INVALID_FIELD - — machine-readable schema for
references/contract.json. Load when writing downstream tooling that consumes the tree.metadata_tree.json - — section-by-section structure of the rendered
references/architecture_sections.md.<agent>_<ver>_architecture.md
请勿提前加载。仅当用户的问题需要时加载:
- — 此技能涉及的13个sObject(2个Data API + 11个Tooling)的逐对象字段参考,带有
references/soql_fields.md和[mandatory]标签。当用户询问特定字段或调试[optional]SOQL错误时加载。INVALID_FIELD - —
references/contract.json的机器可读 schema。当编写消费该树结构的下游工具时加载。metadata_tree.json - — 渲染后的
references/architecture_sections.md的分节结构说明。<agent>_<ver>_architecture.md
Invariants worth knowing upfront
需提前了解的不变规则
- Pipeline is deterministic. Same + static org metadata → byte-identical
(org, agent, version)and<agent>_<ver>_metadata_tree.json. Only manifest timestamps drift across re-runs.<agent>_<ver>_architecture.md - 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 with
_unresolved[].reason=...if any channel failed;STATUS=PARTIAL_OKonly on a clean run.STATUS=OK - Cycle detection is per-branch. Same flow visited along its own ancestor chain emits instead of recursing. A defensive
_cycle_back_to:<path>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 likeMAX_BFS_DEPTH=20tripped it on every nested tree — seehandleFlowFaultfor the rationale.)config.MAX_BFS_DEPTH - Child ordering is alphabetical by (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.
api_name
- 管道具有确定性。相同的+ 静态组织元数据 → 字节完全相同的
(组织, 代理, 版本)和<agent>_<ver>_metadata_tree.json。仅清单时间戳会在重新运行时变化。<agent>_<ver>_architecture.md - 仅向前遍历。所有发现的引用均从规划器向子节点向前遍历。无反向查找。
- 部分结果会被展示,而非静默忽略。任何未解析的引用都会被放入并附带
_unresolved[]。若任何通道失败,状态为reason=...;仅当所有步骤成功完成时状态为STATUS=PARTIAL_OK。STATUS=OK - 循环检测按分支进行。若沿自身祖先链访问到相同流程,将输出而非递归。每个分支的祖先集合配有防御性的
_cycle_back_to:<path>限制;实际场景中的代理在达到任一限制前就会遍历完成。(早期文档声称硬上限为5;这是历史限制,因共享实用流程如MAX_BFS_DEPTH=20在每个嵌套树中都会触发该限制而被废弃——详见handleFlowFault的说明。)config.MAX_BFS_DEPTH - 子节点按字母顺序排序(不区分大小写)。在根层级,主题排在非主题规划器动作之前。流程动作调用顺序不会被排序——这是流程作者设定的执行顺序。
api_name