diff --git a/kits/flow-copilot/README.md b/kits/flow-copilot/README.md index fc7f122ec..2278fafd1 100644 --- a/kits/flow-copilot/README.md +++ b/kits/flow-copilot/README.md @@ -1,6 +1,6 @@ # Flow Copilot -Translates a plain-English AI agent requirement into a structured Lamatic Flow blueprint. +Translates a plain-English AI agent requirement into a structured Lamatic Flow blueprint, grounded in real Lamatic node documentation via RAG. ## What this does @@ -8,21 +8,32 @@ Give Flow Copilot a plain-English description of the AI agent you want to build - A one-sentence summary of the agent - A numbered, step-by-step suggested flow using real Lamatic node types -- The exact node sequence (e.g., `Chat Trigger → LLM Node → Condition Node → LLM Node`) +- The exact node sequence - Any assumptions it made, if the original request was ambiguous +- A structured JSON blueprint (flow name, trigger, nodes, node sequence, assumptions) for downstream use + +## Setup + +1. Deploy this kit's flows in Lamatic Studio: `flow-copilot` (the main conversational flow) and `ingest-node-docs` (the knowledge-base seeding flow). +2. Configure a Gemini API credential under **Settings → Connections** in your Lamatic project, and select it as the provider for each model config in this kit. +3. Run `ingest-node-docs` once before using Flow Copilot — this populates the `lamaticnodedocs` vector store that the RAG node queries. Re-run it any time you want to refresh or expand the indexed documentation. +4. Once both flows are deployed and the knowledge base is seeded, open the Chat Widget for `flow-copilot` to start using it. ## How to use 1. Open the deployed Chat Widget for this flow 2. Type a plain-English description of the AI agent you want to build 3. Read the returned blueprint — it lists the exact nodes to add and how to connect them in Lamatic Studio +4. Continue the conversation for follow-up refinements — Flow Copilot remembers prior turns ## Example **Input:** + > I want an agent that summarizes long PDF reports into 3 bullet points. **Output:** + > Summary: An agent that ingests a PDF, extracts its text, and generates a concise 3-bullet-point summary. > > Suggested Flow: @@ -34,10 +45,18 @@ Give Flow Copilot a plain-English description of the AI agent you want to build ## Flow structure -- **Chat Trigger** — receives the user's plain-English request -- **Generate Text (LLM Node)** — powered by Gemini, analyzes the request and produces the structured blueprint using a system prompt that enforces Lamatic's real node types and output format +- **Chat Widget** — receives the user's plain-English request +- **Memory Retrieve** — pulls prior conversation context for multi-turn continuity +- **RAG Node** — retrieves relevant Lamatic node documentation from a vector store to ground the blueprint in real node types and patterns +- **Generate Text (LLM Node)** — powered by Gemini, analyzes the request plus retrieved context and produces the structured blueprint +- **Generate JSON (Instructor LLM Node)** — parses the blueprint into structured fields: `flowName`, `trigger`, `nodes`, `nodeSequence`, `assumptions` +- **Memory Add** — stores the exchange for future conversation turns - **Chat Response** — returns the blueprint to the user +## Knowledge base + +A companion flow, `ingest-node-docs`, seeds a `lamaticnodedocs` vector store with Lamatic node reference documentation, including common flow patterns and best practices, which the RAG node queries at runtime. + ## Model used -Google Gemini (via Lamatic's Gemini API integration) +Google Gemini (`gemini-3.5-flash-lite`, via Lamatic's Gemini API integration) — chosen for low latency and near-zero reasoning overhead. diff --git a/kits/flow-copilot/flows/flow-copilot.ts b/kits/flow-copilot/flows/flow-copilot.ts index 66af6597c..90e62bb41 100644 --- a/kits/flow-copilot/flows/flow-copilot.ts +++ b/kits/flow-copilot/flows/flow-copilot.ts @@ -17,12 +17,50 @@ export const meta = { // -- Inputs -- export const inputs = { + "memoryRetrieveNode_859": [ + { + "name": "embeddingModelName", + "label": "Embedding Model Name", + "type": "model" + } + ], + "RAGNode_640": [ + { + "name": "vectorDB", + "label": "Database", + "type": "select" + }, + { + "name": "embeddingModelName", + "label": "Embedding Model Name", + "type": "model" + }, + { + "name": "generativeModelName", + "label": "Generative Model Name", + "type": "model" + } + ], "LLMNode_474": [ { "name": "generativeModelName", "label": "Generative Model Name", "type": "model" } + ], + "InstructorLLMNode_429": [ + { + "name": "generativeModelName", + "label": "Generative Model Name", + "type": "model" + } + ], + "memoryNode_302": [ + { + "name": "embeddingModelName", + "label": "Embedding Model Name", + "type": "model" + } ] }; @@ -32,11 +70,21 @@ export const references = { "default": "@constitutions/default.md" }, "prompts": { + "flow_copilot_ragnode_640_system_0": "@prompts/flow-copilot_ragnode-640_system_0.md", + "flow_copilot_ragnode_640_user_1": "@prompts/flow-copilot_ragnode-640_user_1.md", "flow_copilot_llmnode_474_system_0": "@prompts/flow-copilot_llmnode-474_system_0.md", - "flow_copilot_llmnode_474_user_1": "@prompts/flow-copilot_llmnode-474_user_1.md" + "flow_copilot_llmnode_474_user_1": "@prompts/flow-copilot_llmnode-474_user_1.md", + "flow_copilot_instructor_llmnode_429_system_0": "@prompts/flow-copilot_instructor-llmnode-429_system_0.md", + "flow_copilot_instructor_llmnode_429_user_1": "@prompts/flow-copilot_instructor-llmnode-429_user_1.md" }, "modelConfigs": { - "flow_copilot_llmnode_474_generative_model_name": "@model-configs/flow-copilot_llmnode-474_generative-model-name.ts" + "flow_copilot_memory_retrieve_node_859_embedding_model_name": "@model-configs/flow-copilot_memory-retrieve-node-859_embedding-model-name.ts", + "flow_copilot_ragnode_640_generative_model_name": "@model-configs/flow-copilot_ragnode-640_generative-model-name.ts", + "flow_copilot_ragnode_640_embedding_model_name": "@model-configs/flow-copilot_ragnode-640_embedding-model-name.ts", + "flow_copilot_llmnode_474_generative_model_name": "@model-configs/flow-copilot_llmnode-474_generative-model-name.ts", + "flow_copilot_instructor_llmnode_429_generative_model_name": "@model-configs/flow-copilot_instructor-llmnode-429_generative-model-name.ts", + "flow_copilot_memory_node_302_generative_model_name": "@model-configs/flow-copilot_memory-node-302_generative-model-name.ts", + "flow_copilot_memory_node_302_embedding_model_name": "@model-configs/flow-copilot_memory-node-302_embedding-model-name.ts" } }; @@ -87,6 +135,63 @@ export const nodes = [ } } }, + { + "id": "memoryRetrieveNode_859", + "type": "dynamicNode", + "position": { + "x": 0, + "y": 0 + }, + "data": { + "nodeId": "memoryRetrieveNode", + "values": { + "id": "memoryRetrieveNode_859", + "limit": "3", + "filters": "[]", + "nodeName": "Memory Retrieve", + "searchQuery": "{{triggerNode_1.output.chatMessage}}", + "memoryCollection": "flowcopilotconversationmemory", + "embeddingModelName": "@model-configs/flow-copilot_memory-retrieve-node-859_embedding-model-name.ts" + } + } + }, + { + "id": "RAGNode_640", + "type": "dynamicNode", + "position": { + "x": 0, + "y": 0 + }, + "data": { + "nodeId": "RAGNode", + "values": { + "limit": "3", + "filters": "", + "prompts": [ + { + "id": "187c2f4b-c23d-4545-abef-73dc897d6b7b", + "role": "system", + "content": "@prompts/flow-copilot_ragnode-640_system_0.md" + }, + { + "id": "187c2f4b-c23d-4545-abef-73dc897d6b7d", + "role": "user", + "content": "@prompts/flow-copilot_ragnode-640_user_1.md" + } + ], + "memories": "[]", + "messages": "[]", + "nodeName": "RAG", + "vectorDB": [ + "lamaticnodedocs" + ], + "certainty": "0.7", + "queryField": "{{triggerNode_1.output.chatMessage}}", + "embeddingModelName": "@model-configs/flow-copilot_ragnode-640_embedding-model-name.ts", + "generativeModelName": "@model-configs/flow-copilot_ragnode-640_generative-model-name.ts" + } + } + }, { "id": "LLMNode_474", "type": "dynamicNode", @@ -119,6 +224,64 @@ export const nodes = [ } } }, + { + "id": "InstructorLLMNode_429", + "type": "dynamicNode", + "position": { + "x": 0, + "y": 0 + }, + "data": { + "nodeId": "InstructorLLMNode", + "values": { + "tools": [], + "schema": "{\n \"type\": \"object\",\n \"properties\": {\n \"flowName\": {\n \"type\": \"string\",\n \"required\": true\n },\n \"trigger\": {\n \"type\": \"object\",\n \"properties\": {\n \"type\": {\n \"type\": \"string\",\n \"required\": true\n },\n \"config\": {\n \"type\": \"string\",\n \"required\": true\n }\n },\n \"additionalProperties\": true\n },\n \"nodes\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"type\": {\n \"type\": \"string\",\n \"required\": true\n },\n \"purpose\": {\n \"type\": \"string\",\n \"required\": true\n }\n },\n \"additionalProperties\": true\n }\n },\n \"nodeSequence\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"required\": true\n }\n },\n \"assumptions\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"required\": true\n }\n }\n }\n}", + "prompts": [ + { + "id": "187c2f4b-c23d-4545-abef-73dc897d6b7b", + "role": "system", + "content": "@prompts/flow-copilot_instructor-llmnode-429_system_0.md" + }, + { + "id": "187c2f4b-c23d-4545-abef-73dc897d6b7d", + "role": "user", + "content": "@prompts/flow-copilot_instructor-llmnode-429_user_1.md" + } + ], + "memories": "[]", + "messages": "[]", + "nodeName": "Generate JSON", + "attachments": "", + "generativeModelName": "@model-configs/flow-copilot_instructor-llmnode-429_generative-model-name.ts" + } + } + }, + { + "id": "memoryNode_302", + "type": "dynamicNode", + "position": { + "x": 0, + "y": 0 + }, + "data": { + "nodeId": "memoryNode", + "values": { + "id": "memoryNode_302", + "nodeName": "Memory Add", + "uniqueId": "{{triggerNode_1.output.sessionId}}", + "sessionId": "{{triggerNode_1.output.sessionId}}", + "memoryValue": [ + { + "role": "user", + "content": "User asked: {{triggerNode_1.output.chatMessage}} — Assistant responded: {{InstructorLLMNode_429.output.flowName}} | Trigger: {{InstructorLLMNode_429.output.trigger}} | Nodes: {{InstructorLLMNode_429.output.nodes}} | Sequence: {{InstructorLLMNode_429.output.nodeSequence}} | Assumptions: {{InstructorLLMNode_429.output.assumptions}}" + } + ], + "memoryCollection": "flowcopilotconversationmemory", + "embeddingModelName": "@model-configs/flow-copilot_memory-node-302_embedding-model-name.ts", + "generativeModelName": "@model-configs/flow-copilot_memory-node-302_generative-model-name.ts" + } + } + }, { "id": "responseNode_triggerNode_1", "type": "responseNode", @@ -130,7 +293,7 @@ export const nodes = [ "nodeId": "chatResponseNode", "values": { "id": "responseNode_triggerNode_1", - "content": "{{LLMNode_474.output.generatedResponse}}", + "content": "Here's your flow blueprint: {{InstructorLLMNode_429.output.flowName}}— Sequence: {{InstructorLLMNode_429.output.nodeSequence}}— Assumptions: {{InstructorLLMNode_429.output.assumptions}}— Trigger: {{InstructorLLMNode_429.output.trigger}}— Nodes: {{InstructorLLMNode_429.output.nodes}}", "nodeName": "Chat Response", "references": "", "webhookUrl": "", @@ -142,16 +305,48 @@ export const nodes = [ export const edges = [ { - "id": "triggerNode_1-LLMNode_474", - "source": "triggerNode_1", + "id": "RAGNode_640-LLMNode_474", + "source": "RAGNode_640", "target": "LLMNode_474", "sourceHandle": "bottom", "targetHandle": "top", "type": "defaultEdge" }, { - "id": "LLMNode_474-responseNode_triggerNode_1", + "id": "triggerNode_1-memoryRetrieveNode_859", + "source": "triggerNode_1", + "target": "memoryRetrieveNode_859", + "sourceHandle": "bottom", + "targetHandle": "top", + "type": "defaultEdge" + }, + { + "id": "memoryRetrieveNode_859-RAGNode_640", + "source": "memoryRetrieveNode_859", + "target": "RAGNode_640", + "sourceHandle": "bottom", + "targetHandle": "top", + "type": "defaultEdge" + }, + { + "id": "LLMNode_474-InstructorLLMNode_429", "source": "LLMNode_474", + "target": "InstructorLLMNode_429", + "sourceHandle": "bottom", + "targetHandle": "top", + "type": "defaultEdge" + }, + { + "id": "InstructorLLMNode_429-memoryNode_302", + "source": "InstructorLLMNode_429", + "target": "memoryNode_302", + "sourceHandle": "bottom", + "targetHandle": "top", + "type": "defaultEdge" + }, + { + "id": "memoryNode_302-responseNode_triggerNode_1-567", + "source": "memoryNode_302", "target": "responseNode_triggerNode_1", "sourceHandle": "bottom", "targetHandle": "top", diff --git a/kits/flow-copilot/model-configs/flow-copilot_instructor-llmnode-429_generative-model-name.ts b/kits/flow-copilot/model-configs/flow-copilot_instructor-llmnode-429_generative-model-name.ts new file mode 100644 index 000000000..802e0c20d --- /dev/null +++ b/kits/flow-copilot/model-configs/flow-copilot_instructor-llmnode-429_generative-model-name.ts @@ -0,0 +1,15 @@ +// Model config: instructor-llmnode-429 (InstructorLLMNode) + +export default { + "generativeModelName": [ + { + "type": "generator/text", + "params": {}, + "configName": "configA", + "model_name": "gemini-3.5-flash-lite", + "credentialId": "2aa4a1d8-2361-4774-8129-bb2187122eba", + "provider_name": "gemini", + "credential_name": "Gemini API Key" + } + ] +}; diff --git a/kits/flow-copilot/model-configs/flow-copilot_memory-node-302_embedding-model-name.ts b/kits/flow-copilot/model-configs/flow-copilot_memory-node-302_embedding-model-name.ts new file mode 100644 index 000000000..413887a8b --- /dev/null +++ b/kits/flow-copilot/model-configs/flow-copilot_memory-node-302_embedding-model-name.ts @@ -0,0 +1,12 @@ +// Model config: memory-node-302 (memoryNode) + +export default { + "embeddingModelName": { + "type": "embedder/text", + "params": {}, + "model_name": "gemini/gemini-embedding-001(3072)", + "credentialId": "2aa4a1d8-2361-4774-8129-bb2187122eba", + "provider_name": "gemini", + "credential_name": "Gemini API Key" + } +}; diff --git a/kits/flow-copilot/model-configs/flow-copilot_memory-node-302_generative-model-name.ts b/kits/flow-copilot/model-configs/flow-copilot_memory-node-302_generative-model-name.ts new file mode 100644 index 000000000..1e0c6386e --- /dev/null +++ b/kits/flow-copilot/model-configs/flow-copilot_memory-node-302_generative-model-name.ts @@ -0,0 +1,18 @@ +// Model config: memory-node-302 (memoryNode) + +export default { + "generativeModelName": [ + { + "type": "generator/text", + "params": {}, + "configName": "configA", + "model_name": "gemini/gemini-3.1-flash-lite-preview", + "credentialId": "2aa4a1d8-2361-4774-8129-bb2187122eba", + "provider_name": "gemini", + "credential_name": "Gemini API Key", + "additional_params": { + "thinking_level": "low" + } + } + ] +}; diff --git a/kits/flow-copilot/model-configs/flow-copilot_memory-retrieve-node-859_embedding-model-name.ts b/kits/flow-copilot/model-configs/flow-copilot_memory-retrieve-node-859_embedding-model-name.ts new file mode 100644 index 000000000..8d6e3b43e --- /dev/null +++ b/kits/flow-copilot/model-configs/flow-copilot_memory-retrieve-node-859_embedding-model-name.ts @@ -0,0 +1,12 @@ +// Model config: memory-retrieve-node-859 (memoryRetrieveNode) + +export default { + "embeddingModelName": { + "type": "embedder/text", + "params": {}, + "model_name": "gemini/gemini-embedding-001(3072)", + "credentialId": "2aa4a1d8-2361-4774-8129-bb2187122eba", + "provider_name": "gemini", + "credential_name": "Gemini API Key" + } +}; diff --git a/kits/flow-copilot/model-configs/flow-copilot_ragnode-640_embedding-model-name.ts b/kits/flow-copilot/model-configs/flow-copilot_ragnode-640_embedding-model-name.ts new file mode 100644 index 000000000..bbb2ce072 --- /dev/null +++ b/kits/flow-copilot/model-configs/flow-copilot_ragnode-640_embedding-model-name.ts @@ -0,0 +1,12 @@ +// Model config: ragnode-640 (RAGNode) + +export default { + "embeddingModelName": { + "type": "embedder/text", + "params": {}, + "model_name": "gemini/gemini-embedding-001(3072)", + "credentialId": "2aa4a1d8-2361-4774-8129-bb2187122eba", + "provider_name": "gemini", + "credential_name": "Gemini API Key" + } +}; diff --git a/kits/flow-copilot/model-configs/flow-copilot_ragnode-640_generative-model-name.ts b/kits/flow-copilot/model-configs/flow-copilot_ragnode-640_generative-model-name.ts new file mode 100644 index 000000000..109990bfc --- /dev/null +++ b/kits/flow-copilot/model-configs/flow-copilot_ragnode-640_generative-model-name.ts @@ -0,0 +1,15 @@ +// Model config: ragnode-640 (RAGNode) + +export default { + "generativeModelName": [ + { + "type": "generator/text", + "params": {}, + "configName": "configA", + "model_name": "gemini-3.5-flash-lite", + "credentialId": "2aa4a1d8-2361-4774-8129-bb2187122eba", + "provider_name": "gemini", + "credential_name": "Gemini API Key" + } + ] +}; diff --git a/kits/flow-copilot/prompts/flow-copilot_instructor-llmnode-429_system_0.md b/kits/flow-copilot/prompts/flow-copilot_instructor-llmnode-429_system_0.md new file mode 100644 index 000000000..75e60bab3 --- /dev/null +++ b/kits/flow-copilot/prompts/flow-copilot_instructor-llmnode-429_system_0.md @@ -0,0 +1 @@ +You are a flow architecture parser for Lamatic.ai. Your job is to read a natural-language description of a suggested flow and convert it into structured JSON. Always extract the trigger type, the ordered list of nodes with their purpose, the full node type sequence, and any assumptions mentioned. Be precise and consistent — do not add information that isn't present in the input text. \ No newline at end of file diff --git a/kits/flow-copilot/prompts/flow-copilot_instructor-llmnode-429_user_1.md b/kits/flow-copilot/prompts/flow-copilot_instructor-llmnode-429_user_1.md new file mode 100644 index 000000000..693fe6fcc --- /dev/null +++ b/kits/flow-copilot/prompts/flow-copilot_instructor-llmnode-429_user_1.md @@ -0,0 +1,2 @@ +Convert the following flow description into structured JSON: +{{LLMNode_474.output.generatedResponse}} \ No newline at end of file diff --git a/kits/flow-copilot/prompts/flow-copilot_llmnode-474_user_1.md b/kits/flow-copilot/prompts/flow-copilot_llmnode-474_user_1.md index 340c91ebc..a2176f550 100644 --- a/kits/flow-copilot/prompts/flow-copilot_llmnode-474_user_1.md +++ b/kits/flow-copilot/prompts/flow-copilot_llmnode-474_user_1.md @@ -1 +1,3 @@ -The user's request is: {{triggerNode_1.output.chatMessage}} \ No newline at end of file +The user's request is: {{triggerNode_1.output.chatMessage}} +Relevant Lamatic documentation retrieved for this request: +{{RAGNode_640.output.references}} \ No newline at end of file diff --git a/kits/flow-copilot/prompts/flow-copilot_ragnode-640_system_0.md b/kits/flow-copilot/prompts/flow-copilot_ragnode-640_system_0.md new file mode 100644 index 000000000..b4f8dc05c --- /dev/null +++ b/kits/flow-copilot/prompts/flow-copilot_ragnode-640_system_0.md @@ -0,0 +1,27 @@ +You are a helpful AI assistant. Always communicate in a clear, concise, and informative manner. +When citing any reference, follow **this exact format**: +* Enclose the reference number in square brackets. +* Immediately follow the number with the URL in parentheses. +* There should be **no space** between the closing square bracket and the opening parenthesis. +* Place the reference at the **end of the sentence** where the information is used. +* Only include the reference if a valid URL is available. +**Example format:** +Here is an example of how to onboard new sources [1](https://lamatic.ai/docs/nodes/crawler-node). + +**Reference Rules:** +Do not invent references. Only cite references when a valid, relevant URL is available. + +Do not include any text before or after the reference—place it cleanly at the end of the sentence. + +If multiple sentences require different citations, each must end with its own correctly formatted reference. + +Always use numbered references in sequential order (e.g., [1], [2], [3]…). + +If the same reference is cited again, reuse the original number. + +Apply this format only when referencing factual claims or external sources. + +**General URL Usage (non-reference purposes):** +You may provide URLs for tools, downloads, websites, examples, or navigation purposes without using the numbered reference format. + +In such cases, you may introduce the URL naturally in the sentence (e.g., “You can try this tool at https://example.com”). \ No newline at end of file diff --git a/kits/flow-copilot/prompts/flow-copilot_ragnode-640_user_1.md b/kits/flow-copilot/prompts/flow-copilot_ragnode-640_user_1.md new file mode 100644 index 000000000..706a89f9b --- /dev/null +++ b/kits/flow-copilot/prompts/flow-copilot_ragnode-640_user_1.md @@ -0,0 +1,3 @@ +Retrieve documentation relevant to the following AI agent request. Return the most relevant Lamatic node types, patterns, and best practices needed to build it. +Request: {{triggerNode_1.output.chatMessage}} +