@atom8n/ai-workflow-builder 1.4.3 → 1.5.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.
- package/dist/build.tsbuildinfo +1 -1
- package/dist/prompts/chains/parameter-updater/guides/predecessor-output.d.ts +2 -0
- package/dist/prompts/chains/parameter-updater/guides/predecessor-output.js +24 -0
- package/dist/prompts/shared/node-guidance/index.d.ts +1 -0
- package/dist/prompts/shared/node-guidance/index.js +5 -0
- package/dist/prompts/shared/node-guidance/structured-output-parser.d.ts +2 -0
- package/dist/prompts/shared/node-guidance/structured-output-parser.js +34 -0
- package/dist/prompts/shared/node-recommendations/audio-generation.d.ts +2 -0
- package/dist/prompts/shared/node-recommendations/audio-generation.js +17 -0
- package/dist/prompts/shared/node-recommendations/image-generation.d.ts +2 -0
- package/dist/prompts/shared/node-recommendations/image-generation.js +17 -0
- package/dist/prompts/shared/node-recommendations/index.d.ts +3 -0
- package/dist/prompts/shared/node-recommendations/index.js +16 -0
- package/dist/prompts/shared/node-recommendations/text-manipulation.d.ts +2 -0
- package/dist/prompts/shared/node-recommendations/text-manipulation.js +26 -0
- package/dist/prompts/shared/node-recommendations/utils/format-recommendation.d.ts +2 -0
- package/dist/prompts/shared/node-recommendations/utils/format-recommendation.js +23 -0
- package/dist/prompts/shared/node-recommendations/video-generation.d.ts +2 -0
- package/dist/prompts/shared/node-recommendations/video-generation.js +14 -0
- package/dist/tools/best-practices/data-persistence.d.ts +7 -0
- package/dist/tools/best-practices/data-persistence.js +196 -0
- package/dist/tools/get-documentation.tool.d.ts +79 -0
- package/dist/tools/get-documentation.tool.js +163 -0
- package/dist/tools/rename-node.tool.d.ts +15 -0
- package/dist/tools/rename-node.tool.js +140 -0
- package/dist/types/node-guidance.d.ts +7 -0
- package/dist/types/node-guidance.js +2 -0
- package/dist/types/node-recommendations.d.ts +26 -0
- package/dist/types/node-recommendations.js +15 -0
- package/dist/utils/resource-operation-extractor.d.ts +16 -0
- package/dist/utils/resource-operation-extractor.js +147 -0
- package/dist/validation/auto-fix/auto-fix-connections.d.ts +21 -0
- package/dist/validation/auto-fix/auto-fix-connections.js +206 -0
- package/dist/validation/auto-fix/index.d.ts +2 -0
- package/dist/validation/auto-fix/index.js +5 -0
- package/package.json +7 -7
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PREDECESSOR_OUTPUT_GUIDE = void 0;
|
|
4
|
+
exports.PREDECESSOR_OUTPUT_GUIDE = {
|
|
5
|
+
patterns: ['*'],
|
|
6
|
+
content: `
|
|
7
|
+
### Referencing Output from Special Node Types
|
|
8
|
+
|
|
9
|
+
#### AI Agent Output Structure
|
|
10
|
+
AI Agent nodes (n8n-nodes-langchain.agent) wrap their response in an "output" object:
|
|
11
|
+
- Without Structured Output Parser: Use \`$json.output\` to access the response string
|
|
12
|
+
- With Structured Output Parser (hasOutputParser: true in node settings): Use \`$json.output.fieldName\` to access parsed fields
|
|
13
|
+
- Use \`$('AI Agent').item.json.output.fieldName\` when referencing a node, instead of \`$('AI Agent').item.json.fieldName\`
|
|
14
|
+
- WRONG: \`$json.summary\` → CORRECT: \`$json.output.summary\`
|
|
15
|
+
|
|
16
|
+
#### Webhook Node Output Structure
|
|
17
|
+
When referencing data from a Webhook node (n8n-nodes-base.webhook), the incoming request is structured under \`$json\`:
|
|
18
|
+
- \`$json.headers\` - HTTP headers, example: \`$json.headers.authorization\`
|
|
19
|
+
- \`$json.params\` - URL path parameters, example route: \`/users/:id\`, access: \`$json.params.id\`
|
|
20
|
+
- \`$json.query\` - Query string parameters, example URL: \`?user_id=123\`, access: \`$json.query.user_id\`
|
|
21
|
+
- \`$json.body\` - Request payload, example JSON: \`{ "userName": "sam" }\`, access: \`$json.body.userName\`
|
|
22
|
+
|
|
23
|
+
CRITICAL: When referencing data from a Webhook node, do NOT use \`$json.fieldName\` directly - always specify the container (body, query, params, or headers).`,
|
|
24
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { structuredOutputParser } from './structured-output-parser';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.structuredOutputParser = void 0;
|
|
4
|
+
var structured_output_parser_1 = require("./structured-output-parser");
|
|
5
|
+
Object.defineProperty(exports, "structuredOutputParser", { enumerable: true, get: function () { return structured_output_parser_1.structuredOutputParser; } });
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.structuredOutputParser = void 0;
|
|
4
|
+
exports.structuredOutputParser = {
|
|
5
|
+
nodeType: '@n8n/n8n-nodes-langchain.outputParserStructured',
|
|
6
|
+
usage: `Search for "Structured Output Parser" (@n8n/n8n-nodes-langchain.outputParserStructured) when:
|
|
7
|
+
- AI output will be used programmatically (conditions, formatting, database storage, API calls)
|
|
8
|
+
- AI needs to extract specific fields (e.g., score, category, priority, action items)
|
|
9
|
+
- AI needs to classify/categorize data into defined categories
|
|
10
|
+
- Downstream nodes need to access specific fields from AI response (e.g., $json.score, $json.category)
|
|
11
|
+
- Output will be displayed in a formatted way (e.g., HTML email with specific sections)
|
|
12
|
+
- Data needs validation against a schema before processing
|
|
13
|
+
|
|
14
|
+
- Always use search_nodes to find the exact node names and versions - NEVER guess versions`,
|
|
15
|
+
connections: `When Discovery results include AI Agent or Structured Output Parser:
|
|
16
|
+
1. Create the Structured Output Parser node
|
|
17
|
+
2. Set AI Agent's hasOutputParser: true in initialParameters
|
|
18
|
+
3. Connect: Structured Output Parser → AI Agent (ai_outputParser connection)`,
|
|
19
|
+
configuration: `WHEN TO SET hasOutputParser: true on AI Agent:
|
|
20
|
+
- Discovery found Structured Output Parser node → MUST set hasOutputParser: true
|
|
21
|
+
- AI output will be used in conditions (IF/Switch nodes checking $json.field)
|
|
22
|
+
- AI output will be formatted/displayed (HTML emails, reports with specific sections)
|
|
23
|
+
- AI output will be stored in database/data tables with specific fields
|
|
24
|
+
- AI is classifying, scoring, or extracting specific data fields`,
|
|
25
|
+
recommendation: `For AI-generated structured data, prefer Structured Output Parser nodes over Code nodes.
|
|
26
|
+
Why: Purpose-built parsers are more reliable and handle edge cases better than custom code.
|
|
27
|
+
|
|
28
|
+
For binary file data, use Extract From File node to extract content from files before processing.
|
|
29
|
+
|
|
30
|
+
Use Code nodes only for:
|
|
31
|
+
- Simple string manipulations
|
|
32
|
+
- Already structured data (JSON, CSV)
|
|
33
|
+
- Custom business logic beyond parsing`,
|
|
34
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.audioGenerationRecommendation = void 0;
|
|
4
|
+
const node_recommendations_1 = require("../../../types/node-recommendations");
|
|
5
|
+
exports.audioGenerationRecommendation = {
|
|
6
|
+
category: node_recommendations_1.RecommendationCategory.AUDIO_GENERATION,
|
|
7
|
+
version: '1.0.0',
|
|
8
|
+
recommendation: {
|
|
9
|
+
defaultNode: '@n8n/n8n-nodes-langchain.openAi',
|
|
10
|
+
operations: [
|
|
11
|
+
'Generate Audio: Create speech from text using OpenAI TTS',
|
|
12
|
+
'Transcribe a Recording: Convert audio to text using Whisper',
|
|
13
|
+
'Translate a Recording: Transcribe and translate audio to English using Whisper',
|
|
14
|
+
],
|
|
15
|
+
reasoning: "OpenAI provides comprehensive audio capabilities: TTS for speech generation, Whisper for transcription and translation. Prefer OpenAI when user doesn't specify a provider.",
|
|
16
|
+
},
|
|
17
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.imageGenerationRecommendation = void 0;
|
|
4
|
+
const node_recommendations_1 = require("../../../types/node-recommendations");
|
|
5
|
+
exports.imageGenerationRecommendation = {
|
|
6
|
+
category: node_recommendations_1.RecommendationCategory.IMAGE_GENERATION,
|
|
7
|
+
version: '1.0.0',
|
|
8
|
+
recommendation: {
|
|
9
|
+
defaultNode: '@n8n/n8n-nodes-langchain.openAi',
|
|
10
|
+
operations: [
|
|
11
|
+
'Analyze Image: Analyze and describe image content using GPT-4 Vision',
|
|
12
|
+
'Generate an Image: Create images from text prompts using DALL-E',
|
|
13
|
+
'Edit Image: Modify existing images using DALL-E',
|
|
14
|
+
],
|
|
15
|
+
reasoning: "OpenAI provides comprehensive image capabilities: DALL-E for generation/editing, GPT-4 Vision for analysis. Prefer OpenAI when user doesn't specify a provider.",
|
|
16
|
+
},
|
|
17
|
+
};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { type RecommendationCategoryType, type NodeRecommendationDocument } from '../../../types';
|
|
2
|
+
export { formatRecommendation } from './utils/format-recommendation';
|
|
3
|
+
export declare const recommendations: Record<RecommendationCategoryType, NodeRecommendationDocument | undefined>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.recommendations = exports.formatRecommendation = void 0;
|
|
4
|
+
const types_1 = require("../../../types");
|
|
5
|
+
const audio_generation_1 = require("./audio-generation");
|
|
6
|
+
const image_generation_1 = require("./image-generation");
|
|
7
|
+
const text_manipulation_1 = require("./text-manipulation");
|
|
8
|
+
const video_generation_1 = require("./video-generation");
|
|
9
|
+
var format_recommendation_1 = require("./utils/format-recommendation");
|
|
10
|
+
Object.defineProperty(exports, "formatRecommendation", { enumerable: true, get: function () { return format_recommendation_1.formatRecommendation; } });
|
|
11
|
+
exports.recommendations = {
|
|
12
|
+
[types_1.RecommendationCategory.TEXT_MANIPULATION]: text_manipulation_1.textManipulationRecommendation,
|
|
13
|
+
[types_1.RecommendationCategory.IMAGE_GENERATION]: image_generation_1.imageGenerationRecommendation,
|
|
14
|
+
[types_1.RecommendationCategory.VIDEO_GENERATION]: video_generation_1.videoGenerationRecommendation,
|
|
15
|
+
[types_1.RecommendationCategory.AUDIO_GENERATION]: audio_generation_1.audioGenerationRecommendation,
|
|
16
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.textManipulationRecommendation = void 0;
|
|
4
|
+
const node_recommendations_1 = require("../../../types/node-recommendations");
|
|
5
|
+
exports.textManipulationRecommendation = {
|
|
6
|
+
category: node_recommendations_1.RecommendationCategory.TEXT_MANIPULATION,
|
|
7
|
+
version: '1.0.0',
|
|
8
|
+
recommendation: {
|
|
9
|
+
defaultNode: '@n8n/n8n-nodes-langchain.agent',
|
|
10
|
+
operations: [
|
|
11
|
+
'Text summarization',
|
|
12
|
+
'Content analysis and extraction',
|
|
13
|
+
'Classification and categorization',
|
|
14
|
+
'Chat and conversational AI',
|
|
15
|
+
'Content generation and writing',
|
|
16
|
+
],
|
|
17
|
+
reasoning: 'The AI Agent node is the default for text manipulation tasks. New users receive free OpenAI credits. Do NOT use provider-specific nodes directly.',
|
|
18
|
+
connectedNodes: [
|
|
19
|
+
{
|
|
20
|
+
nodeType: '@n8n/n8n-nodes-langchain.lmChatOpenAi',
|
|
21
|
+
connectionType: 'ai_languageModel',
|
|
22
|
+
description: 'Required chat model for the AI Agent',
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatRecommendation = formatRecommendation;
|
|
4
|
+
const builder_1 = require("../../../../prompts/builder");
|
|
5
|
+
function formatRecommendation(rec) {
|
|
6
|
+
const builder = (0, builder_1.prompt)()
|
|
7
|
+
.section('default_node', rec.defaultNode)
|
|
8
|
+
.section('operations', rec.operations.map((op) => `- ${op}`).join('\n'))
|
|
9
|
+
.section('reasoning', rec.reasoning);
|
|
10
|
+
if (rec.connectedNodes && rec.connectedNodes.length > 0) {
|
|
11
|
+
const connectedContent = rec.connectedNodes
|
|
12
|
+
.map((cn) => {
|
|
13
|
+
const desc = cn.description ? ` - ${cn.description}` : '';
|
|
14
|
+
return `- ${cn.nodeType} (connection: ${cn.connectionType})${desc}`;
|
|
15
|
+
})
|
|
16
|
+
.join('\n');
|
|
17
|
+
builder.section('connected_nodes', connectedContent);
|
|
18
|
+
}
|
|
19
|
+
if (rec.note) {
|
|
20
|
+
builder.section('note', rec.note);
|
|
21
|
+
}
|
|
22
|
+
return builder.build();
|
|
23
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.videoGenerationRecommendation = void 0;
|
|
4
|
+
const node_recommendations_1 = require("../../../types/node-recommendations");
|
|
5
|
+
exports.videoGenerationRecommendation = {
|
|
6
|
+
category: node_recommendations_1.RecommendationCategory.VIDEO_GENERATION,
|
|
7
|
+
version: '1.0.0',
|
|
8
|
+
recommendation: {
|
|
9
|
+
defaultNode: '@n8n/n8n-nodes-langchain.openAi',
|
|
10
|
+
operations: ['Generate a Video: Create videos from text prompts using Sora'],
|
|
11
|
+
reasoning: "OpenAI Sora is the default for video generation. Prefer OpenAI when user doesn't specify a provider.",
|
|
12
|
+
note: 'Video generation may require async processing with Wait nodes due to longer generation times.',
|
|
13
|
+
},
|
|
14
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { BestPracticesDocument } from '../../types/best-practices';
|
|
2
|
+
export declare class DataPersistenceBestPractices implements BestPracticesDocument {
|
|
3
|
+
readonly technique: "data_persistence";
|
|
4
|
+
readonly version = "1.0.0";
|
|
5
|
+
private readonly documentation;
|
|
6
|
+
getDocumentation(): string;
|
|
7
|
+
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DataPersistenceBestPractices = void 0;
|
|
4
|
+
const categorization_1 = require("../../types/categorization");
|
|
5
|
+
class DataPersistenceBestPractices {
|
|
6
|
+
technique = categorization_1.WorkflowTechnique.DATA_PERSISTENCE;
|
|
7
|
+
version = '1.0.0';
|
|
8
|
+
documentation = `# Best Practices: Data Persistence
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
Data persistence involves storing, updating, or retrieving records from durable storage systems. This technique is essential when you need to maintain data beyond the lifetime of a single workflow execution, or when you need to access existing data that users have stored in their spreadsheets, tables, or databases as part of your workflow logic.
|
|
13
|
+
|
|
14
|
+
## When to Use Data Persistence
|
|
15
|
+
|
|
16
|
+
Use data persistence when you need to:
|
|
17
|
+
- Store workflow results for later retrieval or audit trails
|
|
18
|
+
- Maintain records that multiple workflows can access and update
|
|
19
|
+
- Create a centralized data repository for your automation
|
|
20
|
+
- Archive historical data for reporting or compliance
|
|
21
|
+
- Build data that persists across workflow executions
|
|
22
|
+
- Track changes or maintain state over time
|
|
23
|
+
- Store raw form inputs
|
|
24
|
+
|
|
25
|
+
## Choosing the Right Storage Node
|
|
26
|
+
|
|
27
|
+
### Data Table (n8n-nodes-base.dataTable) - PREFERRED
|
|
28
|
+
|
|
29
|
+
**Best for:** Quick setup, small to medium amounts of data
|
|
30
|
+
|
|
31
|
+
Advantages:
|
|
32
|
+
- No credentials or external configuration required
|
|
33
|
+
- Built directly into n8n
|
|
34
|
+
- Fast and reliable for small to medium datasets
|
|
35
|
+
- Ideal for prototyping and internal workflows
|
|
36
|
+
- No additional costs or external dependencies
|
|
37
|
+
|
|
38
|
+
When to use:
|
|
39
|
+
- Internal workflow data storage
|
|
40
|
+
- Temporary or staging data
|
|
41
|
+
- Admin/audit trails
|
|
42
|
+
- Simple record keeping
|
|
43
|
+
- Development and testing
|
|
44
|
+
|
|
45
|
+
### Google Sheets (n8n-nodes-base.googleSheets)
|
|
46
|
+
|
|
47
|
+
**Best for:** Collaboration, reporting, easy data sharing
|
|
48
|
+
|
|
49
|
+
Advantages:
|
|
50
|
+
- Familiar spreadsheet interface for non-technical users
|
|
51
|
+
- Easy to share and collaborate on data
|
|
52
|
+
- Built-in visualization and formula capabilities
|
|
53
|
+
- Good for reporting and dashboards
|
|
54
|
+
- Accessible from anywhere
|
|
55
|
+
|
|
56
|
+
When to use:
|
|
57
|
+
- Data needs to be viewed/edited by multiple people
|
|
58
|
+
- Non-technical users need access to data
|
|
59
|
+
- Integration with other Google Workspace tools
|
|
60
|
+
- Simple data structures without complex relationships
|
|
61
|
+
- Workflow needs access to existing spreadsheets in Google Sheets
|
|
62
|
+
|
|
63
|
+
Pitfalls:
|
|
64
|
+
- API rate limits can affect high-volume workflows
|
|
65
|
+
- Not suitable for frequently changing data
|
|
66
|
+
- Performance degrades with very large datasets (>10k rows)
|
|
67
|
+
|
|
68
|
+
### Airtable (n8n-nodes-base.airtable)
|
|
69
|
+
|
|
70
|
+
**Best for:** Structured data with relationships, rich field types
|
|
71
|
+
|
|
72
|
+
Advantages:
|
|
73
|
+
- Supports relationships between tables
|
|
74
|
+
- Rich field types (attachments, select, links, etc.)
|
|
75
|
+
- Better structure than spreadsheets
|
|
76
|
+
|
|
77
|
+
When to use:
|
|
78
|
+
- Data has relationships or references between records
|
|
79
|
+
- Need structured database-like features
|
|
80
|
+
- Managing projects, tasks, or inventory
|
|
81
|
+
- Workflow needs access to existing data in Airtable
|
|
82
|
+
|
|
83
|
+
Pitfalls:
|
|
84
|
+
- Requires Airtable account and API key
|
|
85
|
+
- Schema changes require careful planning
|
|
86
|
+
|
|
87
|
+
## Storage Patterns
|
|
88
|
+
|
|
89
|
+
### Immediate Storage Pattern
|
|
90
|
+
|
|
91
|
+
Store data immediately after collection or generation:
|
|
92
|
+
|
|
93
|
+
\`\`\`mermaid
|
|
94
|
+
flowchart LR
|
|
95
|
+
Trigger --> Process_Data["Process Data"]
|
|
96
|
+
Process_Data --> Storage_Node["Storage Node"]
|
|
97
|
+
Storage_Node --> Continue_Workflow["Continue Workflow"]
|
|
98
|
+
\`\`\`
|
|
99
|
+
|
|
100
|
+
Best for: Raw data preservation, audit trails, form submissions
|
|
101
|
+
|
|
102
|
+
### Batch Storage Pattern
|
|
103
|
+
|
|
104
|
+
Collect multiple items and store them together:
|
|
105
|
+
|
|
106
|
+
\`\`\`mermaid
|
|
107
|
+
flowchart LR
|
|
108
|
+
Trigger --> Loop_Split["Loop/Split"]
|
|
109
|
+
Loop_Split --> Process["Process"]
|
|
110
|
+
Process --> Aggregate["Aggregate"]
|
|
111
|
+
Aggregate --> Storage_Node["Storage Node"]
|
|
112
|
+
\`\`\`
|
|
113
|
+
|
|
114
|
+
Best for: Processing lists, batch operations, scheduled aggregations
|
|
115
|
+
|
|
116
|
+
### Update Pattern
|
|
117
|
+
|
|
118
|
+
Retrieve, modify, and update existing records:
|
|
119
|
+
|
|
120
|
+
\`\`\`mermaid
|
|
121
|
+
flowchart LR
|
|
122
|
+
Trigger --> Retrieve["Retrieve from Storage"]
|
|
123
|
+
Retrieve --> Modify["Modify"]
|
|
124
|
+
Modify --> Update_Storage["Update Storage Node"]
|
|
125
|
+
\`\`\`
|
|
126
|
+
|
|
127
|
+
Best for: Maintaining state, updating records, tracking changes
|
|
128
|
+
|
|
129
|
+
### Lookup Pattern
|
|
130
|
+
|
|
131
|
+
Query storage to retrieve specific records:
|
|
132
|
+
|
|
133
|
+
\`\`\`mermaid
|
|
134
|
+
flowchart LR
|
|
135
|
+
Trigger --> Query_Storage["Query Storage Node"]
|
|
136
|
+
Query_Storage --> Use_Data["Use Retrieved Data"]
|
|
137
|
+
Use_Data --> Continue_Workflow["Continue Workflow"]
|
|
138
|
+
\`\`\`
|
|
139
|
+
|
|
140
|
+
Best for: Enrichment, validation, conditional logic based on stored data
|
|
141
|
+
|
|
142
|
+
## Key Considerations
|
|
143
|
+
|
|
144
|
+
### Data Structure
|
|
145
|
+
|
|
146
|
+
- **Plan your schema ahead:** Define what fields you need before creating storage
|
|
147
|
+
- **Use consistent field names:** Match field names across your workflow for easy mapping
|
|
148
|
+
- **Consider data types:** Ensure your storage supports the data types you need
|
|
149
|
+
- **Think about relationships:** If data is related, consider Airtable or use multiple tables
|
|
150
|
+
|
|
151
|
+
### Performance
|
|
152
|
+
|
|
153
|
+
- **Batch operations when possible:** Multiple small writes are slower than batch operations
|
|
154
|
+
- **Use appropriate operations:** Use "append" for new records, "update" for modifications
|
|
155
|
+
- **Consider API limits:** Google Sheets has rate limits; plan accordingly for high-volume workflows
|
|
156
|
+
|
|
157
|
+
### Data Integrity
|
|
158
|
+
|
|
159
|
+
- **Store raw data first:** Keep unmodified input before transformations
|
|
160
|
+
- **Handle errors gracefully:** Use error handling to prevent data loss on failures
|
|
161
|
+
- **Validate before storing:** Ensure data quality before persistence
|
|
162
|
+
- **Avoid duplicates:** Use unique identifiers or upsert operations when appropriate
|
|
163
|
+
|
|
164
|
+
## Referencing Documents, Sheets, or Tables
|
|
165
|
+
|
|
166
|
+
When configuring storage nodes, use ResourceLocator mode "list". This will allow users to select from existing documents, sheets, or tables rather than passing IDs dynamically.
|
|
167
|
+
Use modes "id", "url" or "name" only when user specifically mentions it in their prompt.
|
|
168
|
+
|
|
169
|
+
## Important Distinctions
|
|
170
|
+
|
|
171
|
+
### Storage vs. Transformation
|
|
172
|
+
|
|
173
|
+
- **Set/Merge nodes are NOT storage:** They transform data in memory only
|
|
174
|
+
- **Storage happens explicitly:** Data won't persist unless you explicitly write it to storage
|
|
175
|
+
|
|
176
|
+
### Temporary vs. Persistent Storage
|
|
177
|
+
|
|
178
|
+
- **NOT covered by this technique:** Redis, caching, session storage, in-memory operations
|
|
179
|
+
- **This technique covers:** Durable storage that persists beyond workflow execution
|
|
180
|
+
- **Focus on permanence:** Use these nodes when you need data to survive restarts and be queryable later
|
|
181
|
+
|
|
182
|
+
## Common Pitfalls to Avoid
|
|
183
|
+
|
|
184
|
+
### Not Handling Duplicates
|
|
185
|
+
|
|
186
|
+
Without proper unique identifiers or upsert logic, you may create duplicate records. Use unique IDs or check for existing records before inserting.
|
|
187
|
+
|
|
188
|
+
### Ignoring Storage Limits
|
|
189
|
+
|
|
190
|
+
Each storage system has limits (row counts, API rates, file sizes). Design your workflow to work within these constraints or implement pagination/batching.
|
|
191
|
+
`;
|
|
192
|
+
getDocumentation() {
|
|
193
|
+
return this.documentation;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
exports.DataPersistenceBestPractices = DataPersistenceBestPractices;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { BuilderToolBase } from '../utils/stream-processor';
|
|
3
|
+
export declare const DocumentationType: {
|
|
4
|
+
readonly BEST_PRACTICES: "best_practices";
|
|
5
|
+
readonly NODE_RECOMMENDATIONS: "node_recommendations";
|
|
6
|
+
};
|
|
7
|
+
export declare const GET_DOCUMENTATION_TOOL: BuilderToolBase;
|
|
8
|
+
export declare function createGetDocumentationTool(): {
|
|
9
|
+
toolName: string;
|
|
10
|
+
displayTitle: string;
|
|
11
|
+
getCustomDisplayTitle?: (values: Record<string, unknown>) => string;
|
|
12
|
+
tool: import("@langchain/core/tools").DynamicStructuredTool<z.ZodObject<{
|
|
13
|
+
requests: z.ZodArray<z.ZodUnion<[z.ZodObject<{
|
|
14
|
+
type: z.ZodLiteral<"best_practices">;
|
|
15
|
+
techniques: z.ZodArray<z.ZodNativeEnum<{
|
|
16
|
+
readonly SCHEDULING: "scheduling";
|
|
17
|
+
readonly CHATBOT: "chatbot";
|
|
18
|
+
readonly FORM_INPUT: "form_input";
|
|
19
|
+
readonly SCRAPING_AND_RESEARCH: "scraping_and_research";
|
|
20
|
+
readonly MONITORING: "monitoring";
|
|
21
|
+
readonly ENRICHMENT: "enrichment";
|
|
22
|
+
readonly TRIAGE: "triage";
|
|
23
|
+
readonly CONTENT_GENERATION: "content_generation";
|
|
24
|
+
readonly DOCUMENT_PROCESSING: "document_processing";
|
|
25
|
+
readonly DATA_EXTRACTION: "data_extraction";
|
|
26
|
+
readonly DATA_ANALYSIS: "data_analysis";
|
|
27
|
+
readonly DATA_TRANSFORMATION: "data_transformation";
|
|
28
|
+
readonly DATA_PERSISTENCE: "data_persistence";
|
|
29
|
+
readonly NOTIFICATION: "notification";
|
|
30
|
+
readonly KNOWLEDGE_BASE: "knowledge_base";
|
|
31
|
+
readonly HUMAN_IN_THE_LOOP: "human_in_the_loop";
|
|
32
|
+
}>, "many">;
|
|
33
|
+
}, "strip", z.ZodTypeAny, {
|
|
34
|
+
type: "best_practices";
|
|
35
|
+
techniques: ("scheduling" | "chatbot" | "form_input" | "scraping_and_research" | "monitoring" | "enrichment" | "triage" | "content_generation" | "document_processing" | "data_extraction" | "data_analysis" | "data_transformation" | "data_persistence" | "notification" | "knowledge_base" | "human_in_the_loop")[];
|
|
36
|
+
}, {
|
|
37
|
+
type: "best_practices";
|
|
38
|
+
techniques: ("scheduling" | "chatbot" | "form_input" | "scraping_and_research" | "monitoring" | "enrichment" | "triage" | "content_generation" | "document_processing" | "data_extraction" | "data_analysis" | "data_transformation" | "data_persistence" | "notification" | "knowledge_base" | "human_in_the_loop")[];
|
|
39
|
+
}>, z.ZodObject<{
|
|
40
|
+
type: z.ZodLiteral<"node_recommendations">;
|
|
41
|
+
categories: z.ZodArray<z.ZodNativeEnum<{
|
|
42
|
+
readonly TEXT_MANIPULATION: "text_manipulation";
|
|
43
|
+
readonly IMAGE_GENERATION: "image_generation";
|
|
44
|
+
readonly VIDEO_GENERATION: "video_generation";
|
|
45
|
+
readonly AUDIO_GENERATION: "audio_generation";
|
|
46
|
+
}>, "many">;
|
|
47
|
+
}, "strip", z.ZodTypeAny, {
|
|
48
|
+
type: "node_recommendations";
|
|
49
|
+
categories: ("text_manipulation" | "image_generation" | "video_generation" | "audio_generation")[];
|
|
50
|
+
}, {
|
|
51
|
+
type: "node_recommendations";
|
|
52
|
+
categories: ("text_manipulation" | "image_generation" | "video_generation" | "audio_generation")[];
|
|
53
|
+
}>]>, "many">;
|
|
54
|
+
}, "strip", z.ZodTypeAny, {
|
|
55
|
+
requests: ({
|
|
56
|
+
type: "best_practices";
|
|
57
|
+
techniques: ("scheduling" | "chatbot" | "form_input" | "scraping_and_research" | "monitoring" | "enrichment" | "triage" | "content_generation" | "document_processing" | "data_extraction" | "data_analysis" | "data_transformation" | "data_persistence" | "notification" | "knowledge_base" | "human_in_the_loop")[];
|
|
58
|
+
} | {
|
|
59
|
+
type: "node_recommendations";
|
|
60
|
+
categories: ("text_manipulation" | "image_generation" | "video_generation" | "audio_generation")[];
|
|
61
|
+
})[];
|
|
62
|
+
}, {
|
|
63
|
+
requests: ({
|
|
64
|
+
type: "best_practices";
|
|
65
|
+
techniques: ("scheduling" | "chatbot" | "form_input" | "scraping_and_research" | "monitoring" | "enrichment" | "triage" | "content_generation" | "document_processing" | "data_extraction" | "data_analysis" | "data_transformation" | "data_persistence" | "notification" | "knowledge_base" | "human_in_the_loop")[];
|
|
66
|
+
} | {
|
|
67
|
+
type: "node_recommendations";
|
|
68
|
+
categories: ("text_manipulation" | "image_generation" | "video_generation" | "audio_generation")[];
|
|
69
|
+
})[];
|
|
70
|
+
}>, unknown, {
|
|
71
|
+
requests: ({
|
|
72
|
+
type: "best_practices";
|
|
73
|
+
techniques: ("scheduling" | "chatbot" | "form_input" | "scraping_and_research" | "monitoring" | "enrichment" | "triage" | "content_generation" | "document_processing" | "data_extraction" | "data_analysis" | "data_transformation" | "data_persistence" | "notification" | "knowledge_base" | "human_in_the_loop")[];
|
|
74
|
+
} | {
|
|
75
|
+
type: "node_recommendations";
|
|
76
|
+
categories: ("text_manipulation" | "image_generation" | "video_generation" | "audio_generation")[];
|
|
77
|
+
})[];
|
|
78
|
+
}, import("@langchain/langgraph").Command<unknown, Record<string, unknown>, string>>;
|
|
79
|
+
};
|