@ema.co/mcp-toolkit 2026.1.26 → 2026.1.27-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of @ema.co/mcp-toolkit might be problematic. Click here for more details.

Files changed (44) hide show
  1. package/dist/mcp/handlers/action/index.js +17 -20
  2. package/dist/mcp/handlers/data/index.js +72 -6
  3. package/dist/mcp/handlers/deprecation.js +50 -0
  4. package/dist/mcp/handlers/env/index.js +3 -3
  5. package/dist/mcp/handlers/knowledge/index.js +44 -237
  6. package/dist/mcp/handlers/persona/create.js +47 -18
  7. package/dist/mcp/handlers/persona/index.js +9 -10
  8. package/dist/mcp/handlers/persona/update.js +4 -2
  9. package/dist/mcp/handlers/reference/index.js +15 -2
  10. package/dist/mcp/handlers/sync/index.js +3 -18
  11. package/dist/mcp/handlers/workflow/analyze.js +53 -105
  12. package/dist/mcp/handlers/workflow/deploy.js +129 -0
  13. package/dist/mcp/handlers/workflow/generate.js +8 -28
  14. package/dist/mcp/handlers/workflow/index.js +258 -85
  15. package/dist/mcp/handlers/workflow/modify.js +9 -29
  16. package/dist/mcp/handlers/workflow/optimize.js +22 -108
  17. package/dist/mcp/handlers/workflow/utils.js +0 -102
  18. package/dist/mcp/handlers-consolidated.js +15 -38
  19. package/dist/mcp/prompts.js +82 -44
  20. package/dist/mcp/resources.js +335 -3
  21. package/dist/mcp/server.js +242 -457
  22. package/dist/mcp/tools.js +44 -61
  23. package/dist/sdk/action-schema-parser.js +11 -5
  24. package/dist/sdk/client.js +46 -17
  25. package/dist/sdk/ema-client.js +11 -0
  26. package/dist/sdk/generated/deprecated-actions.js +171 -0
  27. package/dist/sdk/guidance.js +58 -35
  28. package/dist/sdk/index.js +8 -7
  29. package/dist/sdk/knowledge.js +216 -1932
  30. package/dist/sdk/quality-gates.js +60 -336
  31. package/dist/sdk/validation-rules.js +33 -0
  32. package/dist/sdk/workflow-fixer.js +29 -360
  33. package/dist/sdk/workflow-intent.js +43 -3
  34. package/dist/sdk/workflow-transformer.js +0 -342
  35. package/docs/dashboard-operations.md +35 -0
  36. package/docs/ema-user-guide.md +66 -0
  37. package/docs/mcp-tools-guide.md +74 -45
  38. package/package.json +2 -2
  39. package/dist/mcp/handlers/persona/analyze.js +0 -275
  40. package/dist/mcp/handlers/persona/compare.js +0 -32
  41. package/dist/mcp/handlers/workflow/compile.js +0 -39
  42. package/docs/DEBUG-ANALYSIS-unused-category-type-mismatch.md +0 -481
  43. package/docs/TODO-fix-analyzer-and-modify.md +0 -182
  44. package/resources/action-schema.json +0 -5678
@@ -1,30 +1,6 @@
1
1
  /**
2
2
  * Shared utilities for workflow handlers
3
3
  */
4
- /**
5
- * Get the type/category of an action node
6
- */
7
- export function getActionType(action) {
8
- const name = action.name;
9
- if (!name)
10
- return "unknown";
11
- // Categorize by action name patterns
12
- if (name.includes("hitl") || name.includes("human"))
13
- return "hitl";
14
- if (name.includes("email") || name.includes("send"))
15
- return "communication";
16
- if (name.includes("search") || name.includes("retrieve"))
17
- return "retrieval";
18
- if (name.includes("classify") || name.includes("categorize"))
19
- return "classification";
20
- if (name.includes("generate") || name.includes("compose"))
21
- return "generation";
22
- if (name.includes("output") || name === "WORKFLOW_OUTPUT")
23
- return "output";
24
- if (name.includes("input") || name === "WORKFLOW_INPUT")
25
- return "input";
26
- return "processing";
27
- }
28
4
  /**
29
5
  * Sanitize workflow for deployment
30
6
  * Removes internal-only fields, validates structure
@@ -52,81 +28,3 @@ export function sanitizeWorkflowForDeploy(workflow) {
52
28
  });
53
29
  return sanitized;
54
30
  }
55
- /**
56
- * Check if a node has a path to the output
57
- */
58
- export function checkNodeHasPath(nodeId, connections, outputNodeId, visited = new Set()) {
59
- if (nodeId === outputNodeId)
60
- return true;
61
- if (visited.has(nodeId))
62
- return false;
63
- visited.add(nodeId);
64
- const outgoing = connections.filter(c => c.from === nodeId);
65
- for (const conn of outgoing) {
66
- if (checkNodeHasPath(conn.to, connections, outputNodeId, visited)) {
67
- return true;
68
- }
69
- }
70
- return false;
71
- }
72
- /**
73
- * Find orphan nodes (nodes with no path to output)
74
- */
75
- export function findOrphanNodes(workflow) {
76
- const actions = workflow.actions;
77
- if (!actions || actions.length === 0)
78
- return [];
79
- // Find output node
80
- const outputNode = actions.find(a => a.name?.includes("OUTPUT") ||
81
- a.id?.includes("OUTPUT"));
82
- if (!outputNode) {
83
- // No output node - can't determine orphans
84
- return [];
85
- }
86
- const outputId = (outputNode.id ?? outputNode.name);
87
- // Build connection list
88
- const connections = [];
89
- for (const action of actions) {
90
- const inputs = action.inputs;
91
- if (inputs) {
92
- const actionId = (action.id ?? action.name);
93
- for (const [_key, value] of Object.entries(inputs)) {
94
- if (typeof value === "string" && value.includes(".")) {
95
- const sourceAction = value.split(".")[0];
96
- connections.push({ from: sourceAction, to: actionId });
97
- }
98
- }
99
- }
100
- }
101
- // Find orphans
102
- const orphans = [];
103
- for (const action of actions) {
104
- const actionId = (action.id ?? action.name);
105
- const actionName = action.name;
106
- if (actionId === outputId)
107
- continue; // Skip output node
108
- if (!checkNodeHasPath(actionId, connections, outputId)) {
109
- orphans.push({
110
- id: actionId,
111
- name: actionName,
112
- reason: "No path to output node",
113
- });
114
- }
115
- }
116
- return orphans;
117
- }
118
- /**
119
- * Extract enum type name from a value
120
- */
121
- export function extractEnumTypeName(value) {
122
- if (typeof value === "object" && value !== null) {
123
- const obj = value;
124
- if (typeof obj.name === "string")
125
- return obj.name;
126
- if (typeof obj.type === "string")
127
- return obj.type;
128
- }
129
- if (typeof value === "string")
130
- return value;
131
- return undefined;
132
- }
@@ -28,37 +28,8 @@ import { handleWorkflow as handleWorkflowExtracted } from "./handlers/workflow/i
28
28
  // ─────────────────────────────────────────────────────────────────────────────
29
29
  // isValidWidget and sanitizeWidgets imported from ../sdk/proto-config.js
30
30
  // validateWidgetsForApi imported from handlers/utils.ts
31
- // ─────────────────────────────────────────────────────────────────────────────
32
- // Deprecation tracking - helps users migrate to new param names
33
- // ─────────────────────────────────────────────────────────────────────────────
34
- const DEPRECATED_PARAMS = {
35
- identifier: { newName: "id", removeVersion: "2.0.0" },
36
- clone_from: { newName: "from", removeVersion: "2.0.0" },
37
- template_id: { newName: "from", removeVersion: "2.0.0" },
38
- clone_data: { newName: "include_data", removeVersion: "2.0.0" },
39
- };
40
- /**
41
- * Check for deprecated params and collect warnings.
42
- * Returns array of warning messages for deprecated params that were used.
43
- */
44
- function checkDeprecatedParams(args) {
45
- const warnings = [];
46
- for (const [oldName, { newName, removeVersion }] of Object.entries(DEPRECATED_PARAMS)) {
47
- if (args[oldName] !== undefined) {
48
- warnings.push(`'${oldName}' is deprecated, use '${newName}' instead (will be removed in v${removeVersion})`);
49
- }
50
- }
51
- return warnings;
52
- }
53
- /**
54
- * Add deprecation warnings to response if any deprecated params were used.
55
- */
56
- function addDeprecationWarnings(result, warnings) {
57
- if (warnings.length > 0) {
58
- return { ...result, _deprecation_warnings: warnings };
59
- }
60
- return result;
61
- }
31
+ // Deprecation tracking - single source of truth
32
+ import { checkDeprecatedParams, addDeprecationWarnings } from "./handlers/deprecation.js";
62
33
  // Template utilities imported from handlers/utils.ts:
63
34
  // - normalizeTriggerType
64
35
  // - getTemplates
@@ -229,8 +200,8 @@ export async function handlePersona(args, client, getTemplateId, createClientFor
229
200
  return {
230
201
  error: "Explicit method required",
231
202
  message: "You provided a persona id/name. What operation would you like to perform?",
232
- valid_methods: ["get", "update", "delete", "analyze", "sanitize", "snapshot", "history", "restore", "compare"],
233
- hint: "Specify method='get' to fetch, method='update' to modify",
203
+ valid_methods: ["get", "update", "delete", "sanitize", "snapshot", "history", "restore"],
204
+ hint: "LLM does analysis/comparison. Use method='get' to fetch data, then reason about it.",
234
205
  example: `persona(method="get", id="${idOrName}")`,
235
206
  };
236
207
  }
@@ -316,16 +287,22 @@ export async function handlePersona(args, client, getTemplateId, createClientFor
316
287
  return { error: `Failed to get schema: ${error instanceof Error ? error.message : String(error)}` };
317
288
  }
318
289
  }
319
- // Compare, clone, create, analyze - all handled by extracted handlers
320
- case "compare":
290
+ // Clone and create - handled by extracted handlers
321
291
  case "clone":
322
- case "create":
323
- case "analyze": {
292
+ case "create": {
324
293
  // These modes have been extracted to handlers/persona/*.ts
325
294
  // - create.ts: handleCreate (~410 lines)
326
- // - analyze.ts: handleAnalyze (~195 lines)
327
295
  return { error: `Mode "${effectiveMode}" should be handled by extracted handler` };
328
296
  }
297
+ // Analyze and compare - LLM does this, not MCP
298
+ case "analyze":
299
+ case "compare": {
300
+ return {
301
+ error: `Method "${effectiveMode}" removed - LLM does analysis/comparison`,
302
+ hint: "Use method='get' to fetch persona data, then do your own analysis/comparison.",
303
+ example: `persona(method="get", id="...", include_workflow=true)`,
304
+ };
305
+ }
329
306
  // ─────────────── Version Management Modes ───────────────
330
307
  // Extracted to handlers/persona/version.ts
331
308
  case "snapshot":
@@ -28,12 +28,12 @@ const PROMPTS = {
28
28
  },
29
29
  {
30
30
  name: "context",
31
- description: "Context type: 'greenfield' (new workflow), 'brownfield' (extend existing), 'optimize' (improve existing)",
31
+ description: "Context type: 'greenfield' (new workflow), 'brownfield' (extend existing)",
32
32
  required: false,
33
33
  },
34
34
  {
35
35
  name: "persona_id",
36
- description: "Existing persona ID if brownfield/optimize context",
36
+ description: "Existing persona ID if brownfield context",
37
37
  required: false,
38
38
  },
39
39
  ],
@@ -53,10 +53,12 @@ ${args.persona_id ? `**Existing Persona**: ${args.persona_id}` : ""}
53
53
 
54
54
  ### Step 1: Parse the Request
55
55
  Identify what the user is asking for:
56
- - **Action Type**: Create new / Extend existing / Optimize / Analyze
56
+ - **Action Type**: Create new / Extend existing
57
57
  - **Scope**: Single intent / Multi-intent / Full workflow
58
58
  - **Specificity**: Vague / Partially specified / Detailed
59
59
 
60
+ Note: For analysis/optimization, use \`workflow(mode="get")\` then analyze with \`ema://rules/*\` resources.
61
+
60
62
  ### Step 2: Check for Required Information
61
63
 
62
64
  #### For ALL requests, verify:
@@ -92,13 +94,6 @@ For external side-effect actions (send_email, create_ticket, update_record):
92
94
  | **Data Dependencies** | ✓/✗ | What existing data to use? |
93
95
  | **Impact Assessment** | ✓/✗ | What might break? |
94
96
 
95
- #### For OPTIMIZE:
96
- | Dimension | Status | Missing Info |
97
- |-----------|--------|--------------|
98
- | **Problem Areas** | ✓/✗ | What's not working? |
99
- | **Performance Goals** | ✓/✗ | Speed, accuracy, cost? |
100
- | **Constraints** | ✓/✗ | What can't change? |
101
-
102
97
  ### Step 3: Identify Ambiguities
103
98
 
104
99
  Look for:
@@ -159,7 +154,7 @@ Based on analysis, output ONE of:
159
154
  "confidence": "high|medium",
160
155
  "summary": "Brief summary of understood requirements",
161
156
  "inferred_defaults": ["List any assumptions made"],
162
- "next_action": "workflow(mode='generate'|'extend'|'optimize', ...)"
157
+ "next_action": "workflow(mode='get'|'deploy', ...)"
163
158
  }
164
159
  \`\`\`
165
160
 
@@ -338,15 +333,19 @@ Environment: ${args.env || "demo"}
338
333
 
339
334
  Follow this review workflow using the consolidated tools:
340
335
 
341
- ### Step 1: Fetch Persona + Workflow
342
- Call \`persona(id="${args.persona_id}", include_workflow=true, env="${args.env || "demo"}")\` to fetch the full workflow_def.
336
+ ### Step 1: Fetch Workflow Data
337
+ Call \`workflow(mode="get", persona_id="${args.persona_id}", env="${args.env || "demo"}")\` to get the workflow_def, schema, and examples.
343
338
 
344
- ### Step 2: Analyze (Issues + Connections + Fixes + Metrics)
345
- Call \`workflow(mode="analyze", persona_id="${args.persona_id}", env="${args.env || "demo"}")\`.
339
+ ### Step 2: Analyze (YOU do this)
340
+ Review the workflow_def for:
341
+ - Missing WORKFLOW_OUTPUT (required for activation)
342
+ - Missing Fallback category in categorizers
343
+ - Type mismatches between connected nodes
344
+ - Orphan nodes not connected to output
346
345
 
347
- ### Step 3: (Optional) Preview Auto-Fixes
348
- If issues are found and you want a one-click preview of fixes:
349
- Call \`workflow(mode="optimize", persona_id="${args.persona_id}", preview=true, env="${args.env || "demo"}")\`.
346
+ ### Step 3: Propose Fixes
347
+ If issues are found, generate a corrected workflow_def and deploy:
348
+ Call \`workflow(mode="deploy", persona_id="${args.persona_id}", workflow_def={...}, env="${args.env || "demo"}")\`.
350
349
 
351
350
  ## Output Format
352
351
 
@@ -456,9 +455,9 @@ ${args.symptoms.toLowerCase().includes("hitl") || args.symptoms.toLowerCase().in
456
455
  ` : ""}
457
456
  ${args.symptoms.toLowerCase().includes("type") || args.symptoms.toLowerCase().includes("mismatch") ? `
458
457
  **Type Compatibility Issues:**
459
- - Call \`workflow(mode="analyze", persona_id="${args.persona_id}", env="${args.env || "demo"}", include=["connections"])\` for an edge-by-edge type check
458
+ - Call \`workflow(mode="get", persona_id="${args.persona_id}", env="${args.env || "demo"}")\` and analyze the workflow_def
459
+ - Check wellKnownType compatibility between connected nodes
460
460
  - Common issues: chat_conversation → search (should be user_query)
461
- - Check wellKnownType compatibility
462
461
  ` : ""}
463
462
  ${args.symptoms.toLowerCase().includes("loop") || args.symptoms.toLowerCase().includes("infinite") || args.symptoms.toLowerCase().includes("hang") ? `
464
463
  **Loop/Hang Issues:**
@@ -467,8 +466,8 @@ ${args.symptoms.toLowerCase().includes("loop") || args.symptoms.toLowerCase().in
467
466
  - Verify workflow has proper termination paths
468
467
  ` : ""}
469
468
 
470
- ### Step 4: Run Issue Detection
471
- Call \`workflow(mode="analyze", persona_id="${args.persona_id}", env="${args.env || "demo"}")\` to find issues, connections, suggested fixes, and metrics.
469
+ ### Step 4: Review Workflow
470
+ Call \`workflow(mode="get", persona_id="${args.persona_id}", env="${args.env || "demo"}")\` and analyze the workflow_def for issues.
472
471
 
473
472
  ### Step 5: Propose Fix
474
473
  Based on findings, provide specific fix with before/after configuration.
@@ -642,13 +641,15 @@ Call in parallel:
642
641
  - \`persona(id="${args.persona_id_1}", include_workflow=true, env="${args.env_1 || "demo"}")\`
643
642
  - \`persona(id="${args.persona_id_2}", include_workflow=true, env="${args.env_2 || args.env_1 || "demo"}")\`
644
643
 
645
- ### Step 2: Compare
646
- Call \`persona(id="${args.persona_id_1}", mode="compare", compare_to="${args.persona_id_2}", env="${args.env_1 || "demo"}", compare_env="${args.env_2 || args.env_1 || "demo"}")\`.
644
+ ### Step 2: Get Both Personas
645
+ Call \`persona(method="get", id="${args.persona_id_1}", include_workflow=true, env="${args.env_1 || "demo"}")\`
646
+ Call \`persona(method="get", id="${args.persona_id_2}", include_workflow=true, env="${args.env_2 || args.env_1 || "demo"}")\`
647
647
 
648
- ### Step 3: Compare Workflows (if both have workflows)
649
- If both personas are in the same environment, call:
650
- \`workflow(mode="compare", persona_id="${args.persona_id_1}", compare_to="${args.persona_id_2}", env="${args.env_1 || "demo"}")\`
651
- to see structural differences.
648
+ ### Step 3: Compare (YOU do this)
649
+ Compare the two workflow_def structures:
650
+ - Node differences (added/removed/renamed)
651
+ - Connection differences
652
+ - Configuration differences
652
653
 
653
654
  ## Output Format
654
655
 
@@ -754,8 +755,9 @@ ${args.action === "snapshot" ? `
754
755
  1. List versions first to see available:
755
756
  \`persona(id="${args.persona_id}", mode="version_list", env="${args.env || "demo"}")\`
756
757
 
757
- 2. Compare two versions:
758
- \`persona(id="${args.persona_id}", mode="version_compare", v1="${args.version || "v1"}", v2="latest", env="${args.env || "demo"}")\`
758
+ 2. Get two versions and compare (YOU compare the results):
759
+ \`persona(id="${args.persona_id}", mode="version_get", version="${args.version || "v1"}", env="${args.env || "demo"}")\`
760
+ \`persona(id="${args.persona_id}", mode="version_get", version="latest", env="${args.env || "demo"}")\`
759
761
 
760
762
  3. Present changes:
761
763
  - Fields that changed
@@ -937,7 +939,7 @@ Provide examples of common tasks:
937
939
  2. **Search for specific persona**: \`persona(query="support", status="active", env="demo")\`
938
940
  3. **Get full persona details**: \`persona(id="xxx", include_workflow=true, env="demo")\`
939
941
  4. **Sync a persona**: \`sync(id="my-bot", source="demo", target="dev")\`
940
- 5. **Analyze workflow**: \`workflow(mode="analyze", persona_id="xxx", env="demo")\`
942
+ 5. **Get workflow data**: \`workflow(mode="get", persona_id="xxx", env="demo")\` (you analyze the result)
941
943
 
942
944
  ## Output Format
943
945
 
@@ -1027,6 +1029,15 @@ ${args.intents ? `**Intents**: ${args.intents}` : ""}
1027
1029
 
1028
1030
  ## Instructions
1029
1031
 
1032
+ ### Step 0: Check Deprecated Actions (DO THIS FIRST)
1033
+ Fetch \`ema://rules/deprecated-actions-summary\` to know which actions to AVOID.
1034
+
1035
+ **Key deprecated actions to avoid:**
1036
+ - search/v0 → use search/v2 (requires datastore_configs)
1037
+ - respond_with_sources → use respond_for_external_actions
1038
+ - call_llm/v0 → use call_llm/v2
1039
+ - web_search/v0 → use live_web_search or ai_web_search
1040
+
1030
1041
  ### Step 1: Get Templates
1031
1042
  Get templates from API or use generated fallbacks:
1032
1043
  - \`template(config="voice")\` - Voice AI persona configuration (API-first with fallback)
@@ -1061,10 +1072,12 @@ ${args.name.toLowerCase().replace(/\s+/g, "-")}/
1061
1072
  └── proto-config.json # Full API config
1062
1073
  \`\`\`
1063
1074
 
1075
+ **IMPORTANT**: Only use non-deprecated actions from Step 0.
1076
+
1064
1077
  ### Step 6: Validate
1065
1078
  Call \`reference(validate_prompt=<generated_prompt>)\` to verify the prompt.
1066
1079
 
1067
- Now begin by reading the resources, then proceed with generation.`,
1080
+ Now begin by reading the deprecated actions, then proceed with generation.`,
1068
1081
  },
1069
1082
  },
1070
1083
  ],
@@ -1107,6 +1120,15 @@ ${args.data_sources ? `**Data Sources**: ${args.data_sources}` : ""}
1107
1120
 
1108
1121
  ## Instructions
1109
1122
 
1123
+ ### Step 0: Check Deprecated Actions (DO THIS FIRST)
1124
+ Fetch \`ema://rules/deprecated-actions-summary\` to know which actions to AVOID.
1125
+
1126
+ **Key deprecated actions to avoid:**
1127
+ - search/v0 → use search/v2 (requires datastore_configs)
1128
+ - respond_with_sources → use respond_for_external_actions
1129
+ - call_llm/v0 → use call_llm/v2
1130
+ - web_search/v0 → use live_web_search or ai_web_search
1131
+
1110
1132
  ### Step 1: Get Templates
1111
1133
  Get templates from API or use generated fallbacks:
1112
1134
  - \`template(config="chat")\` - Chat AI persona configuration (API-first with fallback)
@@ -1130,6 +1152,8 @@ Call \`reference(guidance="conversation-vs-query")\` to understand:
1130
1152
  ### Step 5: Generate Output
1131
1153
  Using the templates from Step 1 and guidance from Steps 3-4, generate:
1132
1154
 
1155
+ **IMPORTANT**: Only use non-deprecated actions from Step 0.
1156
+
1133
1157
  **Folder structure:**
1134
1158
  \`\`\`
1135
1159
  ${args.name.toLowerCase().replace(/\s+/g, "-")}/
@@ -1183,6 +1207,16 @@ Now begin by reading the resources, then proceed with generation.`,
1183
1207
  **Type**: ${args.type}
1184
1208
  **Description**: ${args.description}
1185
1209
 
1210
+ ## Step 0: Check Deprecated Actions (DO THIS FIRST)
1211
+
1212
+ Fetch \`ema://rules/deprecated-actions-summary\` to see which actions to AVOID.
1213
+
1214
+ Common deprecated actions:
1215
+ - search/v0 → use search/v2 (requires datastore_configs)
1216
+ - respond_with_sources → use respond_for_external_actions
1217
+ - call_llm/v0 → use call_llm/v2
1218
+ - web_search/v0 → use live_web_search or ai_web_search
1219
+
1186
1220
  ## Step 1: Preview the workflow
1187
1221
 
1188
1222
  \`\`\`
@@ -1193,6 +1227,7 @@ workflow(
1193
1227
  \`\`\`
1194
1228
 
1195
1229
  This returns workflow_def and proto_config. Review them before deploying.
1230
+ **Check for any deprecated actions in the generated workflow.**
1196
1231
 
1197
1232
  ## Step 2: Deploy when ready
1198
1233
 
@@ -1213,7 +1248,8 @@ ${args.type === "voice" ? `
1213
1248
  The generated proto_config includes voice settings:
1214
1249
  - welcomeMessage: Generated greeting
1215
1250
  - identityAndPurpose: Generated from description
1216
- - takeActionInstructions, hangupInstructions: Sensible defaults
1251
+ - takeActionInstructions: Auto-generated from workflow tools (if tools specified)
1252
+ - hangupInstructions: Sensible defaults
1217
1253
 
1218
1254
  These are set automatically but can be customized via proto_config override.
1219
1255
  ` : ""}`,
@@ -1349,8 +1385,7 @@ ${args.workflow_def ? `**Workflow Definition**: Provided inline` : ""}
1349
1385
  ${args.persona_id ? `First, fetch the workflow:
1350
1386
  \`persona(id="${args.persona_id}", include_workflow=true, env="${args.env || "demo"}")\`
1351
1387
 
1352
- Then analyze it using:
1353
- \`workflow(persona_id="${args.persona_id}", mode="analyze", env="${args.env || "demo"}")\`
1388
+ Then review the workflow_def for issues (missing WORKFLOW_OUTPUT, type mismatches, etc.).
1354
1389
  ` : ""}
1355
1390
 
1356
1391
  ## Required Analysis Sections
@@ -1506,10 +1541,11 @@ Proceed to Phase 1.
1506
1541
 
1507
1542
  ### Step 1.1: Fetch and Analyze
1508
1543
  \`\`\`
1509
- persona(id="${args.persona_id}", include_workflow=true, env="${args.env || "demo"}")
1510
- workflow(persona_id="${args.persona_id}", mode="analyze", env="${args.env || "demo"}")
1544
+ workflow(mode="get", persona_id="${args.persona_id}", env="${args.env || "demo"}")
1511
1545
  \`\`\`
1512
1546
 
1547
+ Review the workflow_def for issues (missing WORKFLOW_OUTPUT, type mismatches, orphan nodes).
1548
+
1513
1549
  ### Step 1.2: Document Existing Logic
1514
1550
  Before making changes, document:
1515
1551
  - **Current intents**: List all categories and their handlers
@@ -1611,8 +1647,8 @@ workflow(
1611
1647
 
1612
1648
  ## Phase 4: Validate & Deploy
1613
1649
 
1614
- ### Step 4.1: Analyze Changes
1615
- \`workflow(persona_id="${args.persona_id}", mode="analyze")\`
1650
+ ### Step 4.1: Review Changes
1651
+ \`workflow(mode="get", persona_id="${args.persona_id}")\` and verify the workflow_def is correct.
1616
1652
 
1617
1653
  Verify:
1618
1654
  - [ ] No type mismatches
@@ -1620,11 +1656,12 @@ Verify:
1620
1656
  - [ ] All new nodes properly linked
1621
1657
  - [ ] Existing functionality preserved
1622
1658
 
1623
- ### Step 4.2: Preview Changes
1624
- \`workflow(persona_id="${args.persona_id}", mode="optimize", preview=true)\`
1659
+ ### Step 4.2: Validate with Rules
1660
+ Fetch \`ema://rules/anti-patterns\` and verify no issues.
1625
1661
 
1626
1662
  ### Step 4.3: Deploy
1627
- \`workflow(persona_id="${args.persona_id}", mode="deploy", workflow_def=<extended_workflow>)\`
1663
+ \`workflow(persona_id="${args.persona_id}", mode="deploy", workflow_def=<extended_workflow>, preview=true)\`
1664
+ Then without preview to commit.
1628
1665
 
1629
1666
  ## Extension Patterns
1630
1667
 
@@ -1709,10 +1746,11 @@ Provide:
1709
1746
  ## Step 1: Fetch Workflow Data
1710
1747
 
1711
1748
  \`\`\`
1712
- persona(id="${args.persona_id}", include_workflow=true, env="${args.env || "demo"}")
1713
- workflow(persona_id="${args.persona_id}", mode="analyze", env="${args.env || "demo"}")
1749
+ workflow(mode="get", persona_id="${args.persona_id}", env="${args.env || "demo"}")
1714
1750
  \`\`\`
1715
1751
 
1752
+ Review the workflow_def for issues (missing WORKFLOW_OUTPUT, type mismatches, orphan nodes).
1753
+
1716
1754
  ## Step 2: Intent Analysis Framework
1717
1755
 
1718
1756
  ### Business Intent Layer