| name | analyzing-workflows |
| description | Parses discovered n8n workflow JSON files to build dependency graphs, decompose large workflows into subgraphs, identify all node types, resolve unknown nodes, and extract execution data for test fixtures. Activate when discovery is complete and the user is ready to analyze workflows, or when discussing workflow complexity, node types, dependency graphs, subgraphs, or unknown nodes.
|
Analyzing Workflows
You are analyzing the n8n workflows pulled during discovery. Your goal: understand
every workflow completely, flag every risk, and prepare a translation plan.
1. Processing Order
Analyze workflows from simplest to most complex (by node count). This lets you
build confidence and patterns before tackling the hardest ones.
Sort manifest workflows by node_count ascending. Process one at a time.
2. Per-Workflow Analysis Procedure
For each workflow JSON file in migration-state/discovery/workflows/:
Step 1 — Extract Metadata (without loading full file)
Use jq to extract just what you need without loading the full JSON into context:
cat <file> | jq '{
name: .name,
node_count: (.nodes | length),
nodes: [.nodes[] | {name: .name, type: .type, typeVersion: .typeVersion}],
connection_count: ([.connections | to_entries[] | .value.main[][]?] | length),
has_error_workflow: (.settings.errorWorkflow != null)
}'
Step 2 — Build Node Type Inventory
cat <file> | jq '[.nodes[].type] | group_by(.) | map({type: .[0], count: length}) | sort_by(-.count)'
Compile a deduplicated list of ALL node types across ALL workflows. This becomes
the master type inventory.
Step 3 — Resolve Unknown Node Types
For each unique node type in the inventory:
Layer 1 — Try n8n docs:
NODE_NAME=$(echo "<type>" | sed 's/n8n-nodes-base\.//' | sed 's/@.*$//')
curl -s -o /dev/null -w "%{http_code}" \
"https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.${NODE_NAME}/"
If status is 200, fetch the page content and extract key information:
curl -s "https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.${NODE_NAME}/" \
| head -500
If the page is a trigger node, try the trigger path instead:
curl -s -o /dev/null -w "%{http_code}" \
"https://docs.n8n.io/integrations/builtin/trigger-nodes/n8n-nodes-base.${NODE_NAME}trigger/"
Also try core nodes path:
curl -s -o /dev/null -w "%{http_code}" \
"https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.${NODE_NAME}/"
Layer 2 — Ask the user:
If all URL attempts return 404 or unhelpful content, tell the user:
"I found a node type <full_type_string> in workflow <workflow_name> but I
could not find documentation for it. Could you either:
Option A: Search for its docs and paste the URL here so I can read them, or
Option B: Describe what it does — what input does it take, what output does
it produce, and does it have any side effects (sends messages, writes to a
database, calls an API, etc.)?"
When the user provides a URL:
curl -s "<user_provided_url>" | head -1000
Extract the relevant information from the page.
Layer 3 — Record the mapping:
Save all resolved node info to migration-state/learned-nodes.json:
{
"n8n-nodes-base.telegram": {
"category": "messaging",
"docs_url": "https://docs.n8n.io/integrations/...",
"description": "Sends and receives Telegram messages",
"has_side_effects": true,
"requires_credentials": true,
"credential_type": "telegramApi",
"learned_from": "docs"
},
"n8n-nodes-community.customParser": {
"category": "data-transformation",
"docs_url": "https://example.com/custom-docs",
"description": "User-described: parses CSV into JSON",
"has_side_effects": false,
"requires_credentials": false,
"credential_type": null,
"learned_from": "user"
}
}
Step 4 — Build Dependency Graph
cat <file> | jq '
[.connections | to_entries[] |
.key as $src | .value.main[][] |
{source: $src, target: .node}]'
Identify and label:
- Entry points: Nodes with no incoming connections (triggers)
- Terminal nodes: Nodes with no outgoing connections
- Branch points: Nodes with multiple outputs (IF, Switch)
- Merge points: Nodes receiving from multiple sources (Merge)
- Error paths: Connections on error outputs (index 1 in main array)
Save the graph to migration-state/analysis/<workflow_id>_graph.json.
Step 5 — Subgraph Decomposition (for workflows with 50+ nodes)
Large workflows MUST be split into subgraphs to stay within context limits.
Splitting rules:
- Each trigger node starts a new subgraph
- Independent branches after a Switch/IF become separate subgraphs
- Error handling paths are always separate subgraphs
- Any chain of 30+ sequential nodes becomes its own subgraph
- Sub-workflows (Execute Workflow nodes) are natural boundaries
For each subgraph, define an interface contract:
{
"subgraph_id": "sg_a",
"name": "Entry and Routing",
"entry_node": "Webhook",
"exit_nodes": ["Route to Prayer", "Route to Admin"],
"input_schema": {"description": "Raw webhook payload"},
"output_schemas": {
"Route to Prayer": {"description": "Validated prayer request"},
"Route to Admin": {"description": "Admin command object"}
},
"node_count": 15,
"node_ids": ["node1", "node2", "..."]
}
Save to migration-state/analysis/<workflow_id>_subgraphs.json.
Step 6 — Extract Test Fixtures from Execution History
For each workflow, process the execution history files:
cat migration-state/discovery/executions/<wf_id>/<exec_id>.json | jq '
.data.resultData.runData | to_entries[] | {
node_name: .key,
input: .value[0].data.main[0],
output: .value[0].data.main[0]
}'
For each node, collect:
- 3-5 representative inputs and their expected outputs
- At least 1 edge case if visible (empty arrays, null fields, error conditions)
Save to migration-state/analysis/<workflow_id>_fixtures.json.
IMPORTANT: Scrub any PII or sensitive data from fixtures before saving. Replace
real user names, emails, phone numbers, and IDs with anonymized equivalents. Ask
the user to review fixtures if the data looks sensitive.
3. Analysis Report
After analyzing all workflows, present:
Analysis Report
===============
Workflows Analyzed: [n]
Node Type Summary:
[type]: [count] occurrences across [n] workflows
[type]: [count] occurrences across [n] workflows
...
Unknown Nodes Resolved: [n] (via docs: [n], via user: [n])
Remaining Unresolved: [n] — BLOCKS TRANSLATION
Subgraph Decomposition:
[workflow_name]: [n] subgraphs ([total_nodes] nodes)
[workflow_name]: 1 subgraph ([node_count] nodes — small enough for single pass)
...
Test Fixtures Extracted:
[workflow_name]: [n] fixtures from [n] executions
...
Risk Flags:
- [workflow] uses deprecated MySQL nodes — needs Postgres migration first
- [workflow] has [n] branches — high complexity, extra test coverage needed
- [workflow] uses community node [name] — no official docs, relying on user description
- [workflow] has 0 execution history — no fixtures available, manual test data needed
Estimated Translation Effort:
Simple (< 20 nodes): [n] workflows
Medium (20-50 nodes): [n] workflows
Complex (50+ nodes, requires decomposition): [n] workflows
Then ask: "Analysis complete. Ready to proceed to Phase 3 (Collecting Test Credentials)?"