@ema.co/mcp-toolkit 2026.2.13 → 2026.2.23-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.
- 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/api-client/client/client.gen.js +3 -3
- package/dist/sdk/generated/api-client/client/index.js +5 -5
- package/dist/sdk/generated/api-client/client/utils.gen.js +4 -4
- package/dist/sdk/generated/api-client/client.gen.js +1 -1
- package/dist/sdk/generated/api-client/core/utils.gen.js +1 -1
- package/dist/sdk/generated/api-client/index.js +1 -1
- package/dist/sdk/generated/api-client/sdk.gen.js +2 -2
- 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 +4 -3
- 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
|
@@ -1,349 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Dashboard Operations"
|
|
3
|
-
date: 2026-01-27
|
|
4
|
-
audience: public
|
|
5
|
-
---
|
|
6
|
-
# Dashboard Operations
|
|
7
|
-
|
|
8
|
-
## Overview
|
|
9
|
-
|
|
10
|
-
Dashboard-type AI Employees process data in batches. Each row in a dashboard represents one execution of the workflow with specific inputs.
|
|
11
|
-
|
|
12
|
-
## Architecture
|
|
13
|
-
|
|
14
|
-
```
|
|
15
|
-
┌─────────────────────────────────────────────────────────────────┐
|
|
16
|
-
│ Dashboard Persona │
|
|
17
|
-
├─────────────────────────────────────────────────────────────────┤
|
|
18
|
-
│ workflow_dashboard_id: "dashboard-uuid" │
|
|
19
|
-
│ trigger_type: DOCUMENT_TRIGGER │
|
|
20
|
-
└─────────────────────────────────────────────────────────────────┘
|
|
21
|
-
│
|
|
22
|
-
▼
|
|
23
|
-
┌─────────────────────────────────────────────────────────────────┐
|
|
24
|
-
│ Dashboard │
|
|
25
|
-
├────────────┬──────────────┬─────────────┬──────────────────────┤
|
|
26
|
-
│ Schema │ Input Cols │ Output Cols │ Rows │
|
|
27
|
-
├────────────┼──────────────┼─────────────┼──────────────────────┤
|
|
28
|
-
│ columnId │ name, type │ name, type │ id, state, values │
|
|
29
|
-
└────────────┴──────────────┴─────────────┴──────────────────────┘
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
## SDK Methods
|
|
33
|
-
|
|
34
|
-
| Method | Purpose | Key Parameters |
|
|
35
|
-
|--------|---------|----------------|
|
|
36
|
-
| `getDashboardRows()` | List rows with schema | `dashboardId`, `personaId`, `{ limit }` |
|
|
37
|
-
| `getDashboardRowResult()` | Get single row | `personaId`, `rowId`, `includeFileContents?` |
|
|
38
|
-
| `uploadAndRunDashboardRow()` | Create new row | `personaId`, `inputs[]` |
|
|
39
|
-
| `rerunDashboardRow()` | Re-execute workflow | `personaId`, `rowId` |
|
|
40
|
-
|
|
41
|
-
### Input Types (DashboardInput)
|
|
42
|
-
|
|
43
|
-
```typescript
|
|
44
|
-
type DashboardInput = {
|
|
45
|
-
name: string; // Column name (required)
|
|
46
|
-
string_value?: string; // Text input
|
|
47
|
-
number_value?: number; // Numeric input
|
|
48
|
-
boolean_value?: boolean; // Boolean input
|
|
49
|
-
document_value?: Array<{ // File input
|
|
50
|
-
name: string; // Filename
|
|
51
|
-
contents: string; // Base64-encoded content
|
|
52
|
-
is_base64_encoded: boolean; // Always true for documents
|
|
53
|
-
mime_type: string; // e.g., "application/pdf"
|
|
54
|
-
}>;
|
|
55
|
-
};
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
## MCP Tool: Data Operations
|
|
59
|
-
|
|
60
|
-
### Purpose
|
|
61
|
-
Clone rows from one dashboard persona to another. Useful for:
|
|
62
|
-
- Creating demo environments with real data structure
|
|
63
|
-
- Testing with sanitized production data
|
|
64
|
-
- Duplicating configurations across personas
|
|
65
|
-
|
|
66
|
-
### Recommended: Action Composition
|
|
67
|
-
|
|
68
|
-
Use the `actions` array when creating/cloning personas:
|
|
69
|
-
|
|
70
|
-
```typescript
|
|
71
|
-
// Clone persona with data copy and sanitization
|
|
72
|
-
persona(
|
|
73
|
-
method="create",
|
|
74
|
-
from="source-persona-uuid",
|
|
75
|
-
name="Demo Dashboard",
|
|
76
|
-
actions=[
|
|
77
|
-
{tool:"data", args:{method:"copy", from:"$source"}},
|
|
78
|
-
{tool:"data", args:{method:"sanitize", examples:["john@acme.com", "Acme Corp"]}},
|
|
79
|
-
]
|
|
80
|
-
)
|
|
81
|
-
|
|
82
|
-
// Or use built-in alias
|
|
83
|
-
persona(method="create", from="source-persona-uuid", name="Demo Dashboard", actions=["copy-and-sanitize"])
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
### Direct Data Operations
|
|
87
|
-
|
|
88
|
-
For operations on existing personas, use the `data` sub-resource:
|
|
89
|
-
|
|
90
|
-
```typescript
|
|
91
|
-
// Copy data from another persona
|
|
92
|
-
persona(id="target-persona-uuid", data={method:"copy", from:"source-persona-uuid", sanitize:true})
|
|
93
|
-
|
|
94
|
-
// List data items
|
|
95
|
-
persona(id="persona-uuid", data={method:"list"})
|
|
96
|
-
|
|
97
|
-
// Get input schema
|
|
98
|
-
persona(id="persona-uuid", data={method:"schema"})
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
### Upload Dashboard Rows with Files
|
|
102
|
-
|
|
103
|
-
Create new dashboard rows with file attachments (triggers workflow execution):
|
|
104
|
-
|
|
105
|
-
```javascript
|
|
106
|
-
persona(id="dashboard-uuid", data={
|
|
107
|
-
method: "upload",
|
|
108
|
-
items: [
|
|
109
|
-
{
|
|
110
|
-
"Input Document": { file: "/path/to/invoice.pdf" },
|
|
111
|
-
"Customer Name": "Acme Corp",
|
|
112
|
-
"Amount": 1500.00,
|
|
113
|
-
"Priority": true
|
|
114
|
-
}
|
|
115
|
-
]
|
|
116
|
-
})
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
**Supported value types in `items`:**
|
|
120
|
-
|
|
121
|
-
| Type | Format | Result |
|
|
122
|
-
|------|--------|--------|
|
|
123
|
-
| String | `"value"` | `string_value` |
|
|
124
|
-
| Number | `123.45` | `number_value` |
|
|
125
|
-
| Boolean | `true` | `boolean_value` |
|
|
126
|
-
| File | `{ file: "/path/to/doc.pdf" }` | `document_value` (auto base64) |
|
|
127
|
-
| Inline Doc | `{ contents: "...", mime_type: "text/plain" }` | `document_value` |
|
|
128
|
-
|
|
129
|
-
**Key differences from knowledge base upload:**
|
|
130
|
-
|
|
131
|
-
| Operation | Target | Use Case |
|
|
132
|
-
|-----------|--------|----------|
|
|
133
|
-
| `data={method:"upload", path:"..."}` | Knowledge Base | Chat personas, RAG search |
|
|
134
|
-
| `data={method:"upload", items:[...]}` | Dashboard Rows | Dashboard personas, per-row workflow |
|
|
135
|
-
|
|
136
|
-
### Legacy Syntax (still works)
|
|
137
|
-
|
|
138
|
-
```
|
|
139
|
-
knowledge(
|
|
140
|
-
persona_id="target-persona-uuid",
|
|
141
|
-
source_persona_id="source-persona-uuid",
|
|
142
|
-
mode="dashboard_clone",
|
|
143
|
-
sanitize=true,
|
|
144
|
-
sanitize_examples=["john@acme.com", "Acme Corp"]
|
|
145
|
-
)
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
### Response
|
|
149
|
-
|
|
150
|
-
```json
|
|
151
|
-
{
|
|
152
|
-
"success": true,
|
|
153
|
-
"source_persona": "Source Dashboard",
|
|
154
|
-
"target_persona": "Target Dashboard",
|
|
155
|
-
"cloned_count": 5,
|
|
156
|
-
"skipped_count": 0,
|
|
157
|
-
"details": [
|
|
158
|
-
{
|
|
159
|
-
"source_row_id": "row-1",
|
|
160
|
-
"target_row_id": "new-row-1",
|
|
161
|
-
"status": "cloned"
|
|
162
|
-
}
|
|
163
|
-
],
|
|
164
|
-
"notes": [
|
|
165
|
-
"Dashboard clone creates NEW rows in the target dashboard",
|
|
166
|
-
"Workflows will re-run on the new rows to generate output columns"
|
|
167
|
-
]
|
|
168
|
-
}
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
## Document Handling
|
|
172
|
-
|
|
173
|
-
### How Document Cloning Works
|
|
174
|
-
|
|
175
|
-
1. **Fetch source row** with file contents:
|
|
176
|
-
```typescript
|
|
177
|
-
const rowResult = await client.getDashboardRowResult(
|
|
178
|
-
sourcePersonaId,
|
|
179
|
-
rowId,
|
|
180
|
-
true // includeFileContents
|
|
181
|
-
);
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
2. **Extract file content** from `additional_column_details`:
|
|
185
|
-
```typescript
|
|
186
|
-
const fileContent = rowResult.additional_column_details?.find(
|
|
187
|
-
d => d.column_id === columnId
|
|
188
|
-
)?.file_contents; // Base64 encoded
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
3. **Build document input** for target:
|
|
192
|
-
```typescript
|
|
193
|
-
const input: DashboardInput = {
|
|
194
|
-
name: "Document Input",
|
|
195
|
-
document_value: [{
|
|
196
|
-
name: "filename.pdf",
|
|
197
|
-
contents: fileContent,
|
|
198
|
-
is_base64_encoded: true,
|
|
199
|
-
mime_type: "application/pdf",
|
|
200
|
-
}],
|
|
201
|
-
};
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
4. **Upload to target dashboard**:
|
|
205
|
-
```typescript
|
|
206
|
-
await client.uploadAndRunDashboardRow(targetPersonaId, [input]);
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
### MIME Type Inference
|
|
210
|
-
|
|
211
|
-
When document `type` is not available, inferred from extension:
|
|
212
|
-
|
|
213
|
-
| Extension | MIME Type |
|
|
214
|
-
|-----------|-----------|
|
|
215
|
-
| `.pdf` | `application/pdf` |
|
|
216
|
-
| `.docx` | `application/vnd.openxmlformats-officedocument.wordprocessingml.document` |
|
|
217
|
-
| `.xlsx` | `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` |
|
|
218
|
-
| `.csv` | `text/csv` |
|
|
219
|
-
| `.txt` | `text/plain` |
|
|
220
|
-
| `.png` | `image/png` |
|
|
221
|
-
| `.jpg`/`.jpeg` | `image/jpeg` |
|
|
222
|
-
| Other | `application/octet-stream` |
|
|
223
|
-
|
|
224
|
-
## Dashboard Columns: How They Work
|
|
225
|
-
|
|
226
|
-
### Output Columns Come From resultMappings
|
|
227
|
-
|
|
228
|
-
For dashboard personas, the **output columns** visible in the dashboard UI are determined **entirely** by which node outputs are mapped to `WORKFLOW_OUTPUT` via `resultMappings` in the workflow_def. Each `resultMapping` entry creates one output column in the dashboard.
|
|
229
|
-
|
|
230
|
-
```json
|
|
231
|
-
"results": {
|
|
232
|
-
"entity_extraction.invoice_number": {
|
|
233
|
-
"actionName": "entity_extraction",
|
|
234
|
-
"outputName": "invoice_number"
|
|
235
|
-
},
|
|
236
|
-
"entity_extraction.amount": {
|
|
237
|
-
"actionName": "entity_extraction",
|
|
238
|
-
"outputName": "amount"
|
|
239
|
-
},
|
|
240
|
-
"call_llm.summary": {
|
|
241
|
-
"actionName": "call_llm",
|
|
242
|
-
"outputName": "response_with_sources"
|
|
243
|
-
},
|
|
244
|
-
"categorizer.category": {
|
|
245
|
-
"actionName": "categorizer",
|
|
246
|
-
"outputName": "category"
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
This creates 4 output columns: `entity_extraction.invoice_number`, `entity_extraction.amount`, `call_llm.summary`, and `categorizer.category`.
|
|
252
|
-
|
|
253
|
-
**Key rules:**
|
|
254
|
-
- If you forget to map a node output, that column **won't appear** in the dashboard
|
|
255
|
-
- If you map the wrong output, you'll see unexpected data
|
|
256
|
-
- Column display name in the UI = the result mapping key (e.g., `entity_extraction.invoice_number`)
|
|
257
|
-
|
|
258
|
-
### Input Columns Come From the Trigger
|
|
259
|
-
|
|
260
|
-
Dashboard input columns (what users fill in or upload per row) come from the `document_trigger` outputs:
|
|
261
|
-
- `document_content`: For uploaded files (PDF, images, etc.)
|
|
262
|
-
- `row_data`: For text/number inputs from dashboard columns
|
|
263
|
-
|
|
264
|
-
Wire these to your processing nodes:
|
|
265
|
-
- `entity_extraction.document` ← `trigger.document_content`
|
|
266
|
-
- `call_llm.context` ← `trigger.row_data`
|
|
267
|
-
|
|
268
|
-
### Column Ordering
|
|
269
|
-
|
|
270
|
-
**Dashboard column order is determined by the order of resultMappings in the workflow_def.**
|
|
271
|
-
|
|
272
|
-
To reorder columns, you must **remove** them from the result mappings and **re-add** them in the desired order. There is no separate "reorder" API -- the order in the JSON is the order in the UI.
|
|
273
|
-
|
|
274
|
-
```
|
|
275
|
-
// To change order from [Amount, Date, Status] to [Status, Date, Amount]:
|
|
276
|
-
// 1. Remove all three from results
|
|
277
|
-
// 2. Re-add in desired order:
|
|
278
|
-
"results": {
|
|
279
|
-
"extract.status": { "actionName": "extract", "outputName": "status" },
|
|
280
|
-
"extract.date": { "actionName": "extract", "outputName": "date" },
|
|
281
|
-
"extract.amount": { "actionName": "extract", "outputName": "amount" }
|
|
282
|
-
}
|
|
283
|
-
```
|
|
284
|
-
|
|
285
|
-
**Important:** Once columns are created and saved, the output type and multi-value settings cannot be modified via the UI. To change these, you must update the workflow_def directly.
|
|
286
|
-
|
|
287
|
-
## Common Patterns
|
|
288
|
-
|
|
289
|
-
### List Dashboard Rows
|
|
290
|
-
|
|
291
|
-
```
|
|
292
|
-
knowledge(persona_id="...", mode="dashboard_rows", limit=10)
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
### Clone with Sanitization
|
|
296
|
-
|
|
297
|
-
**Recommended (action composition):**
|
|
298
|
-
|
|
299
|
-
```typescript
|
|
300
|
-
persona(
|
|
301
|
-
method="create",
|
|
302
|
-
from="source",
|
|
303
|
-
name="Demo Dashboard",
|
|
304
|
-
actions=[
|
|
305
|
-
{tool:"data", args:{method:"copy", from:"$source"}},
|
|
306
|
-
{tool:"data", args:{method:"sanitize", examples:["real-email@company.com", "Real Company Name"]}},
|
|
307
|
-
]
|
|
308
|
-
)
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
**Legacy syntax (still works):**
|
|
312
|
-
|
|
313
|
-
```
|
|
314
|
-
knowledge(
|
|
315
|
-
persona_id="target",
|
|
316
|
-
source_persona_id="source",
|
|
317
|
-
mode="dashboard_clone",
|
|
318
|
-
sanitize=true,
|
|
319
|
-
sanitize_examples=["real-email@company.com", "Real Company Name"]
|
|
320
|
-
)
|
|
321
|
-
```
|
|
322
|
-
|
|
323
|
-
### Manual Row Upload
|
|
324
|
-
|
|
325
|
-
Use `uploadAndRunDashboardRow` directly for programmatic row creation:
|
|
326
|
-
|
|
327
|
-
```typescript
|
|
328
|
-
await client.uploadAndRunDashboardRow(personaId, [
|
|
329
|
-
{ name: "Input Column", string_value: "test data" },
|
|
330
|
-
{ name: "Document Column", document_value: [...] },
|
|
331
|
-
]);
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
## Error Handling
|
|
335
|
-
|
|
336
|
-
| Error | Cause | Solution |
|
|
337
|
-
|-------|-------|----------|
|
|
338
|
-
| "Persona has no dashboard" | Wrong persona type | Use only with DOCUMENT_TRIGGER personas |
|
|
339
|
-
| "Document content not available" | `includeFileContents` returned empty | Source document may have been deleted |
|
|
340
|
-
| "Source persona not found" | Invalid `source_persona_id` | Verify persona exists in environment |
|
|
341
|
-
|
|
342
|
-
## Related Files
|
|
343
|
-
|
|
344
|
-
| File | Purpose |
|
|
345
|
-
|------|---------|
|
|
346
|
-
| `src/sdk/client.ts` | SDK methods for dashboard operations |
|
|
347
|
-
| `src/mcp/handlers-consolidated.ts` | MCP handlers (dashboard_rows, dashboard_clone) |
|
|
348
|
-
| `test/integration/dashboard-clone.integration.test.ts` | Integration tests |
|
|
349
|
-
| `test/handlers-consolidated.test.ts` | Unit tests for cloning logic |
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Email Field Extraction Patterns"
|
|
3
|
-
date: 2026-01-27
|
|
4
|
-
audience: public
|
|
5
|
-
---
|
|
6
|
-
# Email Field Extraction Patterns
|
|
7
|
-
|
|
8
|
-
## Problem
|
|
9
|
-
|
|
10
|
-
`send_email_agent.to_email` expects a text email address, but `entity_extraction` outputs `extraction_columns` (a JSON object), not individual fields.
|
|
11
|
-
|
|
12
|
-
**This does NOT work:**
|
|
13
|
-
```
|
|
14
|
-
entity_extraction.extraction_columns → send_email.to_email
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
The types are incompatible:
|
|
18
|
-
- `extraction_columns` = `WELL_KNOWN_TYPE_ANY` (JSON object)
|
|
19
|
-
- `to_email` = `WELL_KNOWN_TYPE_TEXT_WITH_SOURCES` (text)
|
|
20
|
-
|
|
21
|
-
## Solution Pattern
|
|
22
|
-
|
|
23
|
-
```
|
|
24
|
-
entity_extraction.extraction_columns
|
|
25
|
-
→ fixed_response (template: "{{email}}")
|
|
26
|
-
→ send_email.to_email
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
### Why This Works
|
|
30
|
-
|
|
31
|
-
1. `entity_extraction` extracts structured data into JSON: `{"email": "user@example.com", "name": "John"}`
|
|
32
|
-
2. `fixed_response` with `{{email}}` template extracts the field and outputs plain text
|
|
33
|
-
3. `fixed_response` output type is `WELL_KNOWN_TYPE_TEXT_WITH_SOURCES` - compatible with `to_email`
|
|
34
|
-
|
|
35
|
-
### WorkflowSpec Example
|
|
36
|
-
|
|
37
|
-
```typescript
|
|
38
|
-
{
|
|
39
|
-
nodes: [
|
|
40
|
-
{
|
|
41
|
-
id: "extract_entities_abc123",
|
|
42
|
-
actionType: "entity_extraction_with_documents",
|
|
43
|
-
displayName: "Extract Contact Info",
|
|
44
|
-
// outputs: extraction_columns (JSON)
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
id: "format_email_def456",
|
|
48
|
-
actionType: "fixed_response",
|
|
49
|
-
displayName: "Format Email Address",
|
|
50
|
-
inputs: {
|
|
51
|
-
query: {
|
|
52
|
-
type: "action_output",
|
|
53
|
-
actionName: "extract_entities_abc123",
|
|
54
|
-
output: "extraction_columns"
|
|
55
|
-
}
|
|
56
|
-
},
|
|
57
|
-
config: {
|
|
58
|
-
response_template: "{{email}}" // Extracts email field
|
|
59
|
-
}
|
|
60
|
-
// outputs: response (text)
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
id: "send_email_ghi789",
|
|
64
|
-
actionType: "send_email_agent",
|
|
65
|
-
displayName: "Send Email",
|
|
66
|
-
inputs: {
|
|
67
|
-
to_email: {
|
|
68
|
-
type: "action_output",
|
|
69
|
-
actionName: "format_email_def456",
|
|
70
|
-
output: "response"
|
|
71
|
-
},
|
|
72
|
-
// ... other inputs
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
]
|
|
76
|
-
}
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
## Alternative: JSON Mapper
|
|
80
|
-
|
|
81
|
-
For complex extraction or multiple fields:
|
|
82
|
-
|
|
83
|
-
```
|
|
84
|
-
entity_extraction.extraction_columns
|
|
85
|
-
→ json_mapper (extracts specific fields)
|
|
86
|
-
→ fixed_response (formats as text)
|
|
87
|
-
→ send_email.to_email
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
**Note:** `json_mapper` is not in the WorkflowSpec compiler's supported action types. Use `applySpecToWorkflow()` for workflows containing `json_mapper`.
|
|
91
|
-
|
|
92
|
-
## Common Mistakes
|
|
93
|
-
|
|
94
|
-
### 1. Direct Wiring
|
|
95
|
-
```
|
|
96
|
-
❌ entity_extraction → send_email.to_email
|
|
97
|
-
```
|
|
98
|
-
Type mismatch. JSON object cannot be used as email address.
|
|
99
|
-
|
|
100
|
-
### 2. Assuming `.email_address` Output Exists
|
|
101
|
-
```
|
|
102
|
-
❌ entity_extraction.email_address → send_email.to_email
|
|
103
|
-
```
|
|
104
|
-
This output doesn't exist. `entity_extraction` only outputs `extraction_columns`.
|
|
105
|
-
|
|
106
|
-
### 3. Skipping Template Step
|
|
107
|
-
```
|
|
108
|
-
❌ entity_extraction → json_mapper → send_email.to_email
|
|
109
|
-
```
|
|
110
|
-
Even `json_mapper` output may not be the right type. Always use `fixed_response` as the final step before `send_email` inputs.
|
|
111
|
-
|
|
112
|
-
## Type Reference
|
|
113
|
-
|
|
114
|
-
| Action | Output | Type |
|
|
115
|
-
|--------|--------|------|
|
|
116
|
-
| `entity_extraction` | `extraction_columns` | `WELL_KNOWN_TYPE_ANY` (JSON) |
|
|
117
|
-
| `json_mapper` | varies | depends on mapping |
|
|
118
|
-
| `fixed_response` | `response` | `WELL_KNOWN_TYPE_TEXT_WITH_SOURCES` |
|
|
119
|
-
| `call_llm` | `response` | `WELL_KNOWN_TYPE_TEXT_WITH_SOURCES` |
|
|
120
|
-
|
|
121
|
-
| Input | Expected Type |
|
|
122
|
-
|-------|---------------|
|
|
123
|
-
| `send_email.to_email` | `WELL_KNOWN_TYPE_TEXT_WITH_SOURCES` |
|
|
124
|
-
| `send_email.subject` | `WELL_KNOWN_TYPE_TEXT_WITH_SOURCES` |
|
|
125
|
-
| `send_email.body` | `WELL_KNOWN_TYPE_TEXT_WITH_SOURCES` |
|