@hailer/mcp 0.0.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.
Files changed (163) hide show
  1. package/.claude/commands/tool-builder.md +37 -0
  2. package/.claude/commands/ws-pull.md +44 -0
  3. package/.claude/settings.json +8 -0
  4. package/.claude/settings.local.json +49 -0
  5. package/.claude/skills/activity-api/SKILL.md +96 -0
  6. package/.claude/skills/activity-api/references/activity-endpoints.md +845 -0
  7. package/.claude/skills/add-app-member-skill/SKILL.md +977 -0
  8. package/.claude/skills/agent-building/SKILL.md +243 -0
  9. package/.claude/skills/agent-building/references/architecture-patterns.md +446 -0
  10. package/.claude/skills/agent-building/references/code-examples.md +587 -0
  11. package/.claude/skills/agent-building/references/implementation-guide.md +619 -0
  12. package/.claude/skills/app-api/SKILL.md +219 -0
  13. package/.claude/skills/app-api/references/app-endpoints.md +759 -0
  14. package/.claude/skills/building-hailer-apps-skill/SKILL.md +548 -0
  15. package/.claude/skills/create-app-skill/SKILL.md +1101 -0
  16. package/.claude/skills/create-insight-skill/SKILL.md +1317 -0
  17. package/.claude/skills/get-insight-data-skill/SKILL.md +1053 -0
  18. package/.claude/skills/hailer-api/SKILL.md +283 -0
  19. package/.claude/skills/hailer-api/references/activities.md +620 -0
  20. package/.claude/skills/hailer-api/references/authentication.md +216 -0
  21. package/.claude/skills/hailer-api/references/datasets.md +437 -0
  22. package/.claude/skills/hailer-api/references/files.md +301 -0
  23. package/.claude/skills/hailer-api/references/insights.md +469 -0
  24. package/.claude/skills/hailer-api/references/workflows.md +720 -0
  25. package/.claude/skills/hailer-api/references/workspaces-users.md +445 -0
  26. package/.claude/skills/insight-api/SKILL.md +185 -0
  27. package/.claude/skills/insight-api/references/insight-endpoints.md +514 -0
  28. package/.claude/skills/install-workflow-skill/SKILL.md +1056 -0
  29. package/.claude/skills/list-apps-skill/SKILL.md +1010 -0
  30. package/.claude/skills/list-workflows-minimal-skill/SKILL.md +992 -0
  31. package/.claude/skills/local-first-skill/SKILL.md +570 -0
  32. package/.claude/skills/mcp-tools/SKILL.md +419 -0
  33. package/.claude/skills/mcp-tools/references/api-endpoints.md +499 -0
  34. package/.claude/skills/mcp-tools/references/data-structures.md +554 -0
  35. package/.claude/skills/mcp-tools/references/implementation-patterns.md +717 -0
  36. package/.claude/skills/preview-insight-skill/SKILL.md +1290 -0
  37. package/.claude/skills/publish-hailer-app-skill/SKILL.md +453 -0
  38. package/.claude/skills/remove-app-member-skill/SKILL.md +671 -0
  39. package/.claude/skills/remove-app-skill/SKILL.md +985 -0
  40. package/.claude/skills/remove-insight-skill/SKILL.md +1011 -0
  41. package/.claude/skills/remove-workflow-skill/SKILL.md +920 -0
  42. package/.claude/skills/scaffold-hailer-app-skill/SKILL.md +1034 -0
  43. package/.claude/skills/skill-testing/README.md +137 -0
  44. package/.claude/skills/skill-testing/SKILL.md +348 -0
  45. package/.claude/skills/skill-testing/references/test-patterns.md +705 -0
  46. package/.claude/skills/skill-testing/references/testing-guide.md +603 -0
  47. package/.claude/skills/skill-testing/references/validation-checklist.md +537 -0
  48. package/.claude/skills/tool-builder/SKILL.md +328 -0
  49. package/.claude/skills/update-app-skill/SKILL.md +970 -0
  50. package/.claude/skills/update-workflow-field-skill/SKILL.md +1098 -0
  51. package/.env.example +81 -0
  52. package/.mcp.json +13 -0
  53. package/README.md +297 -0
  54. package/dist/app.d.ts +4 -0
  55. package/dist/app.js +74 -0
  56. package/dist/cli.d.ts +3 -0
  57. package/dist/cli.js +5 -0
  58. package/dist/client/adaptive-documentation-bot.d.ts +108 -0
  59. package/dist/client/adaptive-documentation-bot.js +475 -0
  60. package/dist/client/adaptive-documentation-types.d.ts +66 -0
  61. package/dist/client/adaptive-documentation-types.js +9 -0
  62. package/dist/client/agent-activity-bot.d.ts +51 -0
  63. package/dist/client/agent-activity-bot.js +166 -0
  64. package/dist/client/agent-tracker.d.ts +499 -0
  65. package/dist/client/agent-tracker.js +659 -0
  66. package/dist/client/description-updater.d.ts +56 -0
  67. package/dist/client/description-updater.js +259 -0
  68. package/dist/client/log-parser.d.ts +72 -0
  69. package/dist/client/log-parser.js +387 -0
  70. package/dist/client/mcp-client.d.ts +50 -0
  71. package/dist/client/mcp-client.js +532 -0
  72. package/dist/client/message-processor.d.ts +35 -0
  73. package/dist/client/message-processor.js +352 -0
  74. package/dist/client/multi-bot-manager.d.ts +24 -0
  75. package/dist/client/multi-bot-manager.js +74 -0
  76. package/dist/client/providers/anthropic-provider.d.ts +19 -0
  77. package/dist/client/providers/anthropic-provider.js +631 -0
  78. package/dist/client/providers/llm-provider.d.ts +47 -0
  79. package/dist/client/providers/llm-provider.js +367 -0
  80. package/dist/client/providers/openai-provider.d.ts +23 -0
  81. package/dist/client/providers/openai-provider.js +621 -0
  82. package/dist/client/simple-llm-caller.d.ts +19 -0
  83. package/dist/client/simple-llm-caller.js +100 -0
  84. package/dist/client/skill-generator.d.ts +81 -0
  85. package/dist/client/skill-generator.js +386 -0
  86. package/dist/client/test-adaptive-bot.d.ts +9 -0
  87. package/dist/client/test-adaptive-bot.js +82 -0
  88. package/dist/client/token-pricing.d.ts +38 -0
  89. package/dist/client/token-pricing.js +127 -0
  90. package/dist/client/token-tracker.d.ts +232 -0
  91. package/dist/client/token-tracker.js +457 -0
  92. package/dist/client/token-usage-bot.d.ts +53 -0
  93. package/dist/client/token-usage-bot.js +153 -0
  94. package/dist/client/tool-executor.d.ts +69 -0
  95. package/dist/client/tool-executor.js +159 -0
  96. package/dist/client/tool-schema-loader.d.ts +60 -0
  97. package/dist/client/tool-schema-loader.js +178 -0
  98. package/dist/client/types.d.ts +69 -0
  99. package/dist/client/types.js +7 -0
  100. package/dist/config.d.ts +162 -0
  101. package/dist/config.js +296 -0
  102. package/dist/core.d.ts +26 -0
  103. package/dist/core.js +147 -0
  104. package/dist/lib/context-manager.d.ts +111 -0
  105. package/dist/lib/context-manager.js +431 -0
  106. package/dist/lib/logger.d.ts +74 -0
  107. package/dist/lib/logger.js +277 -0
  108. package/dist/lib/materialize.d.ts +3 -0
  109. package/dist/lib/materialize.js +101 -0
  110. package/dist/lib/normalizedName.d.ts +7 -0
  111. package/dist/lib/normalizedName.js +48 -0
  112. package/dist/lib/prompt-length-manager.d.ts +81 -0
  113. package/dist/lib/prompt-length-manager.js +457 -0
  114. package/dist/lib/terminal-prompt.d.ts +9 -0
  115. package/dist/lib/terminal-prompt.js +108 -0
  116. package/dist/mcp/UserContextCache.d.ts +56 -0
  117. package/dist/mcp/UserContextCache.js +163 -0
  118. package/dist/mcp/auth.d.ts +2 -0
  119. package/dist/mcp/auth.js +29 -0
  120. package/dist/mcp/hailer-clients.d.ts +42 -0
  121. package/dist/mcp/hailer-clients.js +246 -0
  122. package/dist/mcp/signal-handler.d.ts +45 -0
  123. package/dist/mcp/signal-handler.js +317 -0
  124. package/dist/mcp/tool-registry.d.ts +100 -0
  125. package/dist/mcp/tool-registry.js +306 -0
  126. package/dist/mcp/tools/activity.d.ts +15 -0
  127. package/dist/mcp/tools/activity.js +955 -0
  128. package/dist/mcp/tools/app.d.ts +20 -0
  129. package/dist/mcp/tools/app.js +1488 -0
  130. package/dist/mcp/tools/discussion.d.ts +19 -0
  131. package/dist/mcp/tools/discussion.js +950 -0
  132. package/dist/mcp/tools/file.d.ts +15 -0
  133. package/dist/mcp/tools/file.js +119 -0
  134. package/dist/mcp/tools/insight.d.ts +17 -0
  135. package/dist/mcp/tools/insight.js +806 -0
  136. package/dist/mcp/tools/skill.d.ts +10 -0
  137. package/dist/mcp/tools/skill.js +279 -0
  138. package/dist/mcp/tools/user.d.ts +10 -0
  139. package/dist/mcp/tools/user.js +108 -0
  140. package/dist/mcp/tools/workflow-template.d.ts +19 -0
  141. package/dist/mcp/tools/workflow-template.js +822 -0
  142. package/dist/mcp/tools/workflow.d.ts +18 -0
  143. package/dist/mcp/tools/workflow.js +1362 -0
  144. package/dist/mcp/utils/api-errors.d.ts +45 -0
  145. package/dist/mcp/utils/api-errors.js +160 -0
  146. package/dist/mcp/utils/data-transformers.d.ts +102 -0
  147. package/dist/mcp/utils/data-transformers.js +194 -0
  148. package/dist/mcp/utils/file-upload.d.ts +33 -0
  149. package/dist/mcp/utils/file-upload.js +148 -0
  150. package/dist/mcp/utils/hailer-api-client.d.ts +120 -0
  151. package/dist/mcp/utils/hailer-api-client.js +323 -0
  152. package/dist/mcp/utils/index.d.ts +13 -0
  153. package/dist/mcp/utils/index.js +39 -0
  154. package/dist/mcp/utils/logger.d.ts +42 -0
  155. package/dist/mcp/utils/logger.js +103 -0
  156. package/dist/mcp/utils/types.d.ts +286 -0
  157. package/dist/mcp/utils/types.js +7 -0
  158. package/dist/mcp/workspace-cache.d.ts +42 -0
  159. package/dist/mcp/workspace-cache.js +97 -0
  160. package/dist/mcp-server.d.ts +42 -0
  161. package/dist/mcp-server.js +280 -0
  162. package/package.json +56 -0
  163. package/tsconfig.json +23 -0
@@ -0,0 +1,1317 @@
1
+ ---
2
+ name: Creating Hailer Insights
3
+ description: Complete guide for creating SQL-like insights over Hailer workflow data - use when building reports, analytics, or data queries
4
+ ---
5
+
6
+ # Creating Hailer Insights - Complete Guide
7
+
8
+ Complete reference for creating SQL-like insights that query Hailer workflow data using the `create_insight` MCP tool.
9
+
10
+ ## Table of Contents
11
+ 1. [Quick Reference](#quick-reference)
12
+ 2. [Overview](#overview)
13
+ 3. [Core Concepts](#core-concepts)
14
+ 4. [Meta Fields Reference](#meta-fields-reference)
15
+ 5. [Basic Examples](#basic-examples)
16
+ 6. [SQL Features](#sql-features)
17
+ 7. [Advanced Queries](#advanced-queries)
18
+ 8. [Joins and Relationships](#joins-and-relationships)
19
+ 9. [Aggregations and Grouping](#aggregations-and-grouping)
20
+ 10. [Best Practices](#best-practices)
21
+ 11. [Common Patterns](#common-patterns)
22
+ 12. [Troubleshooting](#troubleshooting)
23
+
24
+ ## Quick Reference
25
+
26
+ **Simple Report (Single Workflow):**
27
+
28
+ ```javascript
29
+ create_insight({
30
+ name: 'All Tasks Report',
31
+ sources: [{
32
+ name: 'tasks',
33
+ workflowId: 'workflow-id',
34
+ fields: [
35
+ { name: 'title', meta: 'name' },
36
+ { name: 'dueDate', fieldId: 'due-date-field-id' }
37
+ ]
38
+ }],
39
+ query: 'SELECT title, dueDate FROM tasks WHERE dueDate > "2024-01-01"'
40
+ })
41
+ ```
42
+
43
+ **Cross-Workflow Join:**
44
+
45
+ ```javascript
46
+ create_insight({
47
+ name: 'Tasks with Projects',
48
+ sources: [
49
+ {
50
+ name: 'tasks',
51
+ workflowId: 'tasks-workflow-id',
52
+ fields: [
53
+ { name: 'taskName', meta: 'name' },
54
+ { name: 'projectLink', fieldId: 'project-field-id' }
55
+ ]
56
+ },
57
+ {
58
+ name: 'projects',
59
+ workflowId: 'projects-workflow-id',
60
+ fields: [
61
+ { name: 'id', meta: '_id' },
62
+ { name: 'projectName', meta: 'name' }
63
+ ]
64
+ }
65
+ ],
66
+ query: `
67
+ SELECT tasks.taskName, projects.projectName
68
+ FROM tasks
69
+ LEFT JOIN projects ON tasks.projectLink = projects.id
70
+ `
71
+ })
72
+ ```
73
+
74
+ **Key Concepts:**
75
+ - Workflows = Database tables
76
+ - Activities = Rows
77
+ - Fields = Columns
78
+ - Insights = SELECT queries with JOINs
79
+ - Meta fields = Built-in activity properties
80
+
81
+ ## Overview
82
+
83
+ **What are Insights?**
84
+
85
+ Insights are SQL queries that run over your Hailer workflow data. They enable powerful reporting and analytics capabilities without writing custom code.
86
+
87
+ **Think of it as:**
88
+ - SQL SELECT queries on workflow data
89
+ - Virtual database views over Hailer
90
+ - Reports that update in real-time
91
+ - Cross-workflow analytics
92
+
93
+ **Common Uses:**
94
+ - Generate reports (tasks by status, projects by team)
95
+ - Analyze trends (activities created per month)
96
+ - Track metrics (completion rates, time to close)
97
+ - Cross-workflow summaries (tasks per project)
98
+ - Data exports for external tools
99
+
100
+ **Key Features:**
101
+ - Full SQL syntax support
102
+ - Cross-workflow JOINs
103
+ - Aggregations (COUNT, SUM, AVG, MIN, MAX)
104
+ - Filtering with WHERE clauses
105
+ - Sorting with ORDER BY
106
+ - Public/private access control
107
+
108
+ ## Core Concepts
109
+
110
+ ### Sources
111
+
112
+ **Sources define which workflows to query:**
113
+
114
+ ```javascript
115
+ sources: [{
116
+ name: 'tasks', // SQL table alias
117
+ workflowId: 'wf-id', // Which workflow to query
118
+ fields: [ // Field mappings
119
+ { name: 'title', meta: 'name' },
120
+ { name: 'priority', fieldId: 'field-id' }
121
+ ]
122
+ }]
123
+ ```
124
+
125
+ **Think of sources as:**
126
+ - Table definitions in SQL
127
+ - Each source = one workflow
128
+ - Fields = column mappings
129
+ - Name = table alias for queries
130
+
131
+ ### Field Mappings
132
+
133
+ **Two types of field mappings:**
134
+
135
+ **1. Meta Fields (Built-in):**
136
+ ```javascript
137
+ { name: 'title', meta: 'name' } // Activity name
138
+ { name: 'id', meta: '_id' } // Activity ID
139
+ { name: 'created', meta: 'created' } // Creation date
140
+ ```
141
+
142
+ **2. Custom Fields:**
143
+ ```javascript
144
+ { name: 'priority', fieldId: 'field-id' } // Custom field
145
+ { name: 'dueDate', fieldId: 'field-id' } // Custom field
146
+ ```
147
+
148
+ ### Workflow โ†’ SQL Mapping
149
+
150
+ | Hailer Concept | SQL Concept | Example |
151
+ |----------------|-------------|---------|
152
+ | Workflow | Table | `tasks` table |
153
+ | Activity | Row | One task row |
154
+ | Field | Column | `priority` column |
155
+ | ActivityLink | Foreign Key | JOIN on `project_id` |
156
+ | Insight | SELECT Query | Report query |
157
+
158
+ ## Meta Fields Reference
159
+
160
+ **Built-in activity properties available in all workflows:**
161
+
162
+ ### Available Meta Fields
163
+
164
+ | Meta Field | Type | Description | Usage |
165
+ |------------|------|-------------|-------|
166
+ | `_id` | string | Activity ID | For JOINs |
167
+ | `uid` | string | User ID (creator) | User filtering |
168
+ | `team` | string | Owner team ID | Team filtering |
169
+ | `createdBy` | string | Creator user ID | Track who created |
170
+ | `name` | string | Activity name/title | Display name |
171
+ | `created` | timestamp | Creation date/time | Sorting, filtering |
172
+ | `updated` | timestamp | Last update date/time | Recent changes |
173
+ | `phaseId` | string | Current phase ID | Status/phase grouping |
174
+ | `phaseName` | string | Current phase name | Display phase name |
175
+ | `phaseLastMove` | timestamp | Last phase change | Track phase transitions |
176
+ | `workflowId` | string | Workflow ID | Identify source workflow |
177
+ | `workflowName` | string | Workflow name | Display workflow name |
178
+ | `priority` | number | Activity priority | Priority filtering |
179
+
180
+ ### Meta Field Examples
181
+
182
+ **Activity Name:**
183
+ ```javascript
184
+ { name: 'title', meta: 'name' }
185
+ // Query: SELECT title FROM tasks
186
+ ```
187
+
188
+ **Activity ID (for JOINs):**
189
+ ```javascript
190
+ { name: 'id', meta: '_id' }
191
+ // Query: SELECT id FROM tasks
192
+ // JOIN: ON tasks.projectId = projects.id
193
+ ```
194
+
195
+ **Created Date:**
196
+ ```javascript
197
+ { name: 'createdDate', meta: 'created' }
198
+ // Query: SELECT createdDate FROM tasks WHERE createdDate > '2024-01-01'
199
+ ```
200
+
201
+ **Updated Date:**
202
+ ```javascript
203
+ { name: 'lastUpdated', meta: 'updated' }
204
+ // Query: SELECT lastUpdated FROM tasks ORDER BY lastUpdated DESC
205
+ ```
206
+
207
+ **Phase ID (Status):**
208
+ ```javascript
209
+ { name: 'status', meta: 'phaseId' }
210
+ // Query: SELECT status FROM tasks GROUP BY status
211
+ ```
212
+
213
+ **Phase Name (Readable Status):**
214
+ ```javascript
215
+ { name: 'statusName', meta: 'phaseName' }
216
+ // Query: SELECT statusName FROM tasks
217
+ ```
218
+
219
+ **Team:**
220
+ ```javascript
221
+ { name: 'ownerTeam', meta: 'team' }
222
+ // Query: SELECT ownerTeam FROM tasks WHERE ownerTeam = 'team-id'
223
+ ```
224
+
225
+ ## Basic Examples
226
+
227
+ ### Example 1: Simple List Query
228
+
229
+ **Goal:** List all tasks with due dates.
230
+
231
+ ```javascript
232
+ create_insight({
233
+ name: 'Tasks with Due Dates',
234
+ sources: [{
235
+ name: 'tasks',
236
+ workflowId: '68446dc05b30685f67c6fcd4',
237
+ fields: [
238
+ { name: 'taskName', meta: 'name' },
239
+ { name: 'dueDate', fieldId: 'due-date-field-id' },
240
+ { name: 'priority', fieldId: 'priority-field-id' }
241
+ ]
242
+ }],
243
+ query: 'SELECT taskName, dueDate, priority FROM tasks'
244
+ })
245
+ ```
246
+
247
+ ### Example 2: Filtered Query
248
+
249
+ **Goal:** Show only high-priority tasks due this month.
250
+
251
+ ```javascript
252
+ create_insight({
253
+ name: 'High Priority Tasks Due Soon',
254
+ sources: [{
255
+ name: 'tasks',
256
+ workflowId: 'tasks-workflow-id',
257
+ fields: [
258
+ { name: 'title', meta: 'name' },
259
+ { name: 'dueDate', fieldId: 'due-date-field-id' },
260
+ { name: 'priority', fieldId: 'priority-field-id' }
261
+ ]
262
+ }],
263
+ query: `
264
+ SELECT title, dueDate, priority
265
+ FROM tasks
266
+ WHERE priority = 'High'
267
+ AND dueDate >= '2024-12-01'
268
+ AND dueDate <= '2024-12-31'
269
+ `
270
+ })
271
+ ```
272
+
273
+ ### Example 3: Sorted Query
274
+
275
+ **Goal:** Recent tasks, newest first.
276
+
277
+ ```javascript
278
+ create_insight({
279
+ name: 'Recently Created Tasks',
280
+ sources: [{
281
+ name: 'tasks',
282
+ workflowId: 'tasks-workflow-id',
283
+ fields: [
284
+ { name: 'title', meta: 'name' },
285
+ { name: 'created', meta: 'created' }
286
+ ]
287
+ }],
288
+ query: `
289
+ SELECT title, created
290
+ FROM tasks
291
+ ORDER BY created DESC
292
+ LIMIT 50
293
+ `
294
+ })
295
+ ```
296
+
297
+ ### Example 4: Public Insight
298
+
299
+ **Goal:** Shareable report accessible without authentication.
300
+
301
+ ```javascript
302
+ create_insight({
303
+ name: 'Project Status Dashboard',
304
+ public: true, // Publicly accessible
305
+ sources: [{
306
+ name: 'projects',
307
+ workflowId: 'projects-workflow-id',
308
+ fields: [
309
+ { name: 'projectName', meta: 'name' },
310
+ { name: 'status', fieldId: 'status-field-id' },
311
+ { name: 'budget', fieldId: 'budget-field-id' }
312
+ ]
313
+ }],
314
+ query: 'SELECT projectName, status, budget FROM projects'
315
+ })
316
+ ```
317
+
318
+ ## SQL Features
319
+
320
+ ### SELECT Statement
321
+
322
+ **Basic SELECT:**
323
+ ```sql
324
+ SELECT title, priority FROM tasks
325
+ ```
326
+
327
+ **SELECT with aliases:**
328
+ ```sql
329
+ SELECT
330
+ title AS "Task Name",
331
+ priority AS "Priority Level"
332
+ FROM tasks
333
+ ```
334
+
335
+ **SELECT all columns:**
336
+ ```sql
337
+ SELECT * FROM tasks
338
+ ```
339
+
340
+ **SELECT distinct values:**
341
+ ```sql
342
+ SELECT DISTINCT priority FROM tasks
343
+ ```
344
+
345
+ ### WHERE Clause
346
+
347
+ **Comparison operators:**
348
+ ```sql
349
+ WHERE priority = 'High' -- Equal
350
+ WHERE dueDate > '2024-01-01' -- Greater than
351
+ WHERE quantity < 100 -- Less than
352
+ WHERE status != 'Done' -- Not equal
353
+ WHERE price >= 50 -- Greater than or equal
354
+ WHERE count <= 10 -- Less than or equal
355
+ ```
356
+
357
+ **Logical operators:**
358
+ ```sql
359
+ WHERE priority = 'High' AND status = 'Open' -- AND
360
+ WHERE priority = 'High' OR priority = 'Urgent' -- OR
361
+ WHERE NOT status = 'Done' -- NOT
362
+ ```
363
+
364
+ **Pattern matching:**
365
+ ```sql
366
+ WHERE title LIKE '%report%' -- Contains
367
+ WHERE email LIKE 'admin@%' -- Starts with
368
+ WHERE name LIKE '%Smith' -- Ends with
369
+ ```
370
+
371
+ **NULL checks:**
372
+ ```sql
373
+ WHERE dueDate IS NULL -- No due date
374
+ WHERE assignee IS NOT NULL -- Has assignee
375
+ ```
376
+
377
+ **IN operator:**
378
+ ```sql
379
+ WHERE priority IN ('High', 'Urgent')
380
+ WHERE status IN ('Open', 'In Progress')
381
+ ```
382
+
383
+ **BETWEEN operator:**
384
+ ```sql
385
+ WHERE dueDate BETWEEN '2024-01-01' AND '2024-12-31'
386
+ WHERE quantity BETWEEN 10 AND 100
387
+ ```
388
+
389
+ ### ORDER BY Clause
390
+
391
+ **Sort ascending:**
392
+ ```sql
393
+ ORDER BY dueDate ASC
394
+ ORDER BY priority
395
+ ```
396
+
397
+ **Sort descending:**
398
+ ```sql
399
+ ORDER BY created DESC
400
+ ORDER BY quantity DESC
401
+ ```
402
+
403
+ **Multiple columns:**
404
+ ```sql
405
+ ORDER BY priority DESC, dueDate ASC
406
+ ```
407
+
408
+ ### LIMIT and OFFSET
409
+
410
+ **Limit results:**
411
+ ```sql
412
+ SELECT * FROM tasks LIMIT 10
413
+ ```
414
+
415
+ **Pagination:**
416
+ ```sql
417
+ SELECT * FROM tasks LIMIT 10 OFFSET 20 -- Skip 20, take 10
418
+ ```
419
+
420
+ ## Advanced Queries
421
+
422
+ ### Complex Filtering
423
+
424
+ **Multiple conditions:**
425
+ ```javascript
426
+ create_insight({
427
+ name: 'Complex Task Filter',
428
+ sources: [{
429
+ name: 'tasks',
430
+ workflowId: 'tasks-workflow-id',
431
+ fields: [
432
+ { name: 'title', meta: 'name' },
433
+ { name: 'priority', fieldId: 'priority-field-id' },
434
+ { name: 'status', fieldId: 'status-field-id' },
435
+ { name: 'dueDate', fieldId: 'due-date-field-id' }
436
+ ]
437
+ }],
438
+ query: `
439
+ SELECT title, priority, status, dueDate
440
+ FROM tasks
441
+ WHERE (priority = 'High' OR priority = 'Urgent')
442
+ AND status != 'Done'
443
+ AND (dueDate < '2024-12-31' OR dueDate IS NULL)
444
+ ORDER BY priority DESC, dueDate ASC
445
+ `
446
+ })
447
+ ```
448
+
449
+ ### Calculated Columns
450
+
451
+ **String concatenation:**
452
+ ```sql
453
+ SELECT
454
+ title || ' - ' || priority AS "Full Description"
455
+ FROM tasks
456
+ ```
457
+
458
+ **Date calculations:**
459
+ ```sql
460
+ SELECT
461
+ title,
462
+ dueDate,
463
+ JULIANDAY(dueDate) - JULIANDAY('now') AS "Days Until Due"
464
+ FROM tasks
465
+ WHERE dueDate > date('now')
466
+ ```
467
+
468
+ ### Subqueries
469
+
470
+ **Filter by subquery result:**
471
+ ```sql
472
+ SELECT title, projectId
473
+ FROM tasks
474
+ WHERE projectId IN (
475
+ SELECT id
476
+ FROM projects
477
+ WHERE status = 'Active'
478
+ )
479
+ ```
480
+
481
+ ## Joins and Relationships
482
+
483
+ ### INNER JOIN
484
+
485
+ **Only matching records:**
486
+
487
+ ```javascript
488
+ create_insight({
489
+ name: 'Tasks with Projects (Must Have Project)',
490
+ sources: [
491
+ {
492
+ name: 'tasks',
493
+ workflowId: 'tasks-workflow-id',
494
+ fields: [
495
+ { name: 'taskName', meta: 'name' },
496
+ { name: 'projectLink', fieldId: 'project-link-field-id' }
497
+ ]
498
+ },
499
+ {
500
+ name: 'projects',
501
+ workflowId: 'projects-workflow-id',
502
+ fields: [
503
+ { name: 'id', meta: '_id' },
504
+ { name: 'projectName', meta: 'name' }
505
+ ]
506
+ }
507
+ ],
508
+ query: `
509
+ SELECT tasks.taskName, projects.projectName
510
+ FROM tasks
511
+ INNER JOIN projects ON tasks.projectLink = projects.id
512
+ `
513
+ })
514
+ ```
515
+
516
+ ### LEFT JOIN
517
+
518
+ **All left records + matching right records:**
519
+
520
+ ```javascript
521
+ create_insight({
522
+ name: 'All Tasks with Optional Projects',
523
+ sources: [
524
+ {
525
+ name: 'tasks',
526
+ workflowId: 'tasks-workflow-id',
527
+ fields: [
528
+ { name: 'taskName', meta: 'name' },
529
+ { name: 'projectLink', fieldId: 'project-link-field-id' }
530
+ ]
531
+ },
532
+ {
533
+ name: 'projects',
534
+ workflowId: 'projects-workflow-id',
535
+ fields: [
536
+ { name: 'id', meta: '_id' },
537
+ { name: 'projectName', meta: 'name' }
538
+ ]
539
+ }
540
+ ],
541
+ query: `
542
+ SELECT
543
+ tasks.taskName,
544
+ COALESCE(projects.projectName, 'No Project') AS projectName
545
+ FROM tasks
546
+ LEFT JOIN projects ON tasks.projectLink = projects.id
547
+ `
548
+ })
549
+ ```
550
+
551
+ ### Multiple Joins
552
+
553
+ **Three-level hierarchy:**
554
+
555
+ ```javascript
556
+ create_insight({
557
+ name: 'Tasks โ†’ Topics โ†’ Projects',
558
+ sources: [
559
+ {
560
+ name: 'tasks',
561
+ workflowId: 'tasks-workflow-id',
562
+ fields: [
563
+ { name: 'taskName', meta: 'name' },
564
+ { name: 'topicLink', fieldId: 'topic-field-id' }
565
+ ]
566
+ },
567
+ {
568
+ name: 'topics',
569
+ workflowId: 'topics-workflow-id',
570
+ fields: [
571
+ { name: 'id', meta: '_id' },
572
+ { name: 'topicName', meta: 'name' },
573
+ { name: 'projectLink', fieldId: 'project-field-id' }
574
+ ]
575
+ },
576
+ {
577
+ name: 'projects',
578
+ workflowId: 'projects-workflow-id',
579
+ fields: [
580
+ { name: 'id', meta: '_id' },
581
+ { name: 'projectName', meta: 'name' }
582
+ ]
583
+ }
584
+ ],
585
+ query: `
586
+ SELECT
587
+ tasks.taskName,
588
+ topics.topicName,
589
+ projects.projectName
590
+ FROM tasks
591
+ LEFT JOIN topics ON tasks.topicLink = topics.id
592
+ LEFT JOIN projects ON topics.projectLink = projects.id
593
+ `
594
+ })
595
+ ```
596
+
597
+ ## Aggregations and Grouping
598
+
599
+ ### COUNT
600
+
601
+ **Count all activities:**
602
+ ```javascript
603
+ create_insight({
604
+ name: 'Total Task Count',
605
+ sources: [{
606
+ name: 'tasks',
607
+ workflowId: 'tasks-workflow-id',
608
+ fields: [
609
+ { name: 'id', meta: '_id' }
610
+ ]
611
+ }],
612
+ query: 'SELECT COUNT(*) AS total FROM tasks'
613
+ })
614
+ ```
615
+
616
+ **Count by group:**
617
+ ```javascript
618
+ create_insight({
619
+ name: 'Tasks by Priority',
620
+ sources: [{
621
+ name: 'tasks',
622
+ workflowId: 'tasks-workflow-id',
623
+ fields: [
624
+ { name: 'priority', fieldId: 'priority-field-id' }
625
+ ]
626
+ }],
627
+ query: `
628
+ SELECT priority, COUNT(*) AS count
629
+ FROM tasks
630
+ GROUP BY priority
631
+ ORDER BY count DESC
632
+ `
633
+ })
634
+ ```
635
+
636
+ ### SUM
637
+
638
+ **Sum numeric values:**
639
+ ```javascript
640
+ create_insight({
641
+ name: 'Total Project Budget',
642
+ sources: [{
643
+ name: 'projects',
644
+ workflowId: 'projects-workflow-id',
645
+ fields: [
646
+ { name: 'budget', fieldId: 'budget-field-id' }
647
+ ]
648
+ }],
649
+ query: 'SELECT SUM(budget) AS totalBudget FROM projects'
650
+ })
651
+ ```
652
+
653
+ **Sum by group:**
654
+ ```javascript
655
+ create_insight({
656
+ name: 'Budget by Status',
657
+ sources: [{
658
+ name: 'projects',
659
+ workflowId: 'projects-workflow-id',
660
+ fields: [
661
+ { name: 'status', fieldId: 'status-field-id' },
662
+ { name: 'budget', fieldId: 'budget-field-id' }
663
+ ]
664
+ }],
665
+ query: `
666
+ SELECT status, SUM(budget) AS totalBudget
667
+ FROM projects
668
+ GROUP BY status
669
+ `
670
+ })
671
+ ```
672
+
673
+ ### AVG, MIN, MAX
674
+
675
+ **Statistical aggregations:**
676
+ ```javascript
677
+ create_insight({
678
+ name: 'Project Budget Statistics',
679
+ sources: [{
680
+ name: 'projects',
681
+ workflowId: 'projects-workflow-id',
682
+ fields: [
683
+ { name: 'budget', fieldId: 'budget-field-id' }
684
+ ]
685
+ }],
686
+ query: `
687
+ SELECT
688
+ AVG(budget) AS avgBudget,
689
+ MIN(budget) AS minBudget,
690
+ MAX(budget) AS maxBudget,
691
+ COUNT(*) AS projectCount
692
+ FROM projects
693
+ `
694
+ })
695
+ ```
696
+
697
+ ### HAVING Clause
698
+
699
+ **Filter aggregated results:**
700
+ ```javascript
701
+ create_insight({
702
+ name: 'Priorities with 5+ Tasks',
703
+ sources: [{
704
+ name: 'tasks',
705
+ workflowId: 'tasks-workflow-id',
706
+ fields: [
707
+ { name: 'priority', fieldId: 'priority-field-id' }
708
+ ]
709
+ }],
710
+ query: `
711
+ SELECT priority, COUNT(*) AS taskCount
712
+ FROM tasks
713
+ GROUP BY priority
714
+ HAVING COUNT(*) >= 5
715
+ ORDER BY taskCount DESC
716
+ `
717
+ })
718
+ ```
719
+
720
+ ## Best Practices
721
+
722
+ ### 1. Test with preview_insight First
723
+
724
+ **Always test queries before creating:**
725
+
726
+ ```javascript
727
+ // 1. Test with preview
728
+ preview_insight({
729
+ sources: [...],
730
+ query: 'SELECT ...'
731
+ })
732
+
733
+ // 2. If successful, create insight
734
+ create_insight({
735
+ name: 'My Insight',
736
+ sources: [...],
737
+ query: 'SELECT ...'
738
+ })
739
+ ```
740
+
741
+ ### 2. Use Descriptive Source Names
742
+
743
+ **Bad:**
744
+ ```javascript
745
+ sources: [
746
+ { name: 't1', workflowId: '...' },
747
+ { name: 't2', workflowId: '...' }
748
+ ]
749
+ ```
750
+
751
+ **Good:**
752
+ ```javascript
753
+ sources: [
754
+ { name: 'tasks', workflowId: '...' },
755
+ { name: 'projects', workflowId: '...' }
756
+ ]
757
+ ```
758
+
759
+ ### 3. Use Descriptive Column Names
760
+
761
+ **Bad:**
762
+ ```sql
763
+ SELECT t.a, p.b FROM tasks t JOIN projects p ON t.c = p.d
764
+ ```
765
+
766
+ **Good:**
767
+ ```sql
768
+ SELECT
769
+ tasks.taskName AS "Task Name",
770
+ projects.projectName AS "Project Name"
771
+ FROM tasks
772
+ LEFT JOIN projects ON tasks.projectId = projects.id
773
+ ```
774
+
775
+ ### 4. Include id Field for JOINs
776
+
777
+ **Always include _id in sources used for joins:**
778
+
779
+ ```javascript
780
+ sources: [
781
+ {
782
+ name: 'projects',
783
+ workflowId: 'projects-workflow-id',
784
+ fields: [
785
+ { name: 'id', meta: '_id' }, // Required for JOINs
786
+ { name: 'projectName', meta: 'name' }
787
+ ]
788
+ }
789
+ ]
790
+ ```
791
+
792
+ ### 5. Use LEFT JOIN for Optional Relationships
793
+
794
+ ```javascript
795
+ // Good: Shows all tasks, even without projects
796
+ LEFT JOIN projects ON tasks.projectId = projects.id
797
+
798
+ // Bad: Only shows tasks with projects
799
+ INNER JOIN projects ON tasks.projectId = projects.id
800
+ ```
801
+
802
+ ### 6. Get Field IDs from get_workflow_schema
803
+
804
+ ```javascript
805
+ // 1. Get schema
806
+ const schema = get_workflow_schema({
807
+ workflowId: 'workflow-id'
808
+ })
809
+
810
+ // 2. Find field IDs
811
+ const priorityField = schema.fields.find(f => f.key === 'priority')
812
+ console.log('Priority field ID:', priorityField._id)
813
+
814
+ // 3. Use in insight
815
+ create_insight({
816
+ sources: [{
817
+ fields: [
818
+ { name: 'priority', fieldId: priorityField._id }
819
+ ]
820
+ }],
821
+ query: '...'
822
+ })
823
+ ```
824
+
825
+ ### 7. Handle NULL Values
826
+
827
+ **Use COALESCE for defaults:**
828
+ ```sql
829
+ SELECT
830
+ taskName,
831
+ COALESCE(priority, 'Not Set') AS priority
832
+ FROM tasks
833
+ ```
834
+
835
+ **Check for NULL explicitly:**
836
+ ```sql
837
+ SELECT taskName
838
+ FROM tasks
839
+ WHERE dueDate IS NOT NULL
840
+ ```
841
+
842
+ ### 8. Limit Large Result Sets
843
+
844
+ ```sql
845
+ -- Good: Limit results
846
+ SELECT * FROM tasks ORDER BY created DESC LIMIT 100
847
+
848
+ -- Bad: Could return thousands of rows
849
+ SELECT * FROM tasks
850
+ ```
851
+
852
+ ### 9. Use Meaningful Insight Names
853
+
854
+ **Bad:**
855
+ - "Report 1"
856
+ - "Query"
857
+ - "Test"
858
+
859
+ **Good:**
860
+ - "High Priority Tasks Due This Month"
861
+ - "Projects by Team and Budget"
862
+ - "Task Completion Rate by Priority"
863
+
864
+ ### 10. Document Complex Queries
865
+
866
+ ```javascript
867
+ create_insight({
868
+ name: 'Task Status Report',
869
+ sources: [...],
870
+ query: `
871
+ -- Show all tasks with their project and priority
872
+ -- Excludes tasks in 'Done' status
873
+ -- Sorted by priority (High first) and due date
874
+ SELECT
875
+ tasks.taskName,
876
+ projects.projectName,
877
+ tasks.priority,
878
+ tasks.dueDate
879
+ FROM tasks
880
+ LEFT JOIN projects ON tasks.projectId = projects.id
881
+ WHERE tasks.status != 'Done'
882
+ ORDER BY
883
+ CASE tasks.priority
884
+ WHEN 'Urgent' THEN 1
885
+ WHEN 'High' THEN 2
886
+ WHEN 'Medium' THEN 3
887
+ ELSE 4
888
+ END,
889
+ tasks.dueDate ASC
890
+ `
891
+ })
892
+ ```
893
+
894
+ ## Common Patterns
895
+
896
+ ### Pattern 1: Recent Activities Report
897
+
898
+ ```javascript
899
+ create_insight({
900
+ name: 'Recently Created Tasks',
901
+ sources: [{
902
+ name: 'tasks',
903
+ workflowId: 'tasks-workflow-id',
904
+ fields: [
905
+ { name: 'title', meta: 'name' },
906
+ { name: 'created', meta: 'created' },
907
+ { name: 'priority', fieldId: 'priority-field-id' }
908
+ ]
909
+ }],
910
+ query: `
911
+ SELECT title, created, priority
912
+ FROM tasks
913
+ WHERE created >= date('now', '-7 days')
914
+ ORDER BY created DESC
915
+ `
916
+ })
917
+ ```
918
+
919
+ ### Pattern 2: Status Distribution
920
+
921
+ ```javascript
922
+ create_insight({
923
+ name: 'Task Status Distribution',
924
+ sources: [{
925
+ name: 'tasks',
926
+ workflowId: 'tasks-workflow-id',
927
+ fields: [
928
+ { name: 'status', meta: 'phase' }
929
+ ]
930
+ }],
931
+ query: `
932
+ SELECT
933
+ status,
934
+ COUNT(*) AS count,
935
+ ROUND(COUNT(*) * 100.0 / (SELECT COUNT(*) FROM tasks), 2) AS percentage
936
+ FROM tasks
937
+ GROUP BY status
938
+ ORDER BY count DESC
939
+ `
940
+ })
941
+ ```
942
+
943
+ ### Pattern 3: Overdue Tasks
944
+
945
+ ```javascript
946
+ create_insight({
947
+ name: 'Overdue Tasks',
948
+ sources: [{
949
+ name: 'tasks',
950
+ workflowId: 'tasks-workflow-id',
951
+ fields: [
952
+ { name: 'title', meta: 'name' },
953
+ { name: 'dueDate', fieldId: 'due-date-field-id' },
954
+ { name: 'priority', fieldId: 'priority-field-id' }
955
+ ]
956
+ }],
957
+ query: `
958
+ SELECT title, dueDate, priority
959
+ FROM tasks
960
+ WHERE dueDate < date('now')
961
+ AND status != 'Done'
962
+ ORDER BY dueDate ASC
963
+ `
964
+ })
965
+ ```
966
+
967
+ ### Pattern 4: Monthly Trends
968
+
969
+ ```javascript
970
+ create_insight({
971
+ name: 'Tasks Created Per Month',
972
+ sources: [{
973
+ name: 'tasks',
974
+ workflowId: 'tasks-workflow-id',
975
+ fields: [
976
+ { name: 'created', meta: 'created' }
977
+ ]
978
+ }],
979
+ query: `
980
+ SELECT
981
+ strftime('%Y-%m', created) AS month,
982
+ COUNT(*) AS taskCount
983
+ FROM tasks
984
+ GROUP BY month
985
+ ORDER BY month DESC
986
+ `
987
+ })
988
+ ```
989
+
990
+ ### Pattern 5: Top N Report
991
+
992
+ ```javascript
993
+ create_insight({
994
+ name: 'Top 10 Projects by Task Count',
995
+ sources: [
996
+ {
997
+ name: 'tasks',
998
+ workflowId: 'tasks-workflow-id',
999
+ fields: [
1000
+ { name: 'projectId', fieldId: 'project-field-id' }
1001
+ ]
1002
+ },
1003
+ {
1004
+ name: 'projects',
1005
+ workflowId: 'projects-workflow-id',
1006
+ fields: [
1007
+ { name: 'id', meta: '_id' },
1008
+ { name: 'projectName', meta: 'name' }
1009
+ ]
1010
+ }
1011
+ ],
1012
+ query: `
1013
+ SELECT
1014
+ projects.projectName,
1015
+ COUNT(tasks.projectId) AS taskCount
1016
+ FROM projects
1017
+ LEFT JOIN tasks ON projects.id = tasks.projectId
1018
+ GROUP BY projects.id, projects.projectName
1019
+ ORDER BY taskCount DESC
1020
+ LIMIT 10
1021
+ `
1022
+ })
1023
+ ```
1024
+
1025
+ ### Pattern 6: Missing Data Report
1026
+
1027
+ ```javascript
1028
+ create_insight({
1029
+ name: 'Tasks Without Due Date',
1030
+ sources: [{
1031
+ name: 'tasks',
1032
+ workflowId: 'tasks-workflow-id',
1033
+ fields: [
1034
+ { name: 'title', meta: 'name' },
1035
+ { name: 'dueDate', fieldId: 'due-date-field-id' },
1036
+ { name: 'created', meta: 'created' }
1037
+ ]
1038
+ }],
1039
+ query: `
1040
+ SELECT title, created
1041
+ FROM tasks
1042
+ WHERE dueDate IS NULL
1043
+ ORDER BY created DESC
1044
+ `
1045
+ })
1046
+ ```
1047
+
1048
+ ## Troubleshooting
1049
+
1050
+ ### Error: "SQL Query Error"
1051
+
1052
+ **Cause:** Invalid SQL syntax.
1053
+
1054
+ **Solutions:**
1055
+
1056
+ 1. **Test with preview_insight first:**
1057
+ ```javascript
1058
+ preview_insight({
1059
+ sources: [...],
1060
+ query: 'SELECT ...'
1061
+ })
1062
+ ```
1063
+
1064
+ 2. **Check common syntax errors:**
1065
+ ```sql
1066
+ -- Missing FROM clause
1067
+ SELECT title -- โŒ Missing FROM
1068
+ SELECT title FROM tasks -- โœ… Correct
1069
+
1070
+ -- Invalid column name
1071
+ SELECT titleee FROM tasks -- โŒ Typo
1072
+ SELECT title FROM tasks -- โœ… Correct
1073
+
1074
+ -- Missing quotes around strings
1075
+ WHERE priority = High -- โŒ No quotes
1076
+ WHERE priority = 'High' -- โœ… Quoted
1077
+
1078
+ -- Unmatched parentheses
1079
+ WHERE (priority = 'High' -- โŒ Missing )
1080
+ WHERE (priority = 'High') -- โœ… Matched
1081
+ ```
1082
+
1083
+ 3. **Verify field names match source definitions:**
1084
+ ```javascript
1085
+ sources: [{
1086
+ fields: [
1087
+ { name: 'priority', fieldId: '...' } // Name must match query
1088
+ ]
1089
+ }],
1090
+ query: 'SELECT priority FROM tasks' // Must use 'priority'
1091
+ ```
1092
+
1093
+ ### Error: "Invalid field IDs or workflow IDs"
1094
+
1095
+ **Cause:** Field IDs don't exist in workflow.
1096
+
1097
+ **Solution:**
1098
+
1099
+ ```javascript
1100
+ // 1. Get correct field IDs
1101
+ const schema = get_workflow_schema({
1102
+ workflowId: 'workflow-id'
1103
+ })
1104
+
1105
+ // 2. Find field
1106
+ const field = schema.fields.find(f => f.key === 'priority')
1107
+ console.log('Field ID:', field._id)
1108
+
1109
+ // 3. Use correct ID
1110
+ create_insight({
1111
+ sources: [{
1112
+ fields: [
1113
+ { name: 'priority', fieldId: field._id } // Correct ID
1114
+ ]
1115
+ }]
1116
+ })
1117
+ ```
1118
+
1119
+ ### Error: "Permission Denied"
1120
+
1121
+ **Cause:** Don't have permission to create insights or access workflows.
1122
+
1123
+ **Solution:**
1124
+ - Check workspace permissions
1125
+ - Verify access to all workflows in sources
1126
+ - Contact workspace administrator
1127
+
1128
+ ### Insight Created But Returns No Data
1129
+
1130
+ **Causes:**
1131
+ 1. No activities match WHERE clause
1132
+ 2. JOIN eliminates all rows
1133
+ 3. Field values are NULL
1134
+
1135
+ **Solutions:**
1136
+
1137
+ 1. **Check activity count:**
1138
+ ```javascript
1139
+ list_activities({
1140
+ workflowId: 'workflow-id',
1141
+ limit: 1
1142
+ })
1143
+ ```
1144
+
1145
+ 2. **Simplify query to test:**
1146
+ ```sql
1147
+ -- Start simple
1148
+ SELECT * FROM tasks LIMIT 10
1149
+
1150
+ -- Then add filters one by one
1151
+ SELECT * FROM tasks WHERE priority = 'High' LIMIT 10
1152
+ ```
1153
+
1154
+ 3. **Use LEFT JOIN instead of INNER JOIN:**
1155
+ ```sql
1156
+ -- Shows all tasks, even without projects
1157
+ LEFT JOIN projects ON tasks.projectId = projects.id
1158
+ ```
1159
+
1160
+ ### JOIN Not Working
1161
+
1162
+ **Cause:** ActivityLink field ID used instead of activity ID.
1163
+
1164
+ **Solution:**
1165
+
1166
+ ```javascript
1167
+ // Correct: Join on activity _id
1168
+ sources: [
1169
+ {
1170
+ name: 'projects',
1171
+ fields: [
1172
+ { name: 'id', meta: '_id' } // Use _id for joins
1173
+ ]
1174
+ }
1175
+ ],
1176
+ query: 'LEFT JOIN projects ON tasks.projectId = projects.id'
1177
+
1178
+ // Note: projectId field should contain activity ID, not field ID
1179
+ ```
1180
+
1181
+ ### Aggregation Returns Unexpected Results
1182
+
1183
+ **Cause:** Missing GROUP BY or incorrect grouping.
1184
+
1185
+ **Solution:**
1186
+
1187
+ ```sql
1188
+ -- Correct: Group by all non-aggregated columns
1189
+ SELECT priority, COUNT(*) AS count
1190
+ FROM tasks
1191
+ GROUP BY priority
1192
+
1193
+ -- Incorrect: Missing GROUP BY
1194
+ SELECT priority, COUNT(*) AS count -- โŒ Error
1195
+ FROM tasks
1196
+ ```
1197
+
1198
+ ## Integration with Other Tools
1199
+
1200
+ ### With preview_insight
1201
+
1202
+ Test before creating:
1203
+
1204
+ ```javascript
1205
+ // 1. Preview first
1206
+ preview_insight({
1207
+ sources: [...],
1208
+ query: 'SELECT ...'
1209
+ })
1210
+
1211
+ // 2. If successful, create
1212
+ create_insight({
1213
+ name: 'My Insight',
1214
+ sources: [...],
1215
+ query: 'SELECT ...'
1216
+ })
1217
+ ```
1218
+
1219
+ ### With get_insight_data
1220
+
1221
+ Execute after creation:
1222
+
1223
+ ```javascript
1224
+ // 1. Create insight
1225
+ const result = create_insight({...})
1226
+ // Returns: { insightId: '...' }
1227
+
1228
+ // 2. Get data
1229
+ get_insight_data({
1230
+ insightId: result.insightId
1231
+ })
1232
+ ```
1233
+
1234
+ ### With get_workflow_schema
1235
+
1236
+ Get field IDs:
1237
+
1238
+ ```javascript
1239
+ // 1. Get schema
1240
+ const schema = get_workflow_schema({
1241
+ workflowId: 'workflow-id'
1242
+ })
1243
+
1244
+ // 2. Map fields to IDs
1245
+ const fieldMappings = schema.fields
1246
+ .filter(f => f.key)
1247
+ .map(f => ({
1248
+ name: f.key,
1249
+ fieldId: f._id
1250
+ }))
1251
+
1252
+ // 3. Use in insight
1253
+ create_insight({
1254
+ sources: [{
1255
+ workflowId: 'workflow-id',
1256
+ fields: fieldMappings
1257
+ }],
1258
+ query: '...'
1259
+ })
1260
+ ```
1261
+
1262
+ ### With list_workflows
1263
+
1264
+ Find workflow IDs:
1265
+
1266
+ ```javascript
1267
+ // 1. List workflows
1268
+ const workflows = list_workflows()
1269
+
1270
+ // 2. Find specific workflows
1271
+ const tasks = workflows.find(w => w.name === 'Tasks')
1272
+ const projects = workflows.find(w => w.name === 'Projects')
1273
+
1274
+ // 3. Create insight
1275
+ create_insight({
1276
+ sources: [
1277
+ { name: 'tasks', workflowId: tasks._id, ... },
1278
+ { name: 'projects', workflowId: projects._id, ... }
1279
+ ],
1280
+ query: '...'
1281
+ })
1282
+ ```
1283
+
1284
+ ## Summary
1285
+
1286
+ **Key Takeaways:**
1287
+ 1. ๐Ÿ” **SQL queries** - Full SQL syntax over workflow data
1288
+ 2. ๐Ÿ”— **Cross-workflow joins** - Relate data across workflows
1289
+ 3. ๐Ÿ“Š **Aggregations** - COUNT, SUM, AVG, MIN, MAX
1290
+ 4. ๐Ÿ”‘ **Meta fields** - Built-in activity properties (_id, name, created, etc.)
1291
+ 5. ๐Ÿงช **Preview first** - Test queries with preview_insight
1292
+ 6. ๐Ÿ”’ **Public option** - Share insights without authentication
1293
+ 7. ๐Ÿ“ˆ **Real-time** - Insights update as activity data changes
1294
+
1295
+ **Quick Decision Tree:**
1296
+
1297
+ ```
1298
+ Need to create an insight?
1299
+ โ”‚
1300
+ โ”œโ”€ Single workflow? โ†’ Use one source, simple SELECT
1301
+ โ”œโ”€ Multiple workflows? โ†’ Use multiple sources with JOIN
1302
+ โ”œโ”€ Count/aggregate? โ†’ Use GROUP BY with COUNT/SUM/AVG
1303
+ โ”œโ”€ Filter data? โ†’ Add WHERE clause
1304
+ โ”œโ”€ Sort results? โ†’ Add ORDER BY
1305
+ โ”œโ”€ Complex query? โ†’ Test with preview_insight first
1306
+ โ””โ”€ Share publicly? โ†’ Set public: true
1307
+ ```
1308
+
1309
+ ## Additional Resources
1310
+
1311
+ - See `preview-insight-skill` for testing queries
1312
+ - See `get-insight-data-skill` for executing insights
1313
+ - See `remove-insight-skill` for deleting insights
1314
+ - See `insight-api` skill for comprehensive Insight API documentation
1315
+ - See `hailer-api` skill for Hailer API reference
1316
+ - Use `get_workflow_schema` to find field IDs
1317
+ - Use `list_workflows` to find workflow IDs