@ema.co/mcp-toolkit 2026.2.13 → 2026.2.23
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.
- package/.context/public/guides/ema-user-guide.md +12 -16
- package/.context/public/guides/mcp-tools-guide.md +203 -334
- package/dist/cli/index.js +2 -2
- package/dist/mcp/domain/loop-detection.js +89 -0
- package/dist/mcp/domain/sanitizer.js +1 -1
- package/dist/mcp/domain/structural-rules.js +4 -5
- package/dist/mcp/domain/validation-rules.js +5 -5
- package/dist/mcp/domain/workflow-graph.js +3 -5
- package/dist/mcp/domain/workflow-path-enumerator.js +7 -4
- package/dist/mcp/guidance.js +62 -29
- package/dist/mcp/handlers/debug/adapter.js +15 -0
- package/dist/mcp/handlers/debug/formatters.js +282 -0
- package/dist/mcp/handlers/debug/index.js +133 -0
- package/dist/mcp/handlers/demo/adapter.js +180 -0
- package/dist/mcp/handlers/env/config.js +2 -2
- package/dist/mcp/handlers/feedback/index.js +1 -1
- package/dist/mcp/handlers/index.js +0 -1
- package/dist/mcp/handlers/persona/adapter.js +135 -0
- package/dist/mcp/handlers/persona/index.js +237 -8
- package/dist/mcp/handlers/persona/schema.js +27 -0
- package/dist/mcp/handlers/reference/index.js +6 -4
- package/dist/mcp/handlers/sync/adapter.js +200 -0
- package/dist/mcp/handlers/workflow/adapter.js +174 -0
- package/dist/mcp/handlers/workflow/fix.js +11 -12
- package/dist/mcp/handlers/workflow/index.js +12 -40
- package/dist/mcp/handlers/workflow/validation.js +1 -1
- package/dist/mcp/knowledge-guidance-topics.js +615 -0
- package/dist/mcp/knowledge-types.js +7 -0
- package/dist/mcp/knowledge.js +75 -1403
- package/dist/mcp/resources-dynamic.js +2395 -0
- package/dist/mcp/resources-validation.js +408 -0
- package/dist/mcp/resources.js +72 -2508
- package/dist/mcp/server.js +69 -2825
- package/dist/mcp/tools.js +106 -5
- package/dist/sdk/client-adapter.js +265 -24
- package/dist/sdk/ema-client.js +100 -9
- package/dist/sdk/generated/agent-catalog.js +615 -0
- package/dist/sdk/generated/well-known-types.js +99 -0
- package/dist/sdk/generated/widget-catalog.js +60 -0
- package/dist/sdk/grpc-client.js +115 -1
- package/dist/sync/sdk.js +2 -2
- package/dist/sync.js +4 -3
- package/docs/README.md +17 -9
- package/package.json +3 -2
- package/.context/public/guides/dashboard-operations.md +0 -349
- package/.context/public/guides/email-patterns.md +0 -125
- package/.context/public/guides/workflow-builder-patterns.md +0 -708
- package/dist/mcp/domain/intent-architect.js +0 -914
- package/dist/mcp/domain/quality-gates.js +0 -110
- package/dist/mcp/domain/workflow-execution-analyzer.js +0 -412
- package/dist/mcp/domain/workflow-intent.js +0 -1806
- package/dist/mcp/domain/workflow-merge.js +0 -449
- package/dist/mcp/domain/workflow-tracer.js +0 -648
- package/dist/mcp/domain/workflow-transformer.js +0 -742
- package/dist/mcp/handlers/knowledge/index.js +0 -54
- package/dist/mcp/handlers/persona/intent.js +0 -141
- package/dist/mcp/handlers/workflow/analyze.js +0 -119
- package/dist/mcp/handlers/workflow/compare.js +0 -70
- package/dist/mcp/handlers/workflow/generate.js +0 -384
- package/dist/mcp/handlers-consolidated.js +0 -333
package/dist/cli/index.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* config validate - Validate config file
|
|
12
12
|
*/
|
|
13
13
|
import { loadConfig } from "../sdk/config.js";
|
|
14
|
-
import {
|
|
14
|
+
import { EmaClientAdapter } from "../sdk/client-adapter.js";
|
|
15
15
|
import { SyncSDK } from "../sync/sdk.js";
|
|
16
16
|
function printUsage() {
|
|
17
17
|
console.log(`
|
|
@@ -220,7 +220,7 @@ async function runAgentsCommand(subcommand, args, options) {
|
|
|
220
220
|
baseUrl: master.baseUrl,
|
|
221
221
|
bearerToken: getEnvOrThrow(master.bearerTokenEnv),
|
|
222
222
|
};
|
|
223
|
-
const client = new
|
|
223
|
+
const client = new EmaClientAdapter(env);
|
|
224
224
|
switch (subcommand) {
|
|
225
225
|
case "list": {
|
|
226
226
|
const actions = await client.listAgents();
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loop Detection for Workflow Graphs
|
|
3
|
+
*
|
|
4
|
+
* Uses the shared WorkflowGraph representation from workflow-graph.ts
|
|
5
|
+
* for cycle and re-entry detection in workflow validation.
|
|
6
|
+
*/
|
|
7
|
+
import { buildWorkflowGraph } from "./workflow-graph.js";
|
|
8
|
+
export function detectLoops(workflowDef) {
|
|
9
|
+
if (!workflowDef || typeof workflowDef !== "object")
|
|
10
|
+
return [];
|
|
11
|
+
const graph = buildWorkflowGraph(workflowDef);
|
|
12
|
+
if (graph.nodes.size === 0)
|
|
13
|
+
return [];
|
|
14
|
+
const loops = [];
|
|
15
|
+
const { forward } = graph;
|
|
16
|
+
const visited = new Set();
|
|
17
|
+
const recursionStack = new Set();
|
|
18
|
+
const path = [];
|
|
19
|
+
function dfs(nodeId) {
|
|
20
|
+
visited.add(nodeId);
|
|
21
|
+
recursionStack.add(nodeId);
|
|
22
|
+
path.push(nodeId);
|
|
23
|
+
for (const neighbor of (forward.get(nodeId) ?? [])) {
|
|
24
|
+
if (!visited.has(neighbor)) {
|
|
25
|
+
if (dfs(neighbor))
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
else if (recursionStack.has(neighbor)) {
|
|
29
|
+
const cycleStart = path.indexOf(neighbor);
|
|
30
|
+
const cyclePath = path.slice(cycleStart);
|
|
31
|
+
cyclePath.push(neighbor);
|
|
32
|
+
loops.push({
|
|
33
|
+
type: 'circular_dependency',
|
|
34
|
+
nodes: cyclePath,
|
|
35
|
+
description: `Circular dependency: ${cyclePath.join(' → ')}`,
|
|
36
|
+
severity: 'critical',
|
|
37
|
+
fixSuggestion: `Break the cycle by removing one edge.`,
|
|
38
|
+
});
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
path.pop();
|
|
43
|
+
recursionStack.delete(nodeId);
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
if (graph.trigger)
|
|
47
|
+
dfs(graph.trigger);
|
|
48
|
+
for (const nodeId of graph.nodes.keys()) {
|
|
49
|
+
if (!visited.has(nodeId))
|
|
50
|
+
dfs(nodeId);
|
|
51
|
+
}
|
|
52
|
+
// Detect categorizer routing back to upstream (re-entry)
|
|
53
|
+
detectReentryLoops(graph, loops);
|
|
54
|
+
return loops;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Detect categorizer nodes routing back to upstream nodes (re-entry risk).
|
|
58
|
+
* Uses the graph's reverse adjacency map instead of manual edge traversal.
|
|
59
|
+
*/
|
|
60
|
+
function detectReentryLoops(graph, loops) {
|
|
61
|
+
for (const [nodeId, graphNode] of graph.nodes) {
|
|
62
|
+
if (graphNode.actionType !== 'chat_categorizer')
|
|
63
|
+
continue;
|
|
64
|
+
const downstream = graph.forward.get(nodeId) ?? new Set();
|
|
65
|
+
const upstream = new Set();
|
|
66
|
+
function collectUpstream(nId, depth = 0) {
|
|
67
|
+
if (depth > 20)
|
|
68
|
+
return;
|
|
69
|
+
for (const parent of (graph.reverse.get(nId) ?? [])) {
|
|
70
|
+
if (!upstream.has(parent)) {
|
|
71
|
+
upstream.add(parent);
|
|
72
|
+
collectUpstream(parent, depth + 1);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
collectUpstream(nodeId);
|
|
77
|
+
for (const downNode of downstream) {
|
|
78
|
+
if (upstream.has(downNode)) {
|
|
79
|
+
loops.push({
|
|
80
|
+
type: 'reentry_loop',
|
|
81
|
+
nodes: [nodeId, downNode],
|
|
82
|
+
description: `Categorizer "${graphNode.displayName || nodeId}" routes to "${downNode}" which is upstream - can cause re-processing`,
|
|
83
|
+
severity: 'warning',
|
|
84
|
+
fixSuggestion: `Add state tracking or one-time-execution gate to prevent re-processing.`,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -896,7 +896,7 @@ export function applySessionMappings(text, session) {
|
|
|
896
896
|
* Content fields that SHOULD be sanitized (allowlist approach).
|
|
897
897
|
* Only these fields contain user-facing content that may have PII.
|
|
898
898
|
*
|
|
899
|
-
*
|
|
899
|
+
* Manually maintained — candidate for auto-generation from OpenAPI/gRPC definitions.
|
|
900
900
|
*/
|
|
901
901
|
const CONTENT_FIELDS = new Set([
|
|
902
902
|
// Persona-level
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
* Structural Rules for LLM Context
|
|
3
3
|
*
|
|
4
4
|
* These rules encode the validation logic from:
|
|
5
|
-
* - workflow-fixer.ts
|
|
6
|
-
* - workflow-execution-analyzer.ts
|
|
7
5
|
* - knowledge.ts (detectWorkflowIssues)
|
|
6
|
+
* - loop-detection.ts (cycle detection, extracted from workflow-execution-analyzer.ts)
|
|
8
7
|
*
|
|
9
8
|
* PURPOSE: Feed these to the LLM so it can self-validate during generation/transformation.
|
|
10
9
|
* This is the "teach the LLM the rules" approach vs "fix after the fact".
|
|
@@ -105,9 +104,9 @@ export const STRUCTURAL_INVARIANTS = [
|
|
|
105
104
|
{
|
|
106
105
|
id: "hitl_has_both_paths",
|
|
107
106
|
name: "HITL Must Have Success AND Failure Paths",
|
|
108
|
-
rule: "
|
|
107
|
+
rule: "Legacy general_hitl nodes (if present) have two outcomes: approval and rejection. Both MUST have downstream handlers. Note: general_hitl is NOT deployable for new workflows — HITL is a flag on entity_extraction_with_documents and send_email_agent only.",
|
|
109
108
|
violation: "HITL 'approval' only has success path - rejections hang",
|
|
110
|
-
fix: "
|
|
109
|
+
fix: "For legacy workflows: add handler for hitl.approval_decision = 'reject'. For new workflows: use HITL flag on send_email_agent or entity_extraction_with_documents instead.",
|
|
111
110
|
severity: "critical",
|
|
112
111
|
},
|
|
113
112
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -338,7 +337,7 @@ BEFORE finalizing any workflow modification, verify these rules:
|
|
|
338
337
|
|
|
339
338
|
### HITL Rules
|
|
340
339
|
|
|
341
|
-
10. **Both Paths Required**: general_hitl
|
|
340
|
+
10. **Both Paths Required**: Legacy general_hitl nodes need handlers for both approval AND rejection. Note: general_hitl is NOT deployable — HITL is a flag on entity_extraction_with_documents and send_email_agent only.
|
|
342
341
|
|
|
343
342
|
### Raw workflow_def Format Rules (CRITICAL)
|
|
344
343
|
|
|
@@ -135,7 +135,7 @@ export const ANTI_PATTERNS = [
|
|
|
135
135
|
pattern: "send_email_agent without entity_extraction to validate recipient data",
|
|
136
136
|
problem: "Sending emails without extracting and validating recipient data risks sending to wrong people or with wrong content. Emails are high-impact actions with external side effects.",
|
|
137
137
|
solution: "Always: 1) Extract required fields (email_address, subject) via entity_extraction, 2) Validate completeness via categorizer, 3) Ask user if missing. " +
|
|
138
|
-
"For approval: enable the HITL flag on send_email_agent (
|
|
138
|
+
"For approval: enable the HITL flag on send_email_agent (disable_human_interaction: false). general_hitl is NOT deployable.",
|
|
139
139
|
detection: {
|
|
140
140
|
issueType: "incomplete_email_validation",
|
|
141
141
|
condition: "send_email_agent without preceding entity_extraction node to extract/validate recipient data",
|
|
@@ -195,15 +195,15 @@ export const ANTI_PATTERNS = [
|
|
|
195
195
|
name: "Incomplete HITL Paths",
|
|
196
196
|
pattern: "HITL with only success path",
|
|
197
197
|
problem: "Rejected requests have no handling, leaving users without response.",
|
|
198
|
-
solution: "If workflow already has general_hitl node: ALWAYS implement both success AND failure paths. For NEW workflows: use HITL flag on the agent
|
|
198
|
+
solution: "If workflow already has general_hitl node: ALWAYS implement both success AND failure paths. For NEW workflows: use HITL flag on the agent (only entity_extraction_with_documents and send_email_agent support HITL). general_hitl is NOT deployable.",
|
|
199
199
|
detection: {
|
|
200
200
|
issueType: "incomplete_hitl",
|
|
201
201
|
condition: "HITL node missing 'hitl_status_HITL Success' or 'hitl_status_HITL Failure' edge (note: space, not underscore)",
|
|
202
202
|
},
|
|
203
203
|
severity: "critical",
|
|
204
|
-
//
|
|
205
|
-
//
|
|
206
|
-
// This
|
|
204
|
+
// general_hitl is NOT deployable — it appears in catalogs but cannot be deployed.
|
|
205
|
+
// HITL is a flag on entity_extraction_with_documents and send_email_agent only.
|
|
206
|
+
// external_action_caller does NOT support HITL. This rule still fires for legacy workflows.
|
|
207
207
|
},
|
|
208
208
|
{
|
|
209
209
|
id: "orphan-nodes",
|
|
@@ -2,12 +2,10 @@
|
|
|
2
2
|
* Shared Workflow Graph Representation
|
|
3
3
|
*
|
|
4
4
|
* Single source of truth for parsing workflow_def JSON into a typed graph.
|
|
5
|
-
*
|
|
6
|
-
* workflow-optimizer (deprecated), and workflow-tracer.
|
|
5
|
+
* Used by the workflow optimizer for static analysis.
|
|
7
6
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* (static analysis). Future work: consolidate both into this module.
|
|
7
|
+
* `loop-detection.ts` uses `buildWorkflowGraph()` from this module for
|
|
8
|
+
* cycle and re-entry detection (consolidated from a prior local `buildGraphMaps`).
|
|
11
9
|
*/
|
|
12
10
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
13
11
|
// Constants
|
|
@@ -50,7 +50,7 @@ export function enumeratePaths(workflow, options) {
|
|
|
50
50
|
throw new Error("Branch outcome without branch_point");
|
|
51
51
|
}
|
|
52
52
|
for (const value of result.branch_point.possible_values) {
|
|
53
|
-
const forkedSession = forkSessionForBranching(session, result.branch_point, value);
|
|
53
|
+
const forkedSession = forkSessionForBranching(session, result.branch_point, value, workflow);
|
|
54
54
|
sessionsToProcess.push(forkedSession);
|
|
55
55
|
}
|
|
56
56
|
}
|
|
@@ -80,7 +80,7 @@ function createInitialSession(workflow) {
|
|
|
80
80
|
action_states: new Map(),
|
|
81
81
|
};
|
|
82
82
|
}
|
|
83
|
-
function forkSessionForBranching(session, branchInfo, chosenValue) {
|
|
83
|
+
function forkSessionForBranching(session, branchInfo, chosenValue, workflow) {
|
|
84
84
|
// Deep copy session
|
|
85
85
|
const forked = {
|
|
86
86
|
completed_actions: [...session.completed_actions],
|
|
@@ -102,8 +102,11 @@ function forkSessionForBranching(session, branchInfo, chosenValue) {
|
|
|
102
102
|
node_id: branchInfo.action_that_branched,
|
|
103
103
|
output_name: branchInfo.branching_output_name,
|
|
104
104
|
});
|
|
105
|
-
//
|
|
106
|
-
|
|
105
|
+
// Add remaining outputs from the branching action (e.g. categorizer also produces confidence)
|
|
106
|
+
const branchingNode = workflow.nodes?.find(n => n.id === branchInfo.action_that_branched);
|
|
107
|
+
if (branchingNode) {
|
|
108
|
+
addActionOutputs(forked, branchingNode);
|
|
109
|
+
}
|
|
107
110
|
return forked;
|
|
108
111
|
}
|
|
109
112
|
// ─────────────────────────────────────────────────────────────────────────────
|
package/dist/mcp/guidance.js
CHANGED
|
@@ -231,7 +231,7 @@ persona({ id: "abc", env: "prod" }) // production`,
|
|
|
231
231
|
export const TOOL_GUIDANCE = {
|
|
232
232
|
persona: {
|
|
233
233
|
toolName: "persona",
|
|
234
|
-
quickTip: "Use
|
|
234
|
+
quickTip: "Use workflow(mode='get') to understand the workflow before modifying. Use preview=true before deploying.",
|
|
235
235
|
operations: [
|
|
236
236
|
{
|
|
237
237
|
name: "List all",
|
|
@@ -243,11 +243,6 @@ export const TOOL_GUIDANCE = {
|
|
|
243
243
|
description: "Get details for a specific persona",
|
|
244
244
|
example: 'persona(id="abc")',
|
|
245
245
|
},
|
|
246
|
-
{
|
|
247
|
-
name: "Analyze",
|
|
248
|
-
description: "Get workflow_spec, issues, and fix suggestions",
|
|
249
|
-
example: 'persona(id="abc", analyze=true)',
|
|
250
|
-
},
|
|
251
246
|
{
|
|
252
247
|
name: "Update config",
|
|
253
248
|
description: "Update persona config (name, description, widgets)",
|
|
@@ -371,6 +366,51 @@ export const TOOL_GUIDANCE = {
|
|
|
371
366
|
],
|
|
372
367
|
applicableRules: [],
|
|
373
368
|
},
|
|
369
|
+
debug: {
|
|
370
|
+
toolName: "debug",
|
|
371
|
+
quickTip: "Inspect workflow executions and audit conversations. Follow the drill-down: conversations → detail → show_work → action_detail.",
|
|
372
|
+
operations: [
|
|
373
|
+
{
|
|
374
|
+
name: "List conversations",
|
|
375
|
+
description: "List audit conversations for a persona",
|
|
376
|
+
example: 'debug(method="conversations", persona_id="abc")',
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
name: "Conversation detail",
|
|
380
|
+
description: "Get messages with workflow_run_ids",
|
|
381
|
+
example: 'debug(method="conversation_detail", conversation_id="...")',
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
name: "Show work",
|
|
385
|
+
description: "See all actions' execution traces for a workflow run",
|
|
386
|
+
example: 'debug(method="show_work", persona_id="abc", workflow_run_id="...")',
|
|
387
|
+
},
|
|
388
|
+
{
|
|
389
|
+
name: "Action detail",
|
|
390
|
+
description: "Deep trace: inputs, outputs, LLM calls, steps",
|
|
391
|
+
example: 'debug(method="action_detail", persona_id="abc", workflow_run_id="...", action_name="...")',
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
name: "Search messages",
|
|
395
|
+
description: "Full-text search across conversation messages",
|
|
396
|
+
example: 'debug(method="search", persona_id="abc", query="pricing")',
|
|
397
|
+
},
|
|
398
|
+
],
|
|
399
|
+
nextSteps: {
|
|
400
|
+
conversations: "Pick a conversation_id → debug(method='conversation_detail')",
|
|
401
|
+
conversation_detail: "Pick a workflow_run_id → debug(method='show_work', persona_id='...', workflow_run_id='...')",
|
|
402
|
+
show_work: "Pick an action_name (especially ERRORED ones) → debug(method='action_detail', persona_id='...', ...)",
|
|
403
|
+
action_detail: "Examine inputs/outputs/llm_calls to find the root cause",
|
|
404
|
+
search: "Pick a conversation_id from results → debug(method='conversation_detail')",
|
|
405
|
+
},
|
|
406
|
+
commonMistakes: [
|
|
407
|
+
"Jumping to action_detail without running show_work first (you need the action_name)",
|
|
408
|
+
"Forgetting persona_id — required for conversations, show_work, action_detail, and search",
|
|
409
|
+
"Not following _next_step hints in responses",
|
|
410
|
+
"The search method depends on DebuggerService which may not be deployed in all environments",
|
|
411
|
+
],
|
|
412
|
+
applicableRules: [],
|
|
413
|
+
},
|
|
374
414
|
};
|
|
375
415
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
376
416
|
// Contextual Tips (for tool responses)
|
|
@@ -383,19 +423,13 @@ export const CONTEXTUAL_TIPS = [
|
|
|
383
423
|
suggestedAction: "persona(id='<id>')",
|
|
384
424
|
level: "info",
|
|
385
425
|
},
|
|
386
|
-
// After getting persona
|
|
426
|
+
// After getting persona — suggest workflow get for understanding
|
|
387
427
|
{
|
|
388
|
-
condition: "operation === 'get'
|
|
389
|
-
message: "
|
|
390
|
-
suggestedAction: "
|
|
428
|
+
condition: "operation === 'get'",
|
|
429
|
+
message: "Use workflow(mode='get') to understand the workflow before making changes",
|
|
430
|
+
suggestedAction: "workflow(mode='get', persona_id='...')",
|
|
391
431
|
level: "info",
|
|
392
432
|
},
|
|
393
|
-
// After analysis shows issues
|
|
394
|
-
{
|
|
395
|
-
condition: "operation === 'analyze' && result.issues?.length > 0",
|
|
396
|
-
message: `Found ${"{result.issues.length}"} issues. Review and build workflow_spec to fix.`,
|
|
397
|
-
level: "warning",
|
|
398
|
-
},
|
|
399
433
|
// Update without preview
|
|
400
434
|
{
|
|
401
435
|
condition: "operation === 'update' && !args.preview && result.success",
|
|
@@ -426,7 +460,7 @@ export function generateServerInstructions(buildInfo) {
|
|
|
426
460
|
|
|
427
461
|
## Workflow Pattern
|
|
428
462
|
1. **Discover**: persona() to list AI Employees
|
|
429
|
-
2. **Understand**:
|
|
463
|
+
2. **Understand**: workflow(mode="get", persona_id="...") before any changes
|
|
430
464
|
3. **Preview**: Always use preview=true before deploying
|
|
431
465
|
4. **Deploy**: Only after reviewing preview
|
|
432
466
|
|
|
@@ -445,8 +479,16 @@ All workflow modifications follow a 3-step flow:
|
|
|
445
479
|
|
|
446
480
|
The LLM generates the full workflow_def. MCP provides data and executes.
|
|
447
481
|
|
|
482
|
+
## Debugging Workflow Executions
|
|
483
|
+
Use the \`debug\` tool to inspect workflow runs and troubleshoot issues:
|
|
484
|
+
1. \`debug(method="conversations", persona_id="...")\` → list audit conversations
|
|
485
|
+
2. \`debug(method="show_work", workflow_run_id="...")\` → see action execution traces
|
|
486
|
+
3. \`debug(method="action_detail", ...)\` → deep trace with LLM calls, inputs/outputs
|
|
487
|
+
Also available as persona sub-resource: \`persona(id="abc", debug={method:"conversations"})\`
|
|
488
|
+
|
|
448
489
|
## Resources
|
|
449
490
|
- \`ema://docs/usage-guide\` - Complete guide
|
|
491
|
+
- \`ema://docs/debugging-guide\` - Debugging workflow executions
|
|
450
492
|
- \`ema://catalog/agents-summary\` - Action catalog
|
|
451
493
|
- \`ema://rules/anti-patterns\` - Common mistakes
|
|
452
494
|
|
|
@@ -599,22 +641,13 @@ export function getContextualTip(context) {
|
|
|
599
641
|
level: "info",
|
|
600
642
|
};
|
|
601
643
|
}
|
|
602
|
-
if (operation === "get"
|
|
644
|
+
if (operation === "get") {
|
|
603
645
|
return {
|
|
604
|
-
message: "
|
|
605
|
-
suggestedAction: "
|
|
646
|
+
message: "Use workflow(mode='get') to understand the workflow before making changes",
|
|
647
|
+
suggestedAction: "workflow(mode='get', persona_id='...')",
|
|
606
648
|
level: "info",
|
|
607
649
|
};
|
|
608
650
|
}
|
|
609
|
-
if (operation === "analyze" && Array.isArray(result.issues)) {
|
|
610
|
-
const issues = result.issues;
|
|
611
|
-
if (issues.length > 0) {
|
|
612
|
-
return {
|
|
613
|
-
message: `Found ${issues.length} issues. Review and build workflow_spec to fix.`,
|
|
614
|
-
level: "warning",
|
|
615
|
-
};
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
651
|
if (operation === "update" && !args.preview) {
|
|
619
652
|
return {
|
|
620
653
|
message: "Changes deployed. Consider using preview=true next time.",
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debug Adapter
|
|
3
|
+
*
|
|
4
|
+
* Thin adapter that resolves client from env and delegates to handleDebug.
|
|
5
|
+
* Same pattern as workflow/adapter.ts.
|
|
6
|
+
*
|
|
7
|
+
* Extracted from server.ts to keep the dispatch table thin.
|
|
8
|
+
*/
|
|
9
|
+
import { handleDebug } from "./index.js";
|
|
10
|
+
export async function handleDebugAdapter(args, createClient, getDefaultEnvName) {
|
|
11
|
+
const targetEnv = args.env ?? getDefaultEnvName();
|
|
12
|
+
// createClient() returns EmaClientAdapter at runtime (see env/config.ts)
|
|
13
|
+
const client = createClient(targetEnv);
|
|
14
|
+
return handleDebug(args, client);
|
|
15
|
+
}
|