8.3 KiB
architecture.md section reference
Per-section rendering spec for scripts/render_architecture.py::render.
One # Architecture H1, seven numbered ## N. ... sections, plus one
conditional "Dependency graph" appendix. Source of truth: the
metadata_tree.json schema produced by scripts/parse_wave.py at the
end of phase 9.
Source of truth: the live tree — field shapes evolve as parse_wave
learns new agent generations. When this doc disagrees with the
metadata_tree.json written by parse_wave.py for an actual agent on
your machine (under ~/.vibe/data/agentforce-architecture-analyze/<org>/<agent>__<ver>/),
trust the live tree.
The Mermaid templates live at assets/mermaid/*.mmd and are the sole
consumer of the renderer helpers; each {{PARAM}} contract is
documented in the template's own header comment.
Per-diagram node caps
Default caps (override via render(..., max_mermaid_nodes={...})):
| Diagram kind | Default cap | Over-cap behaviour |
|---|---|---|
flowchart |
200 | summary placeholder + top-5 fan-out + catalog pointer |
stateDiagram |
40 | summary placeholder (no fan-out — states are not nodes) |
sequenceDiagram |
60 | summary placeholder + top-5 fan-out |
graph |
100 | summary placeholder + top-5 fan-out |
Cap is measured in rendered elements (nodes + edges for flowchart/graph,
messages for sequenceDiagram, states + transitions for stateDiagram).
Above cap, the renderer emits a > [diagram truncated: ...] blockquote
with the element count, the top-5 nodes by fan-out (when applicable),
and a pointer to the catalog section that enumerates the same data
without compression.
1. Header + agent overview
Purpose: identify the agent and its planner in a single kv table.
Input fields (tree.agent.*):
api_name— agent developer nameversion—v<N>labelmaster_label— human-readable namedescription— prose summaryagent_type—EinsteinAgentKind/EinsteinCopilotForSalesforce/ …type—ExternalCopilot/InternalCopilot/ …agent_templatebot_sourcegeneration—classic/nga/search/byopplanner_nameplanner_typebot_id
Plus tree._schema_version.
Output shape: # <H1> with api_name + version, followed by a 2-col
markdown table.
Empty/degenerate cases:
- Missing
api_name/versionrenders?in the H1 (notNone). - Any missing field renders
-in its row — not empty, because GitHub table rendering collapses empty cells and the row loses alignment.
2. Anatomy summary
Purpose: one-paragraph executive summary plus health callouts.
Input fields:
tree._kind_counts— preferred source for topic / action / flow / apex / prompt counts.tree.depth,tree.node_count— size metrics.tree._partial,tree._partial_reason— health flag + prose reason.tree._pending_fetches—{"FLOW":[...],"APEX":[...], "PROMPT_TEMPLATE":[...],"STANDARD_ACTION":[...]}. Count determines the "pending fetches: N" line in the callout.tree._unresolved— triggers a second warn callout with the count.tree.agent.planner_name— missing -> warn callout.
Output shape: ## 2. Anatomy summary + paragraph + zero-to-three
blockquote callouts. Callouts render as > **Health: PARTIAL.** /
> **Health: WARN.** prefixes with bullet sub-lines.
Empty/degenerate cases: if _kind_counts is absent, the walker
supplies counts from its own pass over the tree. Zero topics is valid
(SequentialPlannerIntentClassifier).
3. Action tree
Purpose: the full declared action tree as a flowchart with per-topic subgraphs, plus a deterministic ASCII appendix for diff review.
Input fields:
- Walker-derived
topics[]-> one subgraph per topic. - Walker-derived
edges[]->parent_api_name --> child_api_name. node._cycle_back_to-> dotted back-edgeA -.->|cycle_back_to: X| B.- Planner-level actions (top-level
GEN_AI_FUNCTIONwith no parent topic) -> synthetic_plannerActionssubgraph.
Output shape: ```mermaid block with flowchart TB + subgraphs
- edges, followed by a
<details>with ASCII-tree appendix. When above cap, the mermaid block is replaced with the truncation placeholder; the ASCII appendix still renders.
Empty/degenerate cases:
- No topics, no planner actions ->
%% no topics+%% no edgesmermaid comments; diagram still parses. - Cycle annotations render in both the mermaid (dotted edge) and the
ASCII appendix (
[cycle]marker on the node line).
4. Topic anatomy
Purpose: per-topic detail dump. One H3 per topic with a bullet list of actions.
Input fields:
- Walker-derived
topics[]withapi_name,label,actions. topic.raw.master_label(preferred) or api_name for the label.
Output shape: ## 4. Topic anatomy + one ### \<api_name>` block per topic + kv list (- Label:, - Action count:, - Actions:`
with sub-bullets).
Empty/degenerate cases: 0 topics -> _No topics defined (planner exposes actions directly)._ italic fallback. This is the expected
case for SequentialPlannerIntentClassifier.
5. Action catalog
Purpose: flat markdown table of every declared action.
Input fields:
- Walker-derived
actions[]withapi_name,topic,raw.unwraps_to.
Output shape: 3-col table (Action | Topic | Unwraps to). Unwraps
column renders as KIND \api_name`whenunwraps_tois present,-otherwise. Planner-level actions show(plannerAction)` in the topic
column.
Empty/degenerate cases: no actions -> _No actions declared._
italic fallback.
6. Data flow / context propagation
Purpose: show which slot values propagate from user utterance through the planner into each action.
Input fields:
- Walker-derived
topics[]andactions[]. action.raw.planner_attr.variable_name+planner_attr.data_type— labels the edgeA -->|var: Type| B. When absent, the edge is bare.
Output shape: flowchart LR via load_mermaid("data_flow", ...).
Skeleton: User -> Planner -> each Topic -> each Action under
that topic.
Empty/degenerate cases: no planner_attr metadata -> every edge is
bare. 0 topics -> only User --> Planner renders (no action-level
edges). Above cap -> truncation placeholder.
7. Flow / Apex / Prompt catalogs
Purpose: per-artifact detail section for every backing flow, apex class, and prompt template referenced by any action.
Input fields:
- Walker-derived
flows{},apex{},prompts{}, keyed on api_name. node.signature(or_signaturefallback) — signature block.
Output shape: ### Flows / ### Apex classes / ### Prompt templates H3 buckets, each containing #### \<api_name>`+ a fenced signature block orSignature not captured.` fallback. Prompt
templates render as a flat bullet list (signature capture is
per-template prose, not a flow/apex shape).
Empty/degenerate cases: no backing artifacts in the tree ->
_No backing artifacts in tree._ italic fallback.
8. Unresolved refs + artifact pointers
Purpose: surface every _unresolved[] entry and point at the
sidecar files the reader can open.
Input fields:
tree._unresolved[]— list of{kind, api_name, reason}records.
Output shape: Either a 3-col Kind | Api name | Reason table or
an _No unresolved references._ italic fallback. Followed by an
### Artifact pointers sub-heading with a bullet list of relative
paths (tree JSON, manifest, summary).
Empty/degenerate cases: always renders — the artifact-pointer list is unconditional.
Conditional: Dependency graph
Purpose: rendered only when tree._unresolved[] is non-empty OR
the tree contains cycle annotations. Shows cross-artifact dependencies
plus the unresolved nodes as dashed-outline markers.
Input fields:
- Walker-derived
edges[]. tree._unresolved[]— each becomes a:::unresolvedstyled node.- Walker-derived
cycles[]— each becomes a dotted back-edge.
Output shape: graph LR via load_mermaid("dependency_graph", ...). Includes a classDef unresolved class marker at the bottom of
the template so unresolved nodes render with stroke-dasharray.
Empty/degenerate cases: not rendered at all when both conditions
are false. Above the graph cap -> truncation placeholder replaces
the mermaid block.