Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions kits/flow-copilot/README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,39 @@
# 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
Comment thread
coderabbitai[bot] marked this conversation as resolved.

Give Flow Copilot a plain-English description of the AI agent you want to build (e.g., "I want a bot that reads customer emails and drafts replies"), and it returns:

- 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
Comment thread
coderabbitai[bot] marked this conversation as resolved.

## 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:
Expand All @@ -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.
207 changes: 201 additions & 6 deletions kits/flow-copilot/flows/flow-copilot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
]
Comment on lines +58 to 64

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

flow='kits/flow-copilot/flows/flow-copilot.ts'

ast-grep outline "$flow"
rg -n -C 6 \
  -e '"memoryNode_302"' \
  -e '"embeddingModelName"' \
  -e '"generativeModelName"' \
  "$flow"

Repository: Lamatic/AgentKit

Length of output: 4769


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== candidate files =="
git ls-files | rg '(^|/)(flows|package\.json|README|lamatic\.config|.*model-configs.*)$|memory-node-302|memory-retrieve-node-859' | sed -n '1,200p'

echo
echo "== flow package/config snippets =="
for f in kits/flow-copilot/package.json kits/flow-copilot/README.md kits/flow-copilot/lamatic.config.ts; do
  [ -f "$f" ] && { echo "--- $f"; sed -n '1,220p' "$f"; }
done

echo
echo "== model-config references =="
rg -n "memory-node-302|memory-retrieve-node-859|generative_model_name|embedding_model_name|generativeModelName|embeddingModelName" kits -S

Repository: Lamatic/AgentKit

Length of output: 50373


Mission abort on missing generative model for Memory Add.

memoryNode_302 references generativeModelName, but the flow inputs only expose embeddingModelName. If inputs drives Lamatic Studio model selection, the user cannot configure this model. Add the matching generative-model input or fix the node configuration to not require it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@kits/flow-copilot/flows/flow-copilot.ts` around lines 58 - 64, Update the
flow input configuration for memoryNode_302 so its generativeModelName
dependency is configurable: add a matching generativeModelName input alongside
embeddingModelName, or remove the node’s generative-model requirement if it is
not needed. Keep the model-selection configuration consistent between
memoryNode_302 and the exposed flow inputs.

};

Expand All @@ -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"
}
};

Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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"
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
},
{
"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",
Expand All @@ -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": "",
Expand All @@ -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",
Expand Down
Original file line number Diff line number Diff line change
@@ -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"
}
]
};
Original file line number Diff line number Diff line change
@@ -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"
}
};
Original file line number Diff line number Diff line change
@@ -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"
}
}
]
};
Original file line number Diff line number Diff line change
@@ -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"
}
};
Loading
Loading